From 473c33754f40c40ea5425d9faee2e12d3bce5412 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Thu, 21 Aug 2025 20:40:05 +0200 Subject: [PATCH] docs: improve compose example (#10518) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Which Problems Are Solved The [compose deployment example](https://zitadel.com/docs/self-hosting/deploy/compose) has improved guidance and a more robust compose configuration. It provides clear paths to a variety of target environments. # How the Problems Are Solved - The introduction sentences make clear that the setup is not intended to be used as is in production. - Info blocks are removed as they rather increased the mental overhead instead of drawing attention to important hints. - The What's next section adds links and hints that help evolving the setup towards production. - The docker-compose.yaml explains variables better, gives hints and provides configuration examples. - The root user is used to write and read the `login-client.pat` file to avoid file permission errors and failing setup steps. - The postgres data is persisted in a named volume, so it survives the PostgreSQL container lifecycle. - `curl` is used instead of `wget`, because `curl` is more likely to already be installed on hosts. # Additional Context - Closes #10432 - Closes #8910 - Implements changes proposed [here](https://github.com/zitadel/zitadel/issues/10432#issuecomment-3188569674) and [here](https://github.com/zitadel/zitadel/issues/10432#issuecomment-3191360487). To test the changes, you can't download the compose file as suggested [by the preview doc](https://docs-nuzruxtoh-zitadel.vercel.app/docs/self-hosting/deploy/compose). As the updated compose file is not merged to main yet, you have to use a different download link: ```shell curl -L https://raw.githubusercontent.com/zitadel/zitadel/improve-compose-example/docs/docs/self-hosting/deploy/docker-compose.yaml -o docker-compose.yaml ``` --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Tim Möhlmann --- .../docs/self-hosting/deploy/_defaultuser.mdx | 7 +- docs/docs/self-hosting/deploy/compose.mdx | 86 ++++++++++++++----- .../self-hosting/deploy/docker-compose.yaml | 66 +++++++++++--- 3 files changed, 116 insertions(+), 43 deletions(-) diff --git a/docs/docs/self-hosting/deploy/_defaultuser.mdx b/docs/docs/self-hosting/deploy/_defaultuser.mdx index 885b5f9a3..51a02eb3f 100644 --- a/docs/docs/self-hosting/deploy/_defaultuser.mdx +++ b/docs/docs/self-hosting/deploy/_defaultuser.mdx @@ -1,6 +1 @@ -Open your favorite internet browser and navigate to http://localhost:8080/ui/console?login_hint=zitadel-admin@zitadel.localhost. -Enther the password *Password1!* to log in. - -:::info -In the above login hint in the URL, replace localhost with your configured external domain, if any. e.g. with *zitadel-admin@zitadel.sso.my.domain.tld* -::: \ No newline at end of file +Visit http://localhost:8080/ui/console?login_hint=zitadel-admin@zitadel.localhost and enter `Password1!` to log in. diff --git a/docs/docs/self-hosting/deploy/compose.mdx b/docs/docs/self-hosting/deploy/compose.mdx index 8496a9b53..47975938c 100644 --- a/docs/docs/self-hosting/deploy/compose.mdx +++ b/docs/docs/self-hosting/deploy/compose.mdx @@ -10,40 +10,80 @@ import DefaultUser from './_defaultuser.mdx' import Next from './_next.mdx' import NoteInstanceNotFound from './troubleshooting/_note_instance_not_found.mdx'; +This guide is the entrypoint for running the Zitadel platform locally for the first time. +It is for demonstration and development purposes only and does not set up a production-ready and security hardened instance of Zitadel. +Once Zitadel up is and running, learn more about a production setup in the [What's Next section](#next-steps). -The setup is tested against Docker version 28.3.2 and Docker Compose version v2.38.2 +## Prerequisites + +The setup is likely to work with other software versions too, but it is tested against the following environment: + +- Ubuntu 24.04.1 +- Docker 28.3.2 +- Docker Compose v2.38.2 +- curl 8.5.0 ## Docker compose -By executing the commands below, you will download the following file: +The following commands set up services for a PostgreSQL database, a Zitadel API and a Zitadel login: + +1. Download the `docker-compose.yaml` file from the Zitadel repository: + ```shell + curl -L https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/docker-compose.yaml -o docker-compose.yaml + ``` +2. Make sure the containers use the latest image versions. + ```shell + docker compose pull + ``` +3. Run the PostgreSQL database, the Zitadel API, and the Zitadel login. + ```shell + docker compose up --detach --wait + ``` +4. Verify the containers are running and healthy. + ```shell + docker compose ps + ``` + + + +## What's next{#next-steps} + +Before proceeding, review the downloaded `docker-compose.yaml` file: +The comments give context to the used variables and show examples for commonly used configuration variants.
docker-compose.yaml {DockerComposeSource}
-```bash -# Download the docker compose example configuration. -wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/docker-compose.yaml +Here are some natural steps forward to go from the current setup to production: -# Make sure you have the latest image versions -docker compose pull +- **Use a different master key**: Set up an instance from scratch and use a different master key. For example, generate one by running `tr -dc A-Za-z0-9 +
+ Read this if the environment uses the login v1 +

+ The login v2 is the next generation of the Zitadel login. + Its code and deployment are easily customizable. + Unlike the login v1, it runs in its own process. + The login v2 is enabled by default in new installations. + But if an existing `docker-compose.yaml` file is updated by following this guide, + an additional `zitadel-login` service is now running which is actually not doing anything, yet. + The following steps give guidance on how to enable the login v2 in an environment. +

+
    +
  1. Read the login v2 related comments in the docker-compose.yaml.
  2. +
  3. Manually create a login client personal access token (PAT) for the now running v2 login.
  4. +
  5. Move the PAT to `./login-client.pat`
  6. +
  7. Restart the login process: `docker compose restart login`
  8. +
  9. Enable the Login UI for all users
  10. +
+
-:::info -If you ran these commands for an existing instance that still uses the login v1, [create a login client for it to the now running v2 login](/self-hosting/manage/login-client#create-login-client). -Move the login client PAT to `./login-client.pat` and restart the login container. -```bash -docker compose restart login -``` -Now, [enable the Login UI for all users](/self-hosting/manage/login-client#require-login-v2) -::: - - - - diff --git a/docs/docs/self-hosting/deploy/docker-compose.yaml b/docs/docs/self-hosting/deploy/docker-compose.yaml index ba27bfb64..ad94aa0c2 100644 --- a/docs/docs/self-hosting/deploy/docker-compose.yaml +++ b/docs/docs/self-hosting/deploy/docker-compose.yaml @@ -2,19 +2,29 @@ services: zitadel: restart: unless-stopped image: ghcr.io/zitadel/zitadel:latest - command: start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled + command: start-from-init --masterkey "MasterkeyNeedsToHave32Characters" environment: + # See "What's next" to learn about how to serve Zitadel on a different domain or IP. + ZITADEL_EXTERNALDOMAIN: localhost + + # See "What's next" to learn about how to enable TLS. ZITADEL_EXTERNALSECURE: false ZITADEL_TLS_ENABLED: false + + # Database connection settings. ZITADEL_DATABASE_POSTGRES_HOST: db ZITADEL_DATABASE_POSTGRES_PORT: 5432 + # The database is created by the init job if it does not exist. ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel - ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel - ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: zitadel - ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable + # The admin user must already exist in the database. ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable + # The zitadel user is created by the init job if it does not exist. + ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel + ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: zitadel + ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable + # By configuring a login client, the setup job creates a user of type machine with the role IAM_LOGIN_CLIENT. # It writes a PAT to the path specified in ZITADEL_FIRSTINSTANCE_LOGINCLIENTPATPATH. # The PAT is passed to the login container via the environment variable ZITADEL_SERVICE_USER_TOKEN_FILE. @@ -23,28 +33,49 @@ services: ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_MACHINE_USERNAME: login-client ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_MACHINE_NAME: Automatically Initialized IAM_LOGIN_CLIENT ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_PAT_EXPIRATIONDATE: '2029-01-01T00:00:00Z' - ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED: true + # Activate the login v2 on an installation from scratch. + # To activate the login v2 on an existing installation, read the "What's next" section. + ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED: true # To use the login v1, set this to false. ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_BASEURI: http://localhost:3000/ui/v2/login + # Configure the redirection paths to the login v2. ZITADEL_OIDC_DEFAULTLOGINURLV2: http://localhost:3000/ui/v2/login/login?authRequest= ZITADEL_OIDC_DEFAULTLOGOUTURLV2: http://localhost:3000/ui/v2/login/logout?post_logout_redirect= ZITADEL_SAML_DEFAULTLOGINURLV2: http://localhost:3000/ui/v2/login/login?samlRequest= + # By configuring a machine, the setup job creates a user of type machine with the role IAM_OWNER. # It writes a personal access token (PAT) to the path specified in ZITADEL_FIRSTINSTANCE_PATPATH. # The PAT can be used to provision resources with [Terraform](/docs/guides/manage/terraform-provider), for example. - ZITADEL_FIRSTINSTANCE_PATPATH: /current-dir/admin.pat - ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_USERNAME: admin - ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_NAME: Automatically Initialized IAM_OWNER - ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINEKEY_TYPE: 1 + # ZITADEL_FIRSTINSTANCE_PATPATH: /current-dir/admin.pat + # ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_USERNAME: admin + # ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_NAME: Automatically Initialized IAM_OWNER + # ZITADEL_FIRSTINSTANCE_ORG_MACHINE_PAT_EXPIRATIONDATE: '2029-01-01T00:00:00Z' + + # To change the initial human admin users username and password, uncomment the following lines. + # The first login name is formatted like this: @. + # With the following incommented configuration, this would be root@my-organization.localhost + # Visit http://localhost:8080/ui/console to check if the login name works. + # If you can't log in, check the available login names: + # echo "select * from projections.login_names3;" | psql -h localhost -U postgres -d zitadel + # The postgres users password is postgres. + # ZITADEL_FIRSTINSTANCE_ORG_NAME: My Organization + # ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME: root + # ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD: RootPassword1! + + # Enable debug logs + # ZITADEL_LOG_LEVEL: debug + # Write Access Logs to stdout. + # ZITADEL_LOGSTORE_ACCESS_STDOUT_ENABLED: true healthcheck: test: - - CMD - - /app/zitadel - - ready + - CMD + - /app/zitadel + - ready interval: 10s timeout: 60s retries: 5 start_period: 10s + user: "0" volumes: - .:/current-dir:delegated ports: @@ -59,13 +90,13 @@ services: login: restart: unless-stopped image: ghcr.io/zitadel/zitadel-login:latest - # If you can't use the network_mode service:zitadel, you can pass the environment variable CUSTOM_REQUEST_HEADERS=Host:localhost instead. + # If you can't use the network_mode service:zitadel, you can pass the environment variables ZITADEL_API_URL=http://zitadel:8080 and CUSTOM_REQUEST_HEADERS=Host:localhost instead. environment: - ZITADEL_API_URL=http://localhost:8080 - NEXT_PUBLIC_BASE_PATH=/ui/v2/login - ZITADEL_SERVICE_USER_TOKEN_FILE=/current-dir/login-client.pat - user: "${UID:-1000}" network_mode: service:zitadel + user: "0" volumes: - .:/current-dir:ro depends_on: @@ -93,6 +124,13 @@ services: start_period: 20s networks: - zitadel + ports: + - 5432:5432 + volumes: + - 'data:/var/lib/postgresql/data:rw' networks: zitadel: + +volumes: + data: