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>
8.1 KiB
ZITADEL Monorepo Guide for AI Agents
Mission & Context
ZITADEL is an open-source Identity Management System (IAM) written in Go and Angular/React. It provides secure login, multi-tenancy, and audit trails.
Read Order
- Read this file first.
- Read the nearest scoped
AGENTS.mdfor the area you edit. - If multiple scopes apply, use the most specific path.
Repository Structure Map
apps/: Consumer-facing web applications.login: Next.js authentication UI. Seeapps/login/AGENTS.md.docs: Fumadocs documentation app. Seeapps/docs/AGENTS.md.api: Backend Nx app target. Seeapps/api/AGENTS.md.
console/: Angular Management Console. Seeconsole/AGENTS.md.internal/: Backend domain and service logic. Seeinternal/AGENTS.md.proto/: API definitions. Seeproto/AGENTS.md.packages/: Shared TypeScript packages. Seepackages/AGENTS.md.tests/functional-ui/: Cypress functional UI tests. Seetests/functional-ui/AGENTS.md.
Technology Stack & Conventions
- Orchestration: Nx is used for build and task orchestration.
- Package Manager: pnpm.
- Backend:
- Go Version Source of Truth: Inspect
go.modbefore Go work (goand optionaltoolchaindirectives). - Communication: For V2 APIs, connectRPC is the primary transport. gRPC and HTTP/JSON endpoints are also supported.
- Pattern: The backend is transitioning to a relational design. Events are still persisted in a separate table for history/audit, but events are not the system of record.
- Go Version Source of Truth: Inspect
- Frontend:
- Console: Angular + RxJS.
- Login/Docs: Next.js + React.
ZITADEL Domain & Multi-Tenancy Logic
1. Hierarchy & Ownership
ZITADEL follows a strict hierarchical containment model. When generating code, logic, or translations, adhere to this structure:
- System (Installation): The entire ZITADEL deployment. Global settings are applied through runtime configuration files or environment variables. See
cmd/defaults.yaml. - Instance (The "Identity System"):
- Definition: A logical partition/virtual tenant. It is a "System inside a System."
- Isolation: Data and settings are strictly isolated between instances.
- Translation Rule: NEVER translate as "Example" or "Case." Use technical terms like "Tenant," "Environment," or the local equivalent of "Logical System Entity."
- Organization: A group within an Instance. It owns Users, Projects, and Roles.
- Project: A collection of Applications and Auth Policies within an Org.
2. Permission Scoping (The "Administrative" Context)
- System User: Manages the entire Installation and creates Instances over the system API.
- Instance Admin: Manages Instance-wide policies (Password complexity, Identity Providers, Organizations).
- Organization Admin: Manages users and access within a specific Organization.
3. Language & Tone Guidelines
- Avoid Ambiguity: When referring to an 'Instance', the context is always infrastructure/tenancy.
- Technical Precision: In UI strings, prefer clarity over brevity if "Instance" is likely to be misinterpreted in the target language.
4. Technical Glossary & Localization Mapping
| Language | Technical Term (SaaS/Cloud) | Why this term? | "Avoid this (The ""Example"" Trap)" |
|---|---|---|---|
| Chinese (Simplified) | 实例 (Shílì) | Standard for a cloud resource/entity. | 例子 (Lìzi) |
| Japanese | インスタンス (Insutansu) | Katakana transliteration; industry standard. | 例 (Rei) |
| Korean | 인스턴스 (Inseuteonseu) | Hangul transliteration; industry standard. | 예 (Ye) |
| German | Instanz | Matches English but implies a technical occurrence. | Beispiel |
| French | Instance | "Standard but often requires ""de ZITADEL"" for clarity." | Exemple |
| Spanish | Instancia | Technical entity in software architecture. | Ejemplo |
| Portuguese | Instância | Standard technical terminology. | Exemplo |
| Russian | Инстанс (Instans) | Modern SaaS jargon (transliterated). | Пример (Primer) |
Translation Guardrails
If a translation is requested for a language not listed above, follow these priority rules for the word 'Instance':
- Priority 1 (Transliteration): Use the phonetic transliteration into the local script (common in Japanese/Korean/Russian).
- Priority 2 (System Entity): Use a term that implies a "running process" or "logical environment."
- Priority 3 (Tenant): If 'Instance' is ambiguous, use the local word for 'Tenant' (e.g., 租户 in Chinese).
- Strict Ban: NEVER use words that mean "an illustration", "a case", "a sample", or "an example."
5. Deployment Targets
ZITADEL supports multiple deployment methods. Each has its own directory and conventions:
| Target | Location | Status | Notes |
|---|---|---|---|
| Docker Compose | deploy/compose/ |
Supported | Single-node, graduated from quickstart to semi-production. See deploy/compose/AGENTS.md for directory-specific rules. |
| Kubernetes (Helm) | External (zitadel-charts) | Supported | Official Helm chart for production workloads. Docs at apps/docs/content/self-hosting/deploy/kubernetes/. |
| apt/rpm packages | Planned | Not yet available | Future packaging target. |
When generating deployment-related content:
- Docker Compose is the recommended path for getting started and homelab/single-node deployments
- Kubernetes is the recommended path for production workloads
- Always reference the correct deployment method for the user's context
- The same
ZITADEL_*environment variable model applies across all deployment methods
Command Rules
Run commands from the repository root.
- Use verified Nx targets only.
- If target availability is unclear, run
pnpm nx show project <project>. - Do not assume all projects have
test,lint,build, orgeneratetargets. - Known exception:
@zitadel/consolehas no configuredtesttarget.
Verified Common Targets
@zitadel/api:prod,build,build-linux,pack,generate,generate-install,lint,test,test-unit,test-integration@zitadel/login:dev,build,pack,lint,test,test-unit,test-integration@zitadel/docs:dev,build,generate,install-proto-plugins,check-links,check-types,test,lint@zitadel/console:dev,build,generate,install-proto-plugins,lint@zitadel/compose:test-config,test-run,test-e2e,test,test-full,stop
Proto Plugin Binaries
All proto plugins are installed to .artifacts/bin/<GOOS>/<GOARCH>/ and Nx-cached. generate targets wire up the correct install dependency and prepend .artifacts/bin/ to $PATH — no manual install step is needed.
PR Title Convention
PR titles are validated by the Semantic PR app. Format:
<type>(<scope>): <short summary>
Types: must come from the list in .github/semantic.yml under types: — e.g. feat, fix, docs, refactor, perf, test, build, ci, chore, revert.
Scopes: optional, but if used must come from the list in .github/semantic.yml under scopes:. When in doubt, omit the scope — do not invent values not on that list.
Documentation
- Human Guide: See
CONTRIBUTING.mdfor setup and contribution details. - API Design: See
API_DESIGN.mdfor API specific guidelines.