Two movers declared this workload and disagreed. Live is universe's: the
Deployment carries apps.hanzo.ai/installation-id=hanzo-cd and managed-by=Helm,
CD Application hanzo-registry is Synced/Healthy, and its env matches
charts/app/values/hanzo/registry.yaml exactly — oci.hanzo.ai, S3 storage,
config from the registry-config ConfigMap.
The k8s/ lane could not have won even if it fired. `kubectl apply -f
k8s/deployment.yaml --dry-run=server` is rejected outright:
spec.selector: Invalid value: ... field is immutable
and the PVC it mounts, registry-data, does not exist in the cluster. It also
declared filesystem storage and a token service the live registry refuses.
So k8s/, the deploy workflow that applied it, and `make deploy` are gone.
Dockerfile and config.yml go with them: nothing builds that image and no pod
runs it — the live config is the registry-config ConfigMap. Keeping a second
copy of the config meant one live value and one that only looked live.
Fixes make status/logs, which selected app=registry — a label from the deleted
manifest that no running pod carries, so both returned nothing.
2.7 KiB
registry
The Hanzo fleet OCI registry: upstream registry:2 (Docker Distribution) with
Hanzo IAM token auth, S3-backed, served at oci.hanzo.ai and org-namespaced
oci.hanzo.ai/<org>/<app>. It holds container images and the Helm charts most CD
Applications pull on every sync, so it is load-bearing for fleet deploys.
oci.hanzo.ai and pkg.hanzo.ai (packages) are the only two artifact hosts.
The deployed spec lives in universe, not here
This repo carries no manifests. Everything that defines the running registry is
declared in hanzoai/universe and applied by Hanzo CD:
| Fact | Home in hanzoai/universe |
|---|---|
Deployment, Service, image digest, REGISTRY_AUTH_TOKEN_* |
charts/app/values/hanzo/registry.yaml (the fleet ApplicationSet) |
| Registry config — S3 storage, CORS | infra/k8s/registry/configmap.yaml → ConfigMap registry-config |
| Public routing | infra/k8s/ingress/routes.yaml, router oci-hanzo-ai |
| IAM app + push credential reconcile | infra/k8s/registry/register-app-job.yaml |
⚠ Auth is declared in the chart values as env, and env OVERRIDES the ConfigMap.
Adding an auth: block to the ConfigMap changes nothing; deleting the env arms
whatever the ConfigMap says instead. A token minted for one service name is
refused for another, and that failure reads as bad credentials rather than as
config.
Storage is hanzoai/s3 at s3.hanzo.svc:9000, bucket registry, with blob
redirects disabled — the S3 endpoint is cluster-internal, so a presigned redirect
would hand an external client an unresolvable host.
Auth
Client hits oci.hanzo.ai → 401 carrying the realm in WWW-Authenticate → client
fetches a token from
hanzo.id/v1/iam/registry/token?service=oci.hanzo.ai&scope=repository:<org>/<app>:pull,push,
basic-auth as the hanzo-registry IAM app → registry validates the JWT against
signing.crt, mounted from secret registry-signing-key as rootcertbundle.
The IAM-side hanzo-registry clientSecret and the KMS-distributed
registry-credentials docker secret must agree or every exchange 401s;
register-app-job.yaml in universe reconciles them non-destructively.
Make
lint (= test) parses every YAML this repo tracks. build and clean are
no-ops for the fleet verb set: the pod runs upstream registry:2, so there is no
image of ours to build and nothing to remove.
status, logs and restart read or roll the live workload. They do not
declare it — CD reconciles the spec from universe either way.
generate-cert writes signing.key/signing.crt: the key material the live
registry-signing-key secret is made from, not build output. Deleting the
private key orphans a live secret nobody can regenerate a match for.