# Which Problems Are Solved
Image versions in the example env, used in the docker quickstart, were
outdated.
# How the Problems Are Solved
Update all image versions.
# Which Problems Are Solved
- Zitadel-api failed to reach PostgreSQL with connection refused,
Zitadel v4.11 does not implement a DSN field.
# How the Problems Are Solved
- Updated ZITADEL_VERSION variable in env.example to v4.13.0
Co-authored-by: Livio Spring <9405495+livio-a@users.noreply.github.com>
# Which Problems Are Solved
After merging #11968 and rechecking the dependabot alerts there are
still some issues leftover.
# How the Problems Are Solved
This pr makes overrides for vulnerable transitive depdencies to force
update to safe versions.
It also upgrades the next.js version in the docs and I also ran `pnpm
update` once more.
# Additional Changes
Removed the mochaawesome dependency is this is not really needed and
seems unmaintained.
# Additional Context
- Precursor: #11968
# Which Problems Are Solved
This pr updates major and minor dependencies and is the first step on
getting our dependabot alerts cut down.
# How the Problems Are Solved
Depedency updates across the board eg:
- Upgrade Angular to v21
- Upgrade next.js to v16.2
- Upgrade tailwind to v4 in the login
- Upgrade vitest to v4 in the login
This is an uncompleted list refer to the changed files for a full
overview of all the updates.
# Additional Changes
Migrated all control flow in the console to the modern control flow
syntax.
Fixed the dependsOn setting for the @zitadel/login:test-unit nx target.
# Additional Context
- Closes https://github.com/zitadel/zitadel/issues/11274
---------
Co-authored-by: Max Peintner <peintnerm@gmail.com>
# Which Problems Are Solved
The login v2 container has no way to verify upstream Zitadel API
connectivity before accepting traffic. The existing `/healthy` endpoint
always returns 200 regardless of whether the backend is reachable. This
means Kubernetes routes user traffic to pods that cannot actually serve
login requests, causing silent failures where the root layout swallows
gRPC errors and renders pages with default settings.
# How the Problems Are Solved
A new `/ui/v2/login/ready` endpoint creates a gRPC client using the same
auth and transport path as real requests, calls
`SettingsService.getGeneralSettings()`, and returns `200 OK` on success
or `503 Service unavailable` on failure. This verifies both network
connectivity and authentication credentials to the upstream Zitadel API.
Kubernetes supports readiness probes natively, so this endpoint can be
configured as a readiness probe to gate traffic until the login
container can connect to Zitadel. Docker Compose does not have a
readiness probe concept, so the compose healthcheck and
`healthcheck.mjs` default remain unchanged and continue using
`/healthy`.
The Docker HEALTHCHECK in the Dockerfile has been updated to use
`/ready` so that the image-level health status reflects actual upstream
connectivity. This will also allow us to simplify the Helm chart by
dropping the `wait4x` init containers that currently poll the Zitadel
API before starting the login pod, since the readiness probe makes them
redundant.
# Additional Changes
The `/ready` endpoint has been added to the OTEL HTTP instrumentation
ignore list to avoid noisy probe traces. Unit tests, a wiring spec
integration test, and an OTEL span filtering test have been added for
the new endpoint. The `# TODO: Check healthy, not ready` comment has
been removed from the Dockerfile. The `/healthy` endpoint is kept as-is
for liveness probes.
# Additional Context
The Helm chart changes to use `/ready` for readiness and startup probes
and to remove the `wait-for-zitadel` init container will be done in a
follow-up PR in the `zitadel-charts` repository.
Replaces the single-file `docker-compose.yaml` quickstart with a
production-aware, Traefik-based compose pack in `deploy/compose/`. The
pack covers the full arc from a 2-minute localhost quickstart to a
hardened homelab or semi-production deployment.
### What's in the pack
**Stack**: Traefik (proxy) → ZITADEL API (Go `:8080`) + ZITADEL Login
(Next.js `:3000`) → PostgreSQL
All HTTP/gRPC routing is handled by Traefik via Docker labels — no
manual proxy config needed. The Login V2 UI is enabled by default. Login
URLs are derived automatically from `ZITADEL_DOMAIN`,
`ZITADEL_EXTERNALPORT`, and `ZITADEL_PUBLIC_SCHEME` — no separate URL
variables needed.
**Compose files**
| File | Purpose |
|------|---------|
| `docker-compose.yml` | Base stack — works standalone. Uses explicit
`name: zitadel` network for reliable Traefik service discovery. |
| `docker-compose.mode-letsencrypt.yml` | TLS overlay: ACME HTTP
challenge |
| `docker-compose.mode-external-tls.yml` | TLS overlay: upstream LB/CDN
terminates TLS. Uses `forwardedHeaders.trustedIPs` (configurable via
`TRAEFIK_TRUSTED_IPS`) instead of `insecure=true`. |
| `docker-compose.mode-local-tls.yml` | TLS overlay: self-signed certs
for LAN |
| `docker-compose.prodlike.yml` | Splits init / setup / start for
controlled upgrades |
| `docker-compose.test.yml` | CI overlay: swaps images to locally-built
`:local` tags |
**Optional profiles**: `cache` (Redis), `observability` (OpenTelemetry
Collector)
### Build infra
- New `@zitadel/api:pack` and `@zitadel/login:pack` Nx targets build
local Docker images (`zitadel/zitadel:local`,
`zitadel/zitadel-login:local`) for use in CI and local testing
- `apps/api/Dockerfile` now accepts a `BINARY` build arg so local and
release builds share the same image
### Testing
- New `@zitadel/compose` Nx project with targets: `test-config`
(validates all overlay combinations using `--quiet`), `test-run` (starts
full stack with local images), `test-e2e` (Playwright wiring + protocol
matrix tests through Traefik), `test-full` (end-to-end: build → start →
test → teardown), `stop`
- **`@zitadel/compose` is explicitly excluded from `nx affected` in CI
for now** — the full stack smoke test requires a Docker daemon and
significant resources. The intent is to add a dedicated
`compose_smoke_test` CI job in a follow-up. The targets can be run
locally with `pnpm nx run @zitadel/compose:test-full`.
### Documentation
- **`compose.mdx`**: Complete rewrite with a staged structure (Stage 1
Quickstart → Stage 2 Homelab → Stage 3 Beyond Compose). Documents TLS
modes, profiles, secrets hardening, ExternalDomain/Port/Secure
invariant, upgrades, and the path to Kubernetes
- **New `requirements.mdx`**: Lists supported PostgreSQL versions
(14–18), Redis (standalone), Docker Compose v2.x, and reverse proxy h2c
requirements
- **`reverse_proxy.mdx`**: Added intro covering h2c requirements, TLS
modes table, and Login UI routing split
- **`troubleshooting.mdx`**: New sections for container restarts on
upgrade, FIRSTINSTANCE env vars not taking effect, and diagnosing
unhealthy containers
- **`caddy/index.mdx`**: Known issue and workaround for the `TE:
trailers` header hang
- Removed the old
`apps/docs/content/self-hosting/deploy/docker-compose.yaml` embedded in
the docs
### Breaking change
The old `apps/docs/content/self-hosting/deploy/docker-compose.yaml` file
is deleted. The getting-started docs page
(`/self-hosting/deploy/compose`) now points to the new pack via a `curl
| tar` download command.
---
### Checklist
- [x] `deploy/compose/` smoke test passes end-to-end locally (`pnpm nx
run @zitadel/compose:test-full`)
- [x] Docs build passes (`pnpm nx run @zitadel/docs:build`)
- [ ] Follow-up issue created to add `compose_smoke_test` CI job
---------
Co-authored-by: Mridang Agarwalla <mridang@zitadel.com>
* fix: compatability for cockroach v22.1
* update cr version in docs and compose
* bind dev cockroach to 127.0.0.1
* Revert "bind dev cockroach to 127.0.0.1"
This reverts commit 1c7c6304ae.
* remove --listen-addr flag
* use v2.0.0-v2-alpha.16
* use v2.0.0-v2-alpha.17
Co-authored-by: Elio Bischof <eliobischof@gmail.com>