It opens with the five required variables, then what production
usually sets (proxy header, PostgreSQL, mail relay, OTP), then every
optional setting commented out at its default. It lists exactly the 51
variables the code reads.
Sample entries from production show:
- customers live in ou=customer (singular), not ou=customers
- customers have gidNumber 10004 and staff 10002; uidNumbers are in
the 10000s
- staff entries list organizationalPerson and person explicitly
- the servers serve ldaps:// on port 636
The app reads all of these from settings, so its behaviour is
unchanged; the customer entry it creates already matches production
attribute for attribute. The defaults and test setups were wrong:
env.sample, the Kubernetes ConfigMap (now ldaps:// without StartTLS,
gid 10004, start uid 10000), dev/env.dev and the dev LDAP seed now
mirror production. The made-up ou=groups is gone. The tests take the
customer DN and gidNumber from settings instead of hardcoding them.
The deployment guide now notes that the app is dual-stack and tested on
an IPv6-only cluster, shows how to mount a private LDAP CA and set
LDAP_CA_FILE, and explains how to run the kind dev overlay as an
IPv6-only cluster.
deploy/k8s/dev runs the base with 2 replicas alongside throwaway
services: two independent OpenLDAP servers (the dev image), PostgreSQL
18 and Mailpit.
deploy/k8s/dev/e2e.sh checks a running deployment: both probes,
registration with the activation mail sent over SMTP (and no password
in it), activation, login, and login and readiness while ldap1 is
scaled to zero. All checks pass.
A kustomize base with a Deployment (2 replicas, migrate_locked init
container, liveness, readiness and startup probes, uid 10001 with a
read-only root filesystem, all capabilities dropped, RuntimeDefault
seccomp, no service account token, resource requests and limits), plus
a Service, an Ingress for account.ungleich.ch, a PodDisruptionBudget
and a ConfigMap with every non-secret setting.
The Secret is not part of the base, so credentials stay out of git;
secret.example.yaml and the README show how to create it. The README
also lists what the cluster must provide and what to confirm before
going live (StartTLS on the LDAP servers, HSTS).