pvm/docker/docker-compose.dev.yml
Mikkel Georgsen a22ba48709 Add Zitadel OIDC setup, SMTP config, and security fixes
- Add setup-zitadel.sh: idempotent script that creates PVM project
  and OIDC app via Zitadel Management API using machine user PAT
- Add machine user + PAT auto-generation to docker-compose via
  FIRSTINSTANCE env vars with bind-mounted machinekey directory
- Add SMTP configuration for email sending (verification, password reset)
- Fix JWT algorithm confusion attack: restrict to RS256/384/512 only
- Add docs/TODO_SECURITY.md tracking review findings
- Update .env.example files with correct local dev URLs
- Add docker/machinekey/ to .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 12:34:44 +01:00

95 lines
3.2 KiB
YAML

services:
zitadel:
image: ghcr.io/zitadel/zitadel:latest
command: start-from-init --masterkey "${ZITADEL_MASTERKEY}" --tlsMode disabled
user: "0"
environment:
ZITADEL_DATABASE_POSTGRES_HOST: zitadel-db
ZITADEL_DATABASE_POSTGRES_PORT: 5432
ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel
ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: "${ZITADEL_DB_PASSWORD}"
ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: zitadel
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: "${ZITADEL_DB_PASSWORD}"
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
ZITADEL_EXTERNALDOMAIN: localhost
ZITADEL_EXTERNALPORT: 8080
ZITADEL_EXTERNALSECURE: "false"
ZITADEL_TLS_MODE: disabled
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME: admin
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD: "${ZITADEL_ADMIN_PASSWORD}"
ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED: "false"
# Machine user for automated setup (PAT written to bind mount)
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_USERNAME: pvm-setup
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_NAME: PVM Setup Service User
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_PAT_EXPIRATIONDATE: "2030-01-01T00:00:00Z"
ZITADEL_FIRSTINSTANCE_PATPATH: /machinekey/admin.pat
# SMTP for email sending (verification, password reset)
ZITADEL_DEFAULTINSTANCE_SMTPCONFIGURATION_SMTP_HOST: "${ZITADEL_SMTP_HOST}:465"
ZITADEL_DEFAULTINSTANCE_SMTPCONFIGURATION_SMTP_USER: "${ZITADEL_SMTP_USER}"
ZITADEL_DEFAULTINSTANCE_SMTPCONFIGURATION_SMTP_PASSWORD: "${ZITADEL_SMTP_PASSWORD}"
ZITADEL_DEFAULTINSTANCE_SMTPCONFIGURATION_TLS: "true"
ZITADEL_DEFAULTINSTANCE_SMTPCONFIGURATION_FROM: "${ZITADEL_SMTP_USER}"
ZITADEL_DEFAULTINSTANCE_SMTPCONFIGURATION_FROMNAME: "PVM"
ports:
- "8080:8080"
depends_on:
zitadel-db:
condition: service_healthy
volumes:
- ./machinekey:/machinekey
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8080/debug/healthz"]
interval: 10s
timeout: 5s
retries: 15
start_period: 30s
restart: unless-stopped
zitadel-db:
image: postgres:16-alpine
environment:
POSTGRES_DB: zitadel
POSTGRES_USER: zitadel
POSTGRES_PASSWORD: "${ZITADEL_DB_PASSWORD}"
volumes:
- zitadel-pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U zitadel -d zitadel"]
interval: 5s
timeout: 5s
retries: 10
restart: unless-stopped
pvm-db:
image: postgres:16-alpine
environment:
POSTGRES_DB: pvm
POSTGRES_USER: pvm
POSTGRES_PASSWORD: "${PVM_DB_PASSWORD}"
ports:
- "5432:5432"
volumes:
- pvm-pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U pvm -d pvm"]
interval: 5s
timeout: 5s
retries: 10
restart: unless-stopped
dragonfly:
image: docker.dragonflydb.io/dragonflydb/dragonfly:latest
ports:
- "6379:6379"
volumes:
- dragonfly-data:/data
ulimits:
memlock: -1
restart: unless-stopped
volumes:
zitadel-pg-data:
pvm-pg-data:
dragonfly-data: