Files
bac224c56d chore: improve docker compose template, tests and docs (#11593)
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 <[email protected]>
2026-02-24 16:33:12 -08:00

126 lines
8.1 KiB
Markdown

# 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
1. Read this file first.
2. Read the nearest scoped `AGENTS.md` for the area you edit.
3. If multiple scopes apply, use the most specific path.
## Repository Structure Map
- **`apps/`**: Consumer-facing web applications.
- **`login`**: Next.js authentication UI. See `apps/login/AGENTS.md`.
- **`docs`**: Fumadocs documentation app. See `apps/docs/AGENTS.md`.
- **`api`**: Backend Nx app target. See `apps/api/AGENTS.md`.
- **`console/`**: Angular Management Console. See `console/AGENTS.md`.
- **`internal/`**: Backend domain and service logic. See `internal/AGENTS.md`.
- **`proto/`**: API definitions. See `proto/AGENTS.md`.
- **`packages/`**: Shared TypeScript packages. See `packages/AGENTS.md`.
- **`tests/functional-ui/`**: Cypress functional UI tests. See `tests/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.mod` before Go work (`go` and optional `toolchain` directives).
- **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.
- **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':
1. **Priority 1 (Transliteration):** Use the phonetic transliteration into the local script (common in Japanese/Korean/Russian).
2. **Priority 2 (System Entity):** Use a term that implies a "running process" or "logical environment."
3. **Priority 3 (Tenant):** If 'Instance' is ambiguous, use the local word for 'Tenant' (e.g., 租户 in Chinese).
4. **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](https://github.com/zitadel/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`, or `generate` targets.
- Known exception: `@zitadel/console` has no configured `test` target.
## 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`](.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`](.github/semantic.yml) under `scopes:`. When in doubt, omit the scope — do not invent values not on that list.
## Documentation
- **Human Guide**: See `CONTRIBUTING.md` for setup and contribution details.
- **API Design**: See `API_DESIGN.md` for API specific guidelines.