Files
universe/k8s/bootnode/deployment-api.yaml
zeekayandHanzo Dev 30e162ad7b kms.lux.cloud is the brand host; kms.lux.network is retired
The .network host was retired 2026-07-27 and no longer resolves at all, so every
reference to it named an address that cannot answer. The brand host is .cloud,
matching kms.zoo.cloud and the rest of the white-label convention.

Left alone deliberately, because rewriting them would invert what they say: the
LLM.md line that RECORDS the retirement, the e2e spec that ASSERTS
kms.lux.network must not resolve, and the recorded applies + cluster backups,
which are faithful accounts of what was applied and are not config.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-05 08:17:04 -07:00

210 lines
6.7 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: bootnode-api
namespace: bootnode
labels:
app: bootnode-api
component: api
brand: lux
spec:
# Single writer: Base/SQLite on one RWO PVC. One replica owns the volume;
# durability/restore come from the Litestream → S3 stream, not extra writers.
replicas: 1
selector:
matchLabels:
app: bootnode-api
strategy:
# Recreate (not RollingUpdate): a RWO volume can't be held by an old and a
# new pod at once, so tear down before bringing up to avoid Multi-Attach.
type: Recreate
template:
metadata:
labels:
app: bootnode-api
component: api
brand: lux
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8000"
prometheus.io/path: "/metrics"
spec:
serviceAccountName: bootnode-api
imagePullSecrets:
- name: ghcr-bootnode-pull
# Single-writer SQLite on a RWO PVC: pin one pod per node and never run
# two writers against the same volume. (Durability/HA come from the
# Litestream → S3 stream, not from multiple replicas.)
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: bootnode-api
topologyKey: kubernetes.io/hostname
initContainers:
# Restore the SQLite DB from S3 if the PVC is empty (fresh pod / new
# volume). No-op when the DB already exists locally — Litestream exits 0.
- name: litestream-restore
image: litestream/litestream:0.3.13
args:
- restore
- -if-db-not-exists
- -if-replica-exists
- -config
- /etc/litestream/litestream.yml
- /data/bootnode/bootnode.db
env:
- name: LITESTREAM_ACCESS_KEY_ID
value: hanzo
- name: LITESTREAM_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: hanzo-s3-secret
key: password
volumeMounts:
- name: data
mountPath: /data/bootnode
- name: litestream-config
mountPath: /etc/litestream
readOnly: true
containers:
- name: api
# Kustomize `images:` (kustomization.yaml) pins the real tag; this is
# the same platform.hanzo.ai-published ref kept in sync for clarity.
image: ghcr.io/bootnode/bootnode:d6a293fb5f9398cc2ec571f6527e0948954dc21e-amd64-api
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8000
protocol: TCP
env:
- name: APP_ENV
value: production
# Canonical store: Base/SQLite on the mounted PVC (durability via the
# Litestream → S3 replica). No Postgres dependency.
- name: DATABASE_URL
value: sqlite+aiosqlite:////data/bootnode/bootnode.db
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: redis-url
- name: DATASTORE_URL
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: datastore-url
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: jwt-secret
- name: API_KEY_SALT
valueFrom:
secretKeyRef:
name: bootnode-secrets
key: api-key-salt
# Lux IAM integration
- name: IAM_URL
value: https://lux.id
- name: IAM_ORG
value: lux
# KMS integration
- name: HANZO_KMS_URL
value: https://kms.lux.cloud
- name: HANZO_KMS_ORG
value: lux
- name: HANZO_KMS_PROJECT
value: bootnode
- name: HANZO_KMS_ENV
value: production
- name: HANZO_KMS_CLIENT_ID
valueFrom:
secretKeyRef:
name: hanzo-kms-secrets
key: client-id
optional: true
- name: HANZO_KMS_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: hanzo-kms-secrets
key: client-secret
optional: true
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: "2"
memory: 2Gi
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
volumeMounts:
- name: tmp
mountPath: /tmp
- name: data
mountPath: /data/bootnode
# Litestream sidecar: continuously replicates the SQLite WAL to the
# Hanzo S3 (SeaweedFS) so the DB survives pod/volume loss.
- name: litestream
image: litestream/litestream:0.3.13
args:
- replicate
- -config
- /etc/litestream/litestream.yml
env:
- name: LITESTREAM_ACCESS_KEY_ID
value: hanzo
- name: LITESTREAM_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: hanzo-s3-secret
key: password
resources:
requests:
cpu: 25m
memory: 32Mi
limits:
cpu: 200m
memory: 128Mi
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
volumeMounts:
- name: data
mountPath: /data/bootnode
- name: litestream-config
mountPath: /etc/litestream
readOnly: true
volumes:
- name: tmp
emptyDir: {}
- name: data
persistentVolumeClaim:
claimName: bootnode-api-data
- name: litestream-config
configMap:
name: bootnode-litestream