publish kms.lux.cloud at the KMS that is actually running
The host resolved and answered 404 on every path, so Lux had a secret store and no way to reach it by name. Three separate reasons, each silent: DNS pointed kms.lux.cloud at 129.212.164.5 — hanzo-k8s — which has no ingress for that host. The Lux KMS is on lux-k8s (134.199.138.27). Repointed. The Ingress named namespace lux-kms, the Node-era KMS. Its Service still exists and has ZERO endpoints, so even a matching route would have found an empty backend. The live store is the Go one in lux-kms-go. cert-manager.io/cluster-issuer said agnost-dns01, which is not a ClusterIssuer on this cluster — only letsencrypt-prod is. No certificate was ever going to be issued. Now serving with a real certificate (CN=kms.lux.cloud, Let's Encrypt, to 2026-11-03): /v1/kms/health 200, /v1/kms/secrets 401 missing bearer token. Publishing it is safe BECAUSE it is API-only — `/` and `/admin` are 404, there is no console. That is the difference from cloud's embedded KMS, whose console had no authentication of its own and is why its brand hosts sit behind an admin-guard ForwardAuth. The dead Node-era manifests are gone rather than left to be re-applied: their kustomization set `namespace: lux-kms`, which would have pushed this very ingress back into the empty namespace. The ingress now lives beside the StatefulSet it fronts, and the image pin records what the cluster runs (v1.12.13, not v1.12.11). IN-CLUSTER CALLERS STILL USE THE SERVICE, and that is not an oversight: from inside the cluster the public host answers 404 (the hairpin does not reach the ingress), which is exactly why the two KMSSecrets that already named https://kms.lux.cloud were failing to sync. 42 of 51 CRs already use http://kms.lux-kms-go.svc.cluster.local; the strays now do too. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -1,99 +0,0 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kms
|
||||
namespace: lux-kms
|
||||
labels:
|
||||
app: kms
|
||||
component: backend
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: kms
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: kms
|
||||
component: backend
|
||||
spec:
|
||||
containers:
|
||||
- name: kms
|
||||
image: ghcr.io/hanzoai/kms:1.0.7
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: NODE_ENV
|
||||
value: production
|
||||
- name: SITE_URL
|
||||
value: https://kms.lux.cloud
|
||||
# Database (uses shared postgres in hanzo.svc)
|
||||
- name: DB_CONNECTION_URI
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: kms-db-credentials
|
||||
key: connection-uri
|
||||
# Redis
|
||||
- name: REDIS_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: kms-db-credentials
|
||||
key: redis-url
|
||||
# Encryption
|
||||
- name: ENCRYPTION_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: kms-encryption
|
||||
key: encryption-key
|
||||
- name: AUTH_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: kms-encryption
|
||||
key: auth-secret
|
||||
# JWT
|
||||
- name: JWT_AUTH_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: kms-encryption
|
||||
key: jwt-auth-secret
|
||||
# Branding
|
||||
- name: BRAND
|
||||
value: lux
|
||||
- name: DEFAULT_ORG_NAME
|
||||
value: Lux Network
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 1Gi
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/status
|
||||
port: http
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/status
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: kms-ingress
|
||||
namespace: lux-kms
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: agnost-dns01
|
||||
spec:
|
||||
ingressClassName: ingress
|
||||
tls:
|
||||
- hosts:
|
||||
- kms.lux.cloud
|
||||
secretName: kms-tls
|
||||
rules:
|
||||
- host: kms.lux.cloud
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: kms
|
||||
port:
|
||||
number: 80
|
||||
@@ -1,10 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: lux-kms
|
||||
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- deployment.yaml
|
||||
- services.yaml
|
||||
- ingress.yaml
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: lux-kms
|
||||
labels:
|
||||
app: lux-kms
|
||||
component: secrets
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: kms
|
||||
namespace: lux-kms
|
||||
labels:
|
||||
app: kms
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: kms
|
||||
@@ -55,7 +55,7 @@ spec:
|
||||
- name: ghcr-luxfi
|
||||
containers:
|
||||
- name: kms
|
||||
image: ghcr.io/luxfi/kms:v1.12.11
|
||||
image: ghcr.io/luxfi/kms:v1.12.13
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- { name: http, containerPort: 8080, protocol: TCP }
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
# kms.lux.cloud — Lux's OWN secret store, published under Lux's own name.
|
||||
#
|
||||
# The brand KMS hosts were removed once because a single path-keyed store sat
|
||||
# behind them, so a brand host served the HANZO store under another brand's
|
||||
# name. That is no longer the shape: Lux runs its own KMS on its own cluster
|
||||
# (ns lux-kms-go, ghcr.io/luxfi/kms), so this host resolves Lux secrets and
|
||||
# nothing else. White-label by ownership, not by a header.
|
||||
#
|
||||
# Two things this file used to get wrong, both of which fail silently:
|
||||
#
|
||||
# namespace lux-kms — the Node-era KMS. Its Service still exists and has ZERO
|
||||
# endpoints, so the ingress would have resolved and then failed on an empty
|
||||
# backend. The live store is the Go one, in lux-kms-go.
|
||||
#
|
||||
# cluster-issuer agnost-dns01 — no such ClusterIssuer on this cluster; only
|
||||
# letsencrypt-prod exists. No certificate was ever going to be issued, so the
|
||||
# host would have served the default cert and failed TLS verification.
|
||||
#
|
||||
# API ONLY, which is what makes publishing it safe. This image serves no
|
||||
# console: `/` and `/admin` are 404, and /v1/kms/secrets answers 401
|
||||
# `missing bearer token`. That is the difference from cloud's embedded KMS,
|
||||
# whose console had no authentication of its own and is the reason its brand
|
||||
# hosts sit behind an admin-guard ForwardAuth.
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: kms-ingress
|
||||
namespace: lux-kms-go
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
# Both spellings: this fleet's controller reads the annotation, while the
|
||||
# class field is what kubectl and every other reader show.
|
||||
kubernetes.io/ingress.class: ingress
|
||||
spec:
|
||||
ingressClassName: ingress
|
||||
tls:
|
||||
- hosts:
|
||||
- kms.lux.cloud
|
||||
secretName: kms-lux-cloud-tls
|
||||
rules:
|
||||
- host: kms.lux.cloud
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: kms
|
||||
port:
|
||||
number: 80
|
||||
Reference in New Issue
Block a user