
ZITADEL is an open-source identity and access management platform that provides authentication, authorization, and user management for applications. It supports standardized protocols including OpenID Connect (OIDC), OAuth 2.0, and SAML, along with features like multi-factor authentication, passkeys, and single sign-on (SSO).
This article explains how to deploy ZITADEL on a Linux server using Docker Compose with PostgreSQL as the database and Traefik as the reverse proxy for TLS termination using Let's Encrypt.
Before you begin, you need to:
zitadel.example.com).ZITADEL requires a project directory with persistent storage for the database and Let's Encrypt certificates. Environment variables control the domain, database credentials, and security settings.
Add your user to the docker group.
Apply the group membership to the current session.
Create the project directory with subdirectories for persistent data.
letsencrypt: Stores SSL/TLS certificates.postgres: Persists PostgreSQL database files.zitadel-bootstrap: Shares the machine user's personal access token (PAT) between the zitadel-api and zitadel-login containers.Navigate to the project directory.
Generate a 32-character masterkey for encrypting sensitive data.
Copy the output for use in the environment file in the next step.
Create the environment file.
Add the following configuration. Replace zitadel.example.com with your domain name, admin@example.com with your email address, YOUR_32_CHARACTER_MASTERKEY with the generated masterkey, STRONG_DATABASE_PASSWORD with a secure password, and ADMIN_PASSWORD_VALUE with a secure password that meets the complexity requirements.
Save and close the file.
$ in passwords stored in .env files. Docker Compose interprets $ as a variable reference and silently removes the characters that follow it, which changes the effective password.ZITADEL_VERSION is pinned to v4.15.1 in this guide. To use the latest release, check the ZITADEL releases page and replace the value before starting the services.The deployment stack runs four services: Traefik as the reverse proxy for TLS termination, PostgreSQL for data persistence, and two ZITADEL components (API and Login UI). This configuration is based on the official ZITADEL Docker Compose setup.
Create the Docker Compose manifest.
Add the following configuration.
Save and close the file.
In the above manifest:
traefik: Serves as the reverse proxy and TLS termination point. It listens on ports 80 and 443, automatically redirects HTTP to HTTPS, and provisions Let's Encrypt certificates.postgres: Runs PostgreSQL 17 as the primary database for storing identity data, users, organizations, and applications.zitadel-api: Runs the main ZITADEL API server that handles authentication requests, user management, and administrative operations.zitadel-login: Runs the ZITADEL Login UI (Next.js) that provides the user-facing authentication pages for login, registration, and account recovery.Start the services.
Verify that all containers are running.
Verify that postgres, zitadel-api, and zitadel-login show a healthy status in the STATUS column, and that traefik shows Up, because it has no configured health check.
View the service logs to confirm that ZITADEL started successfully.
The output displays database migrations completing and both ZITADEL services reporting healthy status.
For more information on managing a Docker Compose stack, see the How to Use Docker Compose article.
zitadel-api fails to start, run docker compose logs zitadel-api to check for initialization errors. A PasswordComplexityPolicy error means the admin password does not meet the requirements. ZITADEL writes a partial migration to the database that cannot be recovered by restarting alone. Stop the stack, remove all volumes with docker compose down -v, fix the password in .env, then run docker compose up -d to start fresh.docker compose restart does not re-read the .env file. Always use docker compose up -d to apply configuration changes.ZITADEL automatically creates a default organization and admin user during the first startup using the credentials from your .env file.
Open the ZITADEL Console in your web browser at https://zitadel.example.com/ui/console, replacing zitadel.example.com with your domain.
Enter the full administrator login name in the format USERNAME@zitadel.DOMAIN (for example, admin@zitadel.zitadel.example.com).
ZITADEL login names follow the format USERNAME@ORG_NAME.DOMAIN. The default organization name is zitadel.
Enter the password you configured in the .env file (ADMIN_PASSWORD) and click Login.
Enter a new password when prompted and click Continue. ZITADEL requires a password change on the first login.
An OIDC application in ZITADEL represents a client that authenticates users through the OpenID Connect protocol. Creating a test user and a registered application validates that ZITADEL's authentication and authorization flows are operational.
A user account is required before an application can authenticate against it.
In the ZITADEL Console, click Users in the top navigation bar.
Click + New.
Enter the user details:
Select Set an initial password for the User and enter a password.
Click Create.
A project groups one or more registered applications under a shared configuration.
Click Projects in the top navigation bar.
Click Create New Project.
Enter a project name such as Test Application and click Continue.
In the project view, click + New under the Applications section.
Enter an application name such as Web App, select Web as the application type, and click Continue.
Select an authentication method and click Continue.
Add a redirect URI for your application (for example, https://example.com/callback) and click Continue.
On the Overview page, review the settings and click Create.
Copy the Client ID from the Client Details popup for use in your application's OIDC configuration. Use your ZITADEL domain as the issuer URL.
Click Close.
This confirms that ZITADEL can create users and applications, and is ready to provide identity services for your applications.
You have deployed ZITADEL on a Linux server using Docker Compose with Traefik for TLS termination and PostgreSQL for persistent data storage. For advanced configuration including custom branding, identity providers, and production hardening, refer to the official ZITADEL documentation.
0 Comments
Be the first to comment and share your perspective with the community.