Introduction

I don’t need to elaborate on the benefits of using Traefik as a proxy, so let’s go straight to the orchestration configuration.

Service Orchestration

For other Zitadel settings, you can refer to the official default steps.yaml, as well as the default global configuration file defaults.yaml.

The docker-compose.yaml file configuration is as follows:

services:
  zitadel:
    image: ghcr.io/zitadel/zitadel:latest
    labels:
      - traefik.enable=true
      - traefik.http.middlewares.gzip.compress=true
      - traefik.http.middlewares.cors.headers.accesscontrolallowmethods=GET,OPTIONS,PUT,POST
      - traefik.http.middlewares.cors.headers.accesscontrolallowheaders=*
      - traefik.http.middlewares.cors.headers.accesscontrolalloworiginlist=*
      - traefik.http.middlewares.cors.headers.accesscontrolmaxage=100
      - traefik.http.middlewares.cors.headers.addvaryheader=true

      - traefik.http.routers.zitadel.rule=Host(`zitadel.local`)
      - traefik.http.routers.zitadel.service=zitadel
      - traefik.http.routers.zitadel.entrypoints=http
      - traefik.http.routers.zitadel.middlewares=redir-https@docker

      - traefik.http.services.zitadel.loadbalancer.server.port=8080
      - traefik.http.services.zitadel.loadbalancer.server.scheme=h2c

      - traefik.http.routers.zitadel-secure.tls=true
      - traefik.http.routers.zitadel-secure.rule=Host(`zitadel.local`)
      - traefik.http.routers.zitadel-secure.service=zitadel
      - traefik.http.routers.zitadel-secure.entrypoints=https
      - traefik.http.routers.zitadel-secure.middlewares=gzip@docker
      - traefik.http.routers.zitadel-secure.middlewares=cors@docker
    restart: always
    networks:
      - traefik
    command: start-from-init --masterkeyFromEnv --tlsMode external
    hostname: zitadel
    container_name: zitadel
    environment:
      - ZITADEL_LOG_LEVEL=info
      - ZITADEL_MASTERKEY=ZQ0rISokQb0o05LvTwWYyt4z32n82wVv

      - ZITADEL_EXTERNALPORT=443
      - ZITADEL_EXTERNALSECURE=true
      - ZITADEL_EXTERNALDOMAIN=zitadel.local

      - ZITADEL_FIRSTINSTANCE_ORG_NAME=BETTERDE
      - ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME=developer
      - ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD=Developer@2023

      - ZITADEL_DEFAULTINSTANCE_ORG_NAME=ZITADEL
      - ZITADEL_DEFAULTINSTANCE_INSTANCENAME=ZITADEL

      - ZITADEL_OIDC_DEFAULTIDTOKENLIFETIME=24h
      - ZITADEL_OIDC_DEFAULTACCESSTOKENLIFETIME=24h

      - ZITADEL_DATABASE_COCKROACH_HOST=cockroachdb
      - ZITADEL_DATABASE_COCKROACH_USER_SSL_MODE=verify-full
      - ZITADEL_DATABASE_COCKROACH_USER_SSL_KEY=/certs/client.zitadel.key
      - ZITADEL_DATABASE_COCKROACH_USER_SSL_CERT=/certs/client.zitadel.crt
      - ZITADEL_DATABASE_COCKROACH_USER_SSL_ROOTCERT=/certs/ca.crt
      - ZITADEL_DATABASE_COCKROACH_USER_USERNAME=zitadel
      - ZITADEL_DATABASE_COCKROACH_USER_PASSWORD=u1mXuweLhw4tHvMZtoOtzy0kSqYdJUea
      - ZITADEL_DATABASE_COCKROACH_ADMIN_SSL_MODE=verify-full
      - ZITADEL_DATABASE_COCKROACH_ADMIN_SSL_KEY=/certs/client.root.key
      - ZITADEL_DATABASE_COCKROACH_ADMIN_SSL_CERT=/certs/client.root.crt
      - ZITADEL_DATABASE_COCKROACH_ADMIN_SSL_ROOTCERT=/certs/ca.crt
      - ZITADEL_DATABASE_COCKROACH_ADMIN_USERNAME=root
      - ZITADEL_DATABASE_COCKROACH_ADMIN_PASSWORD=75bdUlVrVFcNQhmSaLhnYfIatU2dsXL9

      - ZITADEL_DEFAULTINSTANCE_DOMAINPOLICY_SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN=false

      - ZITADEL_DEFAULTINSTANCE_OIDCSETTINGS_IDTOKENLIFETIME=24h
      - ZITADEL_DEFAULTINSTANCE_OIDCSETTINGS_ACCESSTOKENLIFETIME=24h
    volumes:
      - cockroachdb-certs:/certs:ro
    depends_on:
      cockroachdb:
        condition: service_healthy

  cockroachdb:
    image: cockroachdb/cockroach:latest
    labels:
      - traefik.enable=true
      - traefik.http.middlewares.gzip.compress=true

      - traefik.http.routers.cockroachdb.rule=Host(`cockroachdb.service.local`)
      - traefik.http.routers.cockroachdb.service=cockroachdb
      - traefik.http.routers.cockroachdb.entrypoints=http
      - traefik.http.routers.cockroachdb.middlewares=redir-https@docker

      - traefik.http.services.cockroachdb.loadbalancer.server.port=8080
      - traefik.http.services.cockroachdb.loadbalancer.server.scheme=https
      - traefik.http.services.cockroachdb.loadbalancer.passhostheader=true

      - traefik.http.routers.cockroachdb-secure.tls=true
      - traefik.http.routers.cockroachdb-secure.rule=Host(`cockroachdb.service.local`)
      - traefik.http.routers.cockroachdb-secure.service=cockroachdb
      - traefik.http.routers.cockroachdb-secure.entrypoints=https
      - traefik.http.routers.cockroachdb-secure.middlewares=gzip@docker
    restart: always
    networks:
      - traefik
    command: start-single-node --advertise-addr cockroachdb
    hostname: cockroachdb
    container_name: cockroachdb
    volumes:
      - cockroachdb-data:/cockroach/cockroach-data:rw
      - cockroachdb-certs:/cockroach/certs:rw
    environment:
      - COCKROACH_USER=zitadel
      - COCKROACH_PASSWORD=u1mXuweLhw4tHvMZtoOtzy0kSqYdJUea
      - COCKROACH_DATABASE=zitadel
    healthcheck:
      test: ["CMD", "curl", "-k", "-f", "https://localhost:8080/health?ready=1"]
      interval: '10s'
      timeout: '30s'
      retries: 5
      start_period: '20s'

volumes:
  cockroachdb-data:
    external: true
  cockroachdb-certs:
    external: true

networks:
  traefik:
    external: true

Configuration explanation:

  • Lines 7-11: Mainly to allow cross-origin requests, so if some services need to use Zitadel’s Logo as an identifier on the login page, there won’t be cross-origin issues;
  • Lines 13-16: Set up HTTP routing and redirect to HTTP middleware;
  • Lines 18-19: Configure traffic forwarding port and protocol used, since Zitadel supports gRPC, the protocol is set to h2c here;
  • Lines 21-26: Set up HTTPS routing
  • Line 30: –masterkeyFromEnv gets the master key from environment variables, –tlsMode external is only used when using a proxy and enabling HTTPS
  • Line 35: master key
  • Lines 37-39: Set external access port and domain name
  • Lines 41-43: Set the organization name and username/password for the first instance
  • Lines 51-63: Set up cockroachdb database connection, I’m using SSL here
  • Lines 81-84: Set up HTTP routing for the cockroachdb admin backend and redirect to HTTPS
  • Lines 86-88: Specify upstream port and protocol
  • Lines 90-94: Set up HTTPS routing for the cockroachdb admin backend
  • Lines 121-123: Use external Traefik network

Start Service

docker compose up -d

The final result is as follows:

Zitadel API Key Setting

Zitadel API Key Setting

Zitadel API Key Setting

I hope this is helpful, Happy hacking…