Add ZITADEL_ORG_NAME and ZITADEL_ADMIN_{FIRST,LAST,DISPLAY}_NAME (defaults
keep the previous ZITADEL naming for dev); the prod example uses
Iker Demo / admin@ikerdemo.cat.
Zitadel v4 redirects every sign-in to /ui/v2/login, which is served by a
separate container (zitadel-login) that this stack didn't run, so logging
in on a fresh instance ended in a 404.
- Add zitadel-login, with its own service account (login-client) whose
PAT Zitadel writes to a volume only that container mounts.
- Configure the Login V2 base URL (ZITADEL_LOGIN_BASE_URL): its own port
in dev, same hostname as Zitadel behind the edge in prod.
- Pin zitadel and zitadel-login to v4.19.1 and add healthchecks.
- Run Zitadel as root, as Zitadel's own compose does, so it can write the
PATs into root-owned mounts (the Linux bind mount and the new volume).
- Route /ui/v2/login on the auth vhost to the login container and drop
the no-op grpc_set_header.
- Document the extra steps for an instance created before this.
RabbitMQ stores its data under rabbit@<hostname>, and the hostname
changed with every recreated container, so an image update or an .env
change came up with an empty broker. Pin it to `rabbitmq` and document
how to carry the definitions over on an existing deployment.
Every project shares infra-net, where a generic service name like `api`
resolves to every container that has it, round-robin, across projects.
The edge now proxies to container names (musify-api, infra-zitadel, ...).
- Unknown hostnames and direct IP access no longer land on the first
vhost (Gitea): port 80 closes the connection, except for ACME
challenges, and port 443 refuses the handshake.
- Mozilla intermediate ciphers (forward secrecy only, no CBC), session
cache, no session tickets, and HSTS with a short max-age for now.
- Set X-Forwarded-For to the client address instead of appending to
whatever the client sent.
- Pin seaweedfs (4.47), jaeger (1.76.0), certbot (v5.8.0) and pgadmin
(9.18) instead of :latest.
- Rotate container logs (json-file, 3 x 10 MB) in every stack.
- Cap Jaeger's in-memory storage at 100k traces and add a healthcheck.
- Publish dev ports on 127.0.0.1 (DEV_BIND_ADDRESS) so the dev
credentials aren't reachable from the LAN.
- Fix the prod command in compose.yml's header, the README's note on who
writes the admin PAT, and the certbot command's line breaks.
Every project used the Postgres superuser, the RabbitMQ administrator, an
admin S3 identity and the Zitadel instance-admin PAT, so any one of them
could read or change the others' data.
A new one-shot, `provision` (runs on every `up`, idempotent), gives each
project in x-projects its own:
- Postgres role, owner of its database. No database is open to PUBLIC
anymore, so a role can only connect to its own. An existing database
and everything in it is handed over to the project's role.
- RabbitMQ user, with permissions on its own vhost only.
- Zitadel service account, PROJECT_OWNER of its own project only; its
PAT is written to zitadel/.output/<project>/ for that project's
zitadel-init to mount instead of the admin PAT.
SeaweedFS renders one S3 identity per project, limited to its bucket, and
refuses to start with a clear message on a malformed or repeated key.
The admin accounts stay with this stack. postgres-init is gone: provision
creates the databases. *.sh files are checked out with LF so they run in
the Linux containers from a Windows checkout.
Its OIDC login isn't implemented yet, but it's meant to use the same
Zitadel as Musify and Ping. Provision its Zitadel project and service
account now, so its future zitadel-init only has to create its apps.
Document that every project shares one Zitadel organization: one account
per person across all projects, with single sign-on between them.
NotS1mp
merged commit a24f04187c into master2026-09-24 15:21:57 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Add ZITADEL_ORG_NAME and ZITADEL_ADMIN_{FIRST,LAST,DISPLAY}_NAME (defaults keep the previous ZITADEL naming for dev); the prod example uses Iker Demo / admin@ikerdemo.cat.