Dokploy

Zitadel

Open-source identity and access management platform with multi-tenancy, OpenID Connect, SAML, and OAuth 2.0 support.

Zitadel logo

Configuration

services:
  zitadel:
    restart: 'always'
    image: 'ghcr.io/zitadel/zitadel:v4.16.0'
    command: 'start-from-init --masterkey "${ZITADEL_MASTERKEY}" --tlsMode disabled'
    environment:
      # Database Configuration
      ZITADEL_DATABASE_POSTGRES_HOST: db
      ZITADEL_DATABASE_POSTGRES_PORT: 5432
      ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
      ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel
      ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: "${POSTGRES_PASSWORD}"
      ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
      ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
      ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: "${POSTGRES_PASSWORD}"
      ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable

      # External access configuration. These MUST match the domain configured
      # in the Domains tab and the scheme/port it is served on, otherwise
      # Zitadel answers {"code":5,"message":"Not Found"}.
      # HTTP  -> ZITADEL_EXTERNALPORT=80,  ZITADEL_EXTERNALSECURE=false
      # HTTPS -> ZITADEL_EXTERNALPORT=443, ZITADEL_EXTERNALSECURE=true
      ZITADEL_EXTERNALDOMAIN: "${ZITADEL_EXTERNALDOMAIN}"
      ZITADEL_EXTERNALPORT: "${ZITADEL_EXTERNALPORT}"
      ZITADEL_EXTERNALSECURE: "${ZITADEL_EXTERNALSECURE}"
      ZITADEL_TLS_ENABLED: false

      # Custom Admin User Configuration
      ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME: "${ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME}"
      ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD: "${ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD}"
      ZITADEL_FIRSTINSTANCE_ORG_HUMAN_EMAIL_ADDRESS: "${ZITADEL_FIRSTINSTANCE_ORG_HUMAN_EMAIL_ADDRESS}"
      ZITADEL_FIRSTINSTANCE_ORG_HUMAN_FIRSTNAME: "${ZITADEL_FIRSTINSTANCE_ORG_HUMAN_FIRSTNAME}"
      ZITADEL_FIRSTINSTANCE_ORG_HUMAN_LASTNAME: "${ZITADEL_FIRSTINSTANCE_ORG_HUMAN_LASTNAME}"

      # Use the login UI built into the API container (no extra login-v2 service needed)
      ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED: false

    healthcheck:
      test: ["CMD", "/app/zitadel", "ready"]
      interval: '10s'
      timeout: '30s'
      retries: 12
      start_period: '30s'
    depends_on:
      db:
        condition: 'service_healthy'
    expose:
      - 8080

  db:
    restart: 'always'
    image: postgres:17-alpine
    environment:
      PGUSER: postgres
      POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
      POSTGRES_DB: zitadel
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready", "-d", "zitadel", "-U", "postgres"]
      interval: '10s'
      timeout: '30s'
      retries: 5
      start_period: '20s'

volumes:
  postgres_data:
[variables]
main_domain = "${domain}"
postgres_password = "${password:32}"
zitadel_masterkey = "${password:32}"
admin_username = "${username}"
admin_email = "${email}"
admin_password = "AdminPassword123!"

[config]
mounts = []

[[config.domains]]
serviceName = "zitadel"
port = 8080
host = "${main_domain}"
path = "/"

[config.env]
POSTGRES_PASSWORD = "${postgres_password}"
ZITADEL_MASTERKEY = "${zitadel_masterkey}"

# ZITADEL_EXTERNALDOMAIN must always match the domain configured in the
# Domains tab. If you change the domain, update this variable too (and do it
# BEFORE the first deploy — Zitadel binds its instance to this domain on
# first start). For a domain served over HTTPS set ZITADEL_EXTERNALPORT=443
# and ZITADEL_EXTERNALSECURE=true.
ZITADEL_EXTERNALDOMAIN = "${main_domain}"
ZITADEL_EXTERNALPORT = "80"
ZITADEL_EXTERNALSECURE = "false"

# Custom Admin User Configuration
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME = "${admin_username}"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD = "${admin_password}"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_EMAIL_ADDRESS = "${admin_email}"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_FIRSTNAME = "Admin"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_LASTNAME = "User"

Base64

To import this template in Dokploy: create a Compose service → AdvancedBase64 import and paste the content below:

ewogICJjb21wb3NlIjogInNlcnZpY2VzOlxuICB6aXRhZGVsOlxuICAgIHJlc3RhcnQ6ICdhbHdheXMnXG4gICAgaW1hZ2U6ICdnaGNyLmlvL3ppdGFkZWwveml0YWRlbDp2NC4xNi4wJ1xuICAgIGNvbW1hbmQ6ICdzdGFydC1mcm9tLWluaXQgLS1tYXN0ZXJrZXkgXCIke1pJVEFERUxfTUFTVEVSS0VZfVwiIC0tdGxzTW9kZSBkaXNhYmxlZCdcbiAgICBlbnZpcm9ubWVudDpcbiAgICAgICMgRGF0YWJhc2UgQ29uZmlndXJhdGlvblxuICAgICAgWklUQURFTF9EQVRBQkFTRV9QT1NUR1JFU19IT1NUOiBkYlxuICAgICAgWklUQURFTF9EQVRBQkFTRV9QT1NUR1JFU19QT1JUOiA1NDMyXG4gICAgICBaSVRBREVMX0RBVEFCQVNFX1BPU1RHUkVTX0RBVEFCQVNFOiB6aXRhZGVsXG4gICAgICBaSVRBREVMX0RBVEFCQVNFX1BPU1RHUkVTX1VTRVJfVVNFUk5BTUU6IHppdGFkZWxcbiAgICAgIFpJVEFERUxfREFUQUJBU0VfUE9TVEdSRVNfVVNFUl9QQVNTV09SRDogXCIke1BPU1RHUkVTX1BBU1NXT1JEfVwiXG4gICAgICBaSVRBREVMX0RBVEFCQVNFX1BPU1RHUkVTX1VTRVJfU1NMX01PREU6IGRpc2FibGVcbiAgICAgIFpJVEFERUxfREFUQUJBU0VfUE9TVEdSRVNfQURNSU5fVVNFUk5BTUU6IHBvc3RncmVzXG4gICAgICBaSVRBREVMX0RBVEFCQVNFX1BPU1RHUkVTX0FETUlOX1BBU1NXT1JEOiBcIiR7UE9TVEdSRVNfUEFTU1dPUkR9XCJcbiAgICAgIFpJVEFERUxfREFUQUJBU0VfUE9TVEdSRVNfQURNSU5fU1NMX01PREU6IGRpc2FibGVcblxuICAgICAgIyBFeHRlcm5hbCBhY2Nlc3MgY29uZmlndXJhdGlvbi4gVGhlc2UgTVVTVCBtYXRjaCB0aGUgZG9tYWluIGNvbmZpZ3VyZWRcbiAgICAgICMgaW4gdGhlIERvbWFpbnMgdGFiIGFuZCB0aGUgc2NoZW1lL3BvcnQgaXQgaXMgc2VydmVkIG9uLCBvdGhlcndpc2VcbiAgICAgICMgWml0YWRlbCBhbnN3ZXJzIHtcImNvZGVcIjo1LFwibWVzc2FnZVwiOlwiTm90IEZvdW5kXCJ9LlxuICAgICAgIyBIVFRQICAtPiBaSVRBREVMX0VYVEVSTkFMUE9SVD04MCwgIFpJVEFERUxfRVhURVJOQUxTRUNVUkU9ZmFsc2VcbiAgICAgICMgSFRUUFMgLT4gWklUQURFTF9FWFRFUk5BTFBPUlQ9NDQzLCBaSVRBREVMX0VYVEVSTkFMU0VDVVJFPXRydWVcbiAgICAgIFpJVEFERUxfRVhURVJOQUxET01BSU46IFwiJHtaSVRBREVMX0VYVEVSTkFMRE9NQUlOfVwiXG4gICAgICBaSVRBREVMX0VYVEVSTkFMUE9SVDogXCIke1pJVEFERUxfRVhURVJOQUxQT1JUfVwiXG4gICAgICBaSVRBREVMX0VYVEVSTkFMU0VDVVJFOiBcIiR7WklUQURFTF9FWFRFUk5BTFNFQ1VSRX1cIlxuICAgICAgWklUQURFTF9UTFNfRU5BQkxFRDogZmFsc2VcblxuICAgICAgIyBDdXN0b20gQWRtaW4gVXNlciBDb25maWd1cmF0aW9uXG4gICAgICBaSVRBREVMX0ZJUlNUSU5TVEFOQ0VfT1JHX0hVTUFOX1VTRVJOQU1FOiBcIiR7WklUQURFTF9GSVJTVElOU1RBTkNFX09SR19IVU1BTl9VU0VSTkFNRX1cIlxuICAgICAgWklUQURFTF9GSVJTVElOU1RBTkNFX09SR19IVU1BTl9QQVNTV09SRDogXCIke1pJVEFERUxfRklSU1RJTlNUQU5DRV9PUkdfSFVNQU5fUEFTU1dPUkR9XCJcbiAgICAgIFpJVEFERUxfRklSU1RJTlNUQU5DRV9PUkdfSFVNQU5fRU1BSUxfQUREUkVTUzogXCIke1pJVEFERUxfRklSU1RJTlNUQU5DRV9PUkdfSFVNQU5fRU1BSUxfQUREUkVTU31cIlxuICAgICAgWklUQURFTF9GSVJTVElOU1RBTkNFX09SR19IVU1BTl9GSVJTVE5BTUU6IFwiJHtaSVRBREVMX0ZJUlNUSU5TVEFOQ0VfT1JHX0hVTUFOX0ZJUlNUTkFNRX1cIlxuICAgICAgWklUQURFTF9GSVJTVElOU1RBTkNFX09SR19IVU1BTl9MQVNUTkFNRTogXCIke1pJVEFERUxfRklSU1RJTlNUQU5DRV9PUkdfSFVNQU5fTEFTVE5BTUV9XCJcblxuICAgICAgIyBVc2UgdGhlIGxvZ2luIFVJIGJ1aWx0IGludG8gdGhlIEFQSSBjb250YWluZXIgKG5vIGV4dHJhIGxvZ2luLXYyIHNlcnZpY2UgbmVlZGVkKVxuICAgICAgWklUQURFTF9ERUZBVUxUSU5TVEFOQ0VfRkVBVFVSRVNfTE9HSU5WMl9SRVFVSVJFRDogZmFsc2VcblxuICAgIGhlYWx0aGNoZWNrOlxuICAgICAgdGVzdDogW1wiQ01EXCIsIFwiL2FwcC96aXRhZGVsXCIsIFwicmVhZHlcIl1cbiAgICAgIGludGVydmFsOiAnMTBzJ1xuICAgICAgdGltZW91dDogJzMwcydcbiAgICAgIHJldHJpZXM6IDEyXG4gICAgICBzdGFydF9wZXJpb2Q6ICczMHMnXG4gICAgZGVwZW5kc19vbjpcbiAgICAgIGRiOlxuICAgICAgICBjb25kaXRpb246ICdzZXJ2aWNlX2hlYWx0aHknXG4gICAgZXhwb3NlOlxuICAgICAgLSA4MDgwXG5cbiAgZGI6XG4gICAgcmVzdGFydDogJ2Fsd2F5cydcbiAgICBpbWFnZTogcG9zdGdyZXM6MTctYWxwaW5lXG4gICAgZW52aXJvbm1lbnQ6XG4gICAgICBQR1VTRVI6IHBvc3RncmVzXG4gICAgICBQT1NUR1JFU19QQVNTV09SRDogXCIke1BPU1RHUkVTX1BBU1NXT1JEfVwiXG4gICAgICBQT1NUR1JFU19EQjogeml0YWRlbFxuICAgIHZvbHVtZXM6XG4gICAgICAtIHBvc3RncmVzX2RhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhXG4gICAgaGVhbHRoY2hlY2s6XG4gICAgICB0ZXN0OiBbXCJDTUQtU0hFTExcIiwgXCJwZ19pc3JlYWR5XCIsIFwiLWRcIiwgXCJ6aXRhZGVsXCIsIFwiLVVcIiwgXCJwb3N0Z3Jlc1wiXVxuICAgICAgaW50ZXJ2YWw6ICcxMHMnXG4gICAgICB0aW1lb3V0OiAnMzBzJ1xuICAgICAgcmV0cmllczogNVxuICAgICAgc3RhcnRfcGVyaW9kOiAnMjBzJ1xuXG52b2x1bWVzOlxuICBwb3N0Z3Jlc19kYXRhOlxuIiwKICAiY29uZmlnIjogIlt2YXJpYWJsZXNdXG5tYWluX2RvbWFpbiA9IFwiJHtkb21haW59XCJcbnBvc3RncmVzX3Bhc3N3b3JkID0gXCIke3Bhc3N3b3JkOjMyfVwiXG56aXRhZGVsX21hc3RlcmtleSA9IFwiJHtwYXNzd29yZDozMn1cIlxuYWRtaW5fdXNlcm5hbWUgPSBcIiR7dXNlcm5hbWV9XCJcbmFkbWluX2VtYWlsID0gXCIke2VtYWlsfVwiXG5hZG1pbl9wYXNzd29yZCA9IFwiQWRtaW5QYXNzd29yZDEyMyFcIlxuXG5bY29uZmlnXVxubW91bnRzID0gW11cblxuW1tjb25maWcuZG9tYWluc11dXG5zZXJ2aWNlTmFtZSA9IFwieml0YWRlbFwiXG5wb3J0ID0gODA4MFxuaG9zdCA9IFwiJHttYWluX2RvbWFpbn1cIlxucGF0aCA9IFwiL1wiXG5cbltjb25maWcuZW52XVxuUE9TVEdSRVNfUEFTU1dPUkQgPSBcIiR7cG9zdGdyZXNfcGFzc3dvcmR9XCJcblpJVEFERUxfTUFTVEVSS0VZID0gXCIke3ppdGFkZWxfbWFzdGVya2V5fVwiXG5cbiMgWklUQURFTF9FWFRFUk5BTERPTUFJTiBtdXN0IGFsd2F5cyBtYXRjaCB0aGUgZG9tYWluIGNvbmZpZ3VyZWQgaW4gdGhlXG4jIERvbWFpbnMgdGFiLiBJZiB5b3UgY2hhbmdlIHRoZSBkb21haW4sIHVwZGF0ZSB0aGlzIHZhcmlhYmxlIHRvbyAoYW5kIGRvIGl0XG4jIEJFRk9SRSB0aGUgZmlyc3QgZGVwbG95IOKAlCBaaXRhZGVsIGJpbmRzIGl0cyBpbnN0YW5jZSB0byB0aGlzIGRvbWFpbiBvblxuIyBmaXJzdCBzdGFydCkuIEZvciBhIGRvbWFpbiBzZXJ2ZWQgb3ZlciBIVFRQUyBzZXQgWklUQURFTF9FWFRFUk5BTFBPUlQ9NDQzXG4jIGFuZCBaSVRBREVMX0VYVEVSTkFMU0VDVVJFPXRydWUuXG5aSVRBREVMX0VYVEVSTkFMRE9NQUlOID0gXCIke21haW5fZG9tYWlufVwiXG5aSVRBREVMX0VYVEVSTkFMUE9SVCA9IFwiODBcIlxuWklUQURFTF9FWFRFUk5BTFNFQ1VSRSA9IFwiZmFsc2VcIlxuXG4jIEN1c3RvbSBBZG1pbiBVc2VyIENvbmZpZ3VyYXRpb25cblpJVEFERUxfRklSU1RJTlNUQU5DRV9PUkdfSFVNQU5fVVNFUk5BTUUgPSBcIiR7YWRtaW5fdXNlcm5hbWV9XCJcblpJVEFERUxfRklSU1RJTlNUQU5DRV9PUkdfSFVNQU5fUEFTU1dPUkQgPSBcIiR7YWRtaW5fcGFzc3dvcmR9XCJcblpJVEFERUxfRklSU1RJTlNUQU5DRV9PUkdfSFVNQU5fRU1BSUxfQUREUkVTUyA9IFwiJHthZG1pbl9lbWFpbH1cIlxuWklUQURFTF9GSVJTVElOU1RBTkNFX09SR19IVU1BTl9GSVJTVE5BTUUgPSBcIkFkbWluXCJcblpJVEFERUxfRklSU1RJTlNUQU5DRV9PUkdfSFVNQU5fTEFTVE5BTUUgPSBcIlVzZXJcIlxuIgp9

Tags

identity, authentication, authorization, iam, security, oauth, openid-connect, saml, multi-tenant


Version: 4.16.0

On this page