Files
universe/deploy
..

deploy — the fleet, declared

Every service in this cluster is one values file:

deploy/<namespace>/<name>.yaml

That is the whole inventory. Adding a service is adding a file; there is no second list to keep in step with it.

Each file is values for one shared chart, pulled by version:

oci://oci.hanzo.ai/charts/app:0.1.0

The chart is referenced, never copied. A copy per repository is how two fleets end up with two definitions of the same thing and neither one is wrong.

helm template <name> oci://oci.hanzo.ai/charts/app --version 0.1.0 \
  -n <namespace> -f deploy/<namespace>/<name>.yaml

These files were generated from what is RUNNING

Not from the manifests in k8s/. Those were applied by hand over a long period and their currency is unknown — some are ahead of the cluster, some behind, some describe things that were deleted. The running fleet is the only statement of what is true, so it is what was read.

That makes k8s/ and deploy/ disagree on purpose. The disagreement is a drift audit waiting to be done, not a bug to paper over.

Verifying, before changing anything

# regenerate from live
python3 <universe>/charts/app/hack/live2values.py --context <ctx> --out deploy

# render every file and diff it against the live object
python3 <universe>/charts/app/hack/diff-live.py --context <ctx> --values deploy

The gate grades what it finds:

  • BREAKING — the apiserver would refuse the apply. Only a workload's spec.selector qualifies; it is immutable.
  • DRIFT — live differs from the file. Someone changed one of them.
  • BENIGN — an intended consequence of moving to the chart.

Current state for this cluster: BREAKING = 0. Every workload here can be adopted in place.

selectorLabels — why most files have one

spec.selector cannot be changed after a workload is created. Most services here select on app: <name>, not the chart's app.kubernetes.io/name + instance, so each file records the selector its workload already carries. Without that the chart would emit its own, and the apply would be refused.

It is the selector only — the full label set on metadata is still the chart's, so an adopted workload gains the standard labels for everything that reads them without selecting on them.

What is NOT here

Chain CRs (LuxChain, LuxNetwork, LuxIndexer, LuxGateway, LuxMPC) are not services and have their own controllers. They stay in k8s/.

Secrets are not here and never will be. The chart has no way to carry a secret value: kmsSecrets names a path in KMS and the operator syncs it. The placeholder Secret manifests in k8s/ that say CHANGE_ME_VIA_KMS are the older pattern and should become KMSSecret resources.

Deploying

There is no CD in this repository yet, which is why k8s/ drifted in the first place. applicationset.yaml here is ready to apply once this cluster runs one. It deliberately has no automated block: the chart adds labels to the pod template, and a pod template change is a rollout, so switching it on would restart the whole fleet at once. Services move over one at a time.

lux-system/s3 is NOT declared here, deliberately

There was a lux-system/s3.yaml, generated by hack/live2values.py from Deployment/s3. Both halves of what it described were wrong:

  • Deployment/s3 is a 0-replica husk. Nothing has run from it in 57 days.
  • Service/s3 selects app: seaweedfs and its single endpoint is seaweedfs-0, a StatefulSet. The generated file declared selectorLabels: {app: s3}, so a sync would have repointed that Service at a selector matching zero pods and taken S3 down for every in-cluster consumer. It also declared an Ingress for s3.lux.network, a host with no working record today (curl 000).

So the file was deleted rather than corrected: correcting it means picking ONE name for the thing. ghcr.io/hanzoai/s3 IS the SeaweedFS fork, so s3 is the honest name and seaweedfs is the leftover — but renaming a StatefulSet is a recreate against its bound volume, which is a sequenced change against live storage and not a values edit. Until that lands, lux-system S3 is visibly outside CD, which is the truthful state; a values file that claims otherwise is worse than an absence.