mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 08:17:43 +00:00
docs: simplify compose example (#10407)
# Which Problems Are Solved Using the compose configuration with for existing installation doesn't work. It is not appreciated in the whole community, that we use Traefik for the deployment example. # How the Problems Are Solved - The config we used before v4 is reused and extended in a compatible way. - Traefik is removed, Zitadel is accessible again at localhost:8080 and the login at localhost:3000. Deploying with Traefik is described already here http://localhost:3000/docs/self-hosting/manage/reverseproxy/traefik - A page is added that describes how to create a login client and switch from login v1 to v2. The page is linked in a hint in the compose example. # Additional Changes - The config also sets up a machine user and documents it inline. This allows us to avoid using the cumbersome separate docker-compose-sa.yaml # Additional Context - Closes #10379 - Internal discussion https://zitadel.slack.com/archives/C08TL9AURL7/p1754471184222879 - Discord about upgrading to v2 login: - https://discord.com/channels/927474939156643850/927866013545025566/threads/1401950163940933804 - https://discord.com/channels/927474939156643850/927866013545025566/1401312126030708756 - Discord about not found errors: - https://discord.com/channels/927474939156643850/927866013545025566/threads/1401173877941473291 - https://discord.com/channels/927474939156643850/927866013545025566/1401045717849604227 - https://discord.com/channels/927474939156643850/927866013545025566/1401173877941473291 - https://discord.com/channels/927474939156643850/927866013545025566/1401301168998584361
This commit is contained in:
2
docs/docs/self-hosting/deploy/.gitignore
vendored
2
docs/docs/self-hosting/deploy/.gitignore
vendored
@@ -1 +1 @@
|
||||
login-client-pat
|
||||
*.pat
|
@@ -1,8 +1,6 @@
|
||||
Open your favorite internet browser and navigate to [http://localhost:8080/ui/console](http://localhost:8080/ui/console).
|
||||
This is the default IAM admin users login:
|
||||
- **username**: *zitadel-admin@<span></span>zitadel.localhost*
|
||||
- **password**: *Password1!*
|
||||
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 username, replace localhost with your configured external domain, if any. e.g. with *zitadel-admin@<span></span>zitadel.sso.my.domain.tld*
|
||||
In the above login hint in the URL, replace localhost with your configured external domain, if any. e.g. with *zitadel-admin@<span></span>zitadel.sso.my.domain.tld*
|
||||
:::
|
@@ -5,61 +5,45 @@ sidebar_label: Docker Compose
|
||||
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import DockerComposeSource from '!!raw-loader!./docker-compose.yaml'
|
||||
import ExampleZitadelConfigSource from '!!raw-loader!./example-zitadel-config.yaml'
|
||||
import ExampleZitadelSecretsSource from '!!raw-loader!./example-zitadel-secrets.yaml'
|
||||
import ExampleZitadelInitStepsSource from '!!raw-loader!./example-zitadel-init-steps.yaml'
|
||||
import Disclaimer from './_disclaimer.mdx'
|
||||
import DefaultUser from './_defaultuser.mdx'
|
||||
import Next from './_next.mdx'
|
||||
import NoteInstanceNotFound from './troubleshooting/_note_instance_not_found.mdx';
|
||||
|
||||
The stack consists of four long-running containers and a couple of short-lived containers:
|
||||
- A [Traefik](https://doc.traefik.io/traefik/) reverse proxy container with upstream HTTP/2 enabled, issuing a self-signed TLS certificate.
|
||||
- A Login container that is accessible via Traefik at `/ui/v2/login`
|
||||
- A Zitadel container that is accessible via Traefik at all other paths than `/ui/v2/login`.
|
||||
- An insecure [PostgreSQL](https://www.postgresql.org/docs/current/index.html).
|
||||
|
||||
The Traefik container and the login container call the Zitadel container via the internal Docker network at `h2c://zitadel:8080`
|
||||
|
||||
The setup is tested against Docker version 28.3.2 and Docker Compose version v2.38.2
|
||||
|
||||
By executing the commands below, you will download the following files:
|
||||
## Docker compose
|
||||
|
||||
By executing the commands below, you will download the following file:
|
||||
|
||||
<details>
|
||||
<summary>docker-compose.yaml</summary>
|
||||
<CodeBlock language="yaml">{DockerComposeSource}</CodeBlock>
|
||||
</details>
|
||||
<details>
|
||||
<summary>example-zitadel-config.yaml</summary>
|
||||
<CodeBlock language="yaml">{ExampleZitadelConfigSource}</CodeBlock>
|
||||
</details>
|
||||
<details>
|
||||
<summary>example-zitadel-secrets.yaml</summary>
|
||||
<CodeBlock language="yaml">{ExampleZitadelSecretsSource}</CodeBlock>
|
||||
</details>
|
||||
<details>
|
||||
<summary>example-zitadel-init-steps.yaml</summary>
|
||||
<CodeBlock language="yaml">{ExampleZitadelInitStepsSource}</CodeBlock>
|
||||
</details>
|
||||
|
||||
```bash
|
||||
# Download the docker compose example configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/docker-compose.yaml
|
||||
|
||||
# Download and adjust the example configuration file containing standard configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/example-zitadel-config.yaml
|
||||
|
||||
# Download and adjust the example configuration file containing secret configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/example-zitadel-secrets.yaml
|
||||
|
||||
# Download and adjust the example configuration file containing database initialization configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/example-zitadel-init-steps.yaml
|
||||
|
||||
# Make sure you have the latest version of the images
|
||||
# Make sure you have the latest image versions
|
||||
docker compose pull
|
||||
|
||||
# Run the containers
|
||||
# Run the PostgreSQL database, the Zitadel API and the Zitadel login.
|
||||
docker compose up
|
||||
```
|
||||
|
||||
Open your favorite internet browser at https://localhost/ui/console?login_hint=zitadel-admin@zitadel.localhost.
|
||||
Your browser warns you about the insecure self-signed TLS certificate. As localhost resolves to your local machine, you can safely proceed.
|
||||
Use the password *Password1!* to log in.
|
||||
<DefaultUser components={props.components} />
|
||||
|
||||
Read more about [the login process](/guides/integrate/login/oidc/login-users).
|
||||
:::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)
|
||||
:::
|
||||
|
||||
<NoteInstanceNotFound/>
|
||||
<Next components={props.components} />
|
||||
<Disclaimer components={props.components} />
|
||||
|
@@ -1,117 +1,98 @@
|
||||
services:
|
||||
|
||||
db:
|
||||
image: postgres:17-alpine
|
||||
zitadel:
|
||||
restart: unless-stopped
|
||||
image: ghcr.io/zitadel/zitadel:latest
|
||||
command: start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled
|
||||
environment:
|
||||
- POSTGRES_USER=root
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
networks:
|
||||
- 'storage'
|
||||
ZITADEL_EXTERNALSECURE: false
|
||||
ZITADEL_TLS_ENABLED: false
|
||||
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: zitadel
|
||||
ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_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.
|
||||
ZITADEL_FIRSTINSTANCE_LOGINCLIENTPATPATH: /current-dir/login-client.pat
|
||||
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORDCHANGEREQUIRED: false
|
||||
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
|
||||
ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_BASEURI: http://localhost:3000/ui/v2/login
|
||||
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
|
||||
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "pg_isready", "-d", "db_prod" ]
|
||||
test:
|
||||
- CMD
|
||||
- /app/zitadel
|
||||
- ready
|
||||
interval: 10s
|
||||
timeout: 60s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
volumes:
|
||||
- 'data:/var/lib/postgresql/data:rw'
|
||||
|
||||
zitadel-init:
|
||||
restart: 'no'
|
||||
- .:/current-dir:delegated
|
||||
ports:
|
||||
- 8080:8080
|
||||
- 3000:3000
|
||||
networks:
|
||||
- 'storage'
|
||||
image: 'ghcr.io/zitadel/zitadel:v4.0.0-rc.2'
|
||||
command: [ init, --config, /example-zitadel-config.yaml, --config, /example-zitadel-secrets.yaml ]
|
||||
- zitadel
|
||||
depends_on:
|
||||
db:
|
||||
condition: 'service_healthy'
|
||||
volumes:
|
||||
- './example-zitadel-config.yaml:/example-zitadel-config.yaml:ro'
|
||||
- './example-zitadel-secrets.yaml:/example-zitadel-secrets.yaml:ro'
|
||||
|
||||
zitadel-setup:
|
||||
restart: 'no'
|
||||
networks:
|
||||
- 'storage'
|
||||
image: 'ghcr.io/zitadel/zitadel:v4.0.0-rc.2'
|
||||
command: [ setup, --config, /current-dir/example-zitadel-config.yaml, --config, /current-dir/example-zitadel-secrets.yaml, --steps, /current-dir/example-zitadel-init-steps.yaml, --masterkey, MasterkeyNeedsToHave32Characters ]
|
||||
depends_on:
|
||||
zitadel-init:
|
||||
condition: 'service_completed_successfully'
|
||||
restart: false
|
||||
volumes:
|
||||
- '.:/current-dir:rw'
|
||||
|
||||
zitadel:
|
||||
restart: 'unless-stopped'
|
||||
networks:
|
||||
- 'backend'
|
||||
- 'storage'
|
||||
labels:
|
||||
- "traefik.http.routers.zitadel.rule=!PathPrefix(`/ui/v2/login`)"
|
||||
- "traefik.http.routers.zitadel.tls=true" # Traefik uses a self-signed certificate
|
||||
- "traefik.http.services.zitadel.loadbalancer.passhostheader=true"
|
||||
- "traefik.http.services.zitadel.loadbalancer.server.scheme=h2c"
|
||||
- "traefik.http.services.zitadel.loadbalancer.server.port=8080"
|
||||
image: 'ghcr.io/zitadel/zitadel:v4.0.0-rc.2'
|
||||
command: [ start, --config, /example-zitadel-config.yaml, --config, /example-zitadel-secrets.yaml, --masterkey, MasterkeyNeedsToHave32Characters ]
|
||||
depends_on:
|
||||
zitadel-setup:
|
||||
condition: 'service_completed_successfully'
|
||||
restart: true
|
||||
volumes:
|
||||
- './example-zitadel-config.yaml:/example-zitadel-config.yaml:ro'
|
||||
- './example-zitadel-secrets.yaml:/example-zitadel-secrets.yaml:ro'
|
||||
healthcheck:
|
||||
test: [ "CMD", "/app/zitadel", "ready", "--config", "/example-zitadel-config.yaml", "--config", "/example-zitadel-secrets.yaml" ]
|
||||
interval: 10s
|
||||
timeout: 60s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
condition: service_healthy
|
||||
|
||||
login:
|
||||
restart: 'unless-stopped'
|
||||
labels:
|
||||
- "traefik.http.routers.login.rule=PathPrefix(`/ui/v2/login`)"
|
||||
- "traefik.http.routers.login.tls=true" # Traefik uses a self-signed certificate
|
||||
- "traefik.http.services.login.loadbalancer.passhostheader=true"
|
||||
- "traefik.http.services.login.loadbalancer.server.port=3000"
|
||||
image: 'ghcr.io/zitadel/zitadel-login:v4.0.0-rc.2'
|
||||
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.
|
||||
network_mode: service:zitadel
|
||||
environment:
|
||||
- ZITADEL_API_URL=http://localhost:8080
|
||||
- NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
||||
- ZITADEL_SERVICE_USER_TOKEN_FILE=/current-dir/login-client-pat
|
||||
- ZITADEL_SERVICE_USER_TOKEN_FILE=/current-dir/login-client.pat
|
||||
user: "${UID:-1000}"
|
||||
network_mode: service:zitadel
|
||||
volumes:
|
||||
- '.:/current-dir:ro'
|
||||
depends_on:
|
||||
zitadel-setup:
|
||||
condition: 'service_completed_successfully'
|
||||
restart: false
|
||||
|
||||
traefik:
|
||||
image: traefik:latest
|
||||
command: --providers.docker --api.insecure=true --entrypoints.websecure.address=:443 --log.level=DEBUG --accesslog
|
||||
networks:
|
||||
- 'backend'
|
||||
ports:
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- .:/current-dir:ro
|
||||
depends_on:
|
||||
zitadel:
|
||||
condition: 'service_healthy'
|
||||
login:
|
||||
condition: 'service_started'
|
||||
condition: service_healthy
|
||||
restart: false
|
||||
|
||||
db:
|
||||
restart: unless-stopped
|
||||
image: postgres:17-alpine
|
||||
environment:
|
||||
PGUSER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- pg_isready
|
||||
- -d
|
||||
- zitadel
|
||||
- -U
|
||||
- postgres
|
||||
interval: 10s
|
||||
timeout: 30s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
networks:
|
||||
- zitadel
|
||||
|
||||
networks:
|
||||
storage:
|
||||
backend:
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
zitadel:
|
||||
|
@@ -1,22 +0,0 @@
|
||||
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
|
||||
|
||||
ExternalSecure: true
|
||||
ExternalPort: 443
|
||||
|
||||
# Traefik terminates TLS. Inside the Docker network, we use plain text.
|
||||
TLS.Enabled: false
|
||||
|
||||
# If not using the docker compose example, adjust these values for connecting ZITADEL to your PostgreSQL
|
||||
Database:
|
||||
postgres:
|
||||
Host: 'db'
|
||||
Port: 5432
|
||||
Database: zitadel
|
||||
User.SSL.Mode: 'disable'
|
||||
Admin.SSL.Mode: 'disable'
|
||||
|
||||
# Access logs allow us to debug Network issues
|
||||
LogStore.Access.Stdout.Enabled: true
|
||||
|
||||
# Skipping the MFA init step allows us to immediately authenticate at the console
|
||||
DefaultInstance.LoginPolicy.MfaInitSkipLifetime: "0s"
|
@@ -1,11 +0,0 @@
|
||||
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/setup/steps.yaml
|
||||
FirstInstance:
|
||||
LoginClientPatPath: '/current-dir/login-client-pat'
|
||||
Org:
|
||||
# We want to authenticate immediately at the console without changing the password
|
||||
Human.PasswordChangeRequired: false
|
||||
LoginClient:
|
||||
Machine:
|
||||
Username: 'login-client'
|
||||
Name: 'Automatically Initialized IAM Login Client'
|
||||
Pat.ExpirationDate: '2029-01-01T00:00:00Z'
|
@@ -1,12 +0,0 @@
|
||||
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
|
||||
|
||||
# If not using the docker compose example, adjust these values for connecting ZITADEL to your PostgreSQL
|
||||
Database:
|
||||
postgres:
|
||||
User:
|
||||
# If the user doesn't exist already, it is created
|
||||
Username: 'zitadel_user'
|
||||
Password: 'zitadel'
|
||||
Admin:
|
||||
Username: 'root'
|
||||
Password: 'postgres'
|
47
docs/docs/self-hosting/manage/login-client.mdx
Normal file
47
docs/docs/self-hosting/manage/login-client.mdx
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: Connect your Self-Hosted Login UI to Zitadel
|
||||
sidebar_label: Create a Login Client
|
||||
---
|
||||
|
||||
To enable your self-hosted Login UI to connect to the Zitadel API, it needs a token for a user with the IAM_LOGIN_CLIENT role.
|
||||
On new installations, the Zitadel setup job can be configured to automatically write a Personal Access Token (PAT) for the login client.
|
||||
Check out [one of the deployment examples](https://zitadel.com/docs/self-hosting/deploy/overview) to learn how to do this.
|
||||
|
||||
However, if you want to replace the v1 login of an existing installation by a self-hosted v2 login, the setup job won't execute these steps.
|
||||
In that case, you can create a new PAT for the login client manually.
|
||||
|
||||
## Create a Login Client User{#create-login-client}
|
||||
|
||||
In the following URLs, replace the base URL and the user ID according to your environment.
|
||||
|
||||
1. Create a new machine user, for example at http://localhost:8080/ui/console/users/create-machine
|
||||
2. Create a PAT, for example at http://localhost:8080/ui/console/users/332169800719532035?new=true&id=pat
|
||||
3. Save the PAT to a file, for example `/path/on/your/host/login-client.pat`
|
||||
4. Make sure the user has the `Iam Login Client` role (internally called `IAM_LOGIN_CLIENT`), for example at http://localhost:8080/ui/console/instance/members
|
||||
|
||||
# Configure the Login UI
|
||||
|
||||
Make sure your Login UI has the environment variable `ZITADEL_SERVICE_USER_TOKEN` set with your PAT.
|
||||
If you run the Login UI with Docker, you can also mount the file into the container and reference it by passing the environment variable `ZITADEL_SERVICE_USER_TOKEN_FILE`.
|
||||
For example:
|
||||
|
||||
```bash
|
||||
docker run -p 3000:3000 -v /path/on/your/host/login-client.pat:/path/in/container/login-client.pat:ro -e ZITADEL_SERVICE_USER_TOKEN_FILE=/path/in/container/login-client.pat ghcr.io/zitadel/zitadel-login:latest
|
||||
```
|
||||
|
||||
# Enable the Login UI for all users{#require-login-v2}
|
||||
|
||||
:::caution
|
||||
Before doing this, make sure you have a working PAT for an Iam Owner user.
|
||||
In case something goes wrong and you lock yourself out from the login screen, you can revert the changes.
|
||||
Create a machine user PAT like you created the [login client PAT above](#create-login-client), but give the user the Iam Owner role (internally called `IAM_OWNER`).
|
||||
:::
|
||||
|
||||
Enable the `Login V2` feature flag, for example at the bottom of http://localhost:8080/ui/console/instance?id=features.
|
||||
Enter the base URI of your Login UI, for example `http://localhost:3000/ui/v2/login`.
|
||||
|
||||
# Test
|
||||
|
||||
That's it!
|
||||
Click your users avatar in the top right corner of the console and select `Log in With Another Account`.
|
||||
You should see the new Login UI.
|
@@ -1094,6 +1094,7 @@ module.exports = {
|
||||
items: [
|
||||
"self-hosting/manage/production",
|
||||
"self-hosting/manage/productionchecklist",
|
||||
"self-hosting/manage/login-client",
|
||||
"self-hosting/manage/configure/configure",
|
||||
{
|
||||
type: "category",
|
||||
|
Reference in New Issue
Block a user