version: '3.8' ### This file is ready to use for local testing and evaluation. ### To harden it for production, follow the comments marked with [PRODUCTION]. services: devguard-setup: # One-time init container: generates the encryption key and downloads # the Kratos config + DB init script into named volumes. # Runs on every `docker compose up` but skips files that already exist. image: alpine:3.21@sha256:48b0309ca019d89d40f670aa1bc06e426dc0931948452e8491e3d65087abc07d volumes: - encryption-key:/keys - kratos-config:/kratos - initdb:/initdb command: > sh -c " BASE=https://raw.githubusercontent.com/l3montree-dev/devguard/refs/heads/main && if [ ! -f /keys/app_side_encryption.key ]; then od -vN 32 -An -tx1 /dev/urandom | tr -dc '0-9a-f' > /keys/app_side_encryption.key && echo 'Generated new encryption key.'; else echo 'Encryption key already exists, skipping.'; fi && if [ ! -f /kratos/kratos.yml ]; then wget -qO /kratos/kratos.yml $$BASE/.kratos/kratos.example.yml && echo 'Downloaded kratos.yml.'; fi && if [ ! -f /kratos/identity.schema.json ]; then wget -qO /kratos/identity.schema.json $$BASE/.kratos/identity.schema.json && echo 'Downloaded identity.schema.json.'; fi && if [ ! -f /initdb/init.sql ]; then wget -qO /initdb/init.sql $$BASE/initdb.sql && echo 'Downloaded initdb.sql.'; fi " networks: - devguard-local postgresql: image: ghcr.io/l3montree-dev/devguard/postgresql:v1.12.4 shm_size: 1g security_opt: - no-new-privileges:true depends_on: devguard-setup: condition: service_completed_successfully environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: change-me-definitely-when-not-testing # [PRODUCTION] DEVGUARD_DB_PASSWORD — set a strong random password # checkov:skip=CKV_SECRET_6:placeholder password for try-it deployment POSTGRES_DB: devguard #ports: # - "5432:5432" healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 10s timeout: 5s retries: 5 volumes: - postgres:/var/lib/postgresql/data - initdb:/docker-entrypoint-initdb.d:ro # [PRODUCTION] initdb only runs on a fresh database. After first start you can # remove this mount — it has no effect on an existing database. tmpfs: /run/postgresql:rw,uid=999,gid=999 networks: - devguard-local kratos-migrate: image: oryd/kratos:v26.2.0-distroless@sha256:481bfc3022e5427ffb94570eef84480b99c9f8158388378c57df8c1a4a104b3d read_only: true security_opt: - no-new-privileges:true cap_drop: - ALL depends_on: postgresql: condition: service_healthy volumes: - kratos-config:/etc/config/kratos:ro # [PRODUCTION] replace the named volume with a bind mount to your customised kratos.yml: # - type: bind # source: ./kratos # target: /etc/config/kratos # read_only: true environment: # [PRODUCTION] KRATOS_DB_PASSWORD — set a strong random password (separate from DEVGUARD_DB_PASSWORD) - DSN=postgres://kratos:change-me-definitely-when-not-testing@postgresql:5432/kratos?sslmode=disable command: -c /etc/config/kratos/kratos.yml migrate sql -e --yes networks: - devguard-local kratos: image: oryd/kratos:v26.2.0-distroless@sha256:481bfc3022e5427ffb94570eef84480b99c9f8158388378c57df8c1a4a104b3d read_only: true security_opt: - no-new-privileges:true cap_drop: - ALL user: "53111" depends_on: postgresql: condition: service_healthy kratos-migrate: condition: service_started volumes: - kratos-config:/etc/config/kratos:ro # [PRODUCTION] same as kratos-migrate: replace with a bind mount to your customised kratos.yml #ports: #- "4433:4433" # Public #- "4434:4434" # Admin environment: # [PRODUCTION] KRATOS_DB_PASSWORD — same value as in kratos-migrate - DSN=postgres://kratos:change-me-definitely-when-not-testing@postgresql:5432/kratos?sslmode=disable - LOG_LEVEL=debug # [PRODUCTION] set to info or warn command: serve -c /etc/config/kratos/kratos.yml --dev --watch-courier # [PRODUCTION] remove --dev flag: # command: serve -c /etc/config/kratos/kratos.yml --watch-courier networks: - devguard-local devguard-migrate: image: ghcr.io/l3montree-dev/devguard:v1.12.4 read_only: true tmpfs: - /tmp:size=8G security_opt: - no-new-privileges:true cap_drop: - ALL user: "53111" depends_on: postgresql: condition: service_healthy volumes: - encryption-key:/keys:ro environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=change-me-definitely-when-not-testing # [PRODUCTION] DEVGUARD_DB_PASSWORD # checkov:skip=CKV_SECRET_6:placeholder password for try-it deployment - POSTGRES_DB=devguard - POSTGRES_HOST=postgresql - POSTGRES_PORT=5432 - FRONTEND_URL=http://localhost:3000 # [PRODUCTION] set to your public frontend URL - APP_SIDE_ENCRYPTION_KEY_PATH=/keys/app_side_encryption.key command: ["devguard-cli", "migrate"] networks: - devguard-local devguard-api: image: ghcr.io/l3montree-dev/devguard:v1.12.4 read_only: true tmpfs: - /tmp:size=8G security_opt: - no-new-privileges:true cap_drop: - ALL user: "53111" depends_on: postgresql: condition: service_healthy kratos: condition: service_started devguard-migrate: condition: service_completed_successfully ports: - "8080:8080" # [PRODUCTION] put a TLS-terminating reverse proxy (nginx, Caddy, Traefik) in front # and do not expose this port directly to the internet volumes: - encryption-key:/keys:ro environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=change-me-definitely-when-not-testing # [PRODUCTION] DEVGUARD_DB_PASSWORD # checkov:skip=CKV_SECRET_6:placeholder password for try-it deployment - POSTGRES_DB=devguard - POSTGRES_HOST=postgresql - POSTGRES_PORT=5432 - ORY_KRATOS_PUBLIC=http://kratos:4433 - ORY_KRATOS_ADMIN=http://kratos:4434 - LOG_LEVEL=debug # [PRODUCTION] set to info or warn - INSTANCE_DOMAIN=http://localhost:8080 # [PRODUCTION] set to your public API URL (https) - FRONTEND_URL=http://localhost:3000 # [PRODUCTION] set to your public frontend URL (https) - APP_SIDE_ENCRYPTION_KEY_PATH=/keys/app_side_encryption.key networks: - devguard-local devguard-web: image: ghcr.io/l3montree-dev/devguard-web:v1.12.3 read_only: true tmpfs: - /tmp:size=100M - /app/.next/cache:size=500M security_opt: - no-new-privileges:true cap_drop: - ALL depends_on: - devguard-api ports: - "3000:3000" # [PRODUCTION] put a TLS-terminating reverse proxy in front environment: - DEVGUARD_API_URL=http://devguard-api:8080 # - DEVGUARD_API_URL_PUBLIC_INTERNET= - ORY_SDK_URL=http://kratos:4433 - ORY_SDK_PUBLIC_URL=http://localhost:3000 # [PRODUCTION] set to your public frontend URL (https) networks: - devguard-local volumes: postgres: encryption-key: kratos-config: initdb: networks: devguard-local: name: devguard-local