mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 17:27:31 +00:00
docs(self-hosting): simplify lb example and replace compose example (#9844)
# Which Problems Are Solved The load balancing compose example uses a dedicated service `use-new-login` that gives the set up machine user the login role and requires the v2 login using an instance feature. This is cumbersome and unnecessary. # How the Problems Are Solved - A login client machine user is set up and the token is passed to the login by using the environment variable ZITADEL_SERVICE_USER_TOKEN_FILE. - The unnecessary service is removed # Additional Changes - Uses the static `MasterkeyNeedsToHave32Characters` master key. - The load balancing example replaces the previous Docker Compose example. - The login uses `network_mode: service:zitadel` so it can access the zitadel service in the docker network via localhost. - Uses the docker provider for Traefik. # Additional Context - Complements https://github.com/zitadel/zitadel/pull/9496 - Partially closes https://github.com/zitadel/zitadel/issues/10016 - When we release, we should update the image tags to latest, for example with [this PR](https://github.com/zitadel/zitadel/pull/10249). --------- Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
This commit is contained in:
1
docs/docs/self-hosting/deploy/.gitignore
vendored
Normal file
1
docs/docs/self-hosting/deploy/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
login-client-pat
|
@@ -1,67 +1,65 @@
|
|||||||
---
|
---
|
||||||
title: Set up ZITADEL with Docker Compose
|
title: Set up Zitadel with Docker Compose
|
||||||
sidebar_label: Docker Compose
|
sidebar_label: Docker Compose
|
||||||
---
|
---
|
||||||
|
|
||||||
import CodeBlock from '@theme/CodeBlock';
|
import CodeBlock from '@theme/CodeBlock';
|
||||||
import DockerComposeSource from '!!raw-loader!./docker-compose.yaml'
|
import DockerComposeSource from '!!raw-loader!./docker-compose.yaml'
|
||||||
import DockerComposeSaSource from '!!raw-loader!./docker-compose-sa.yaml'
|
import ExampleZitadelConfigSource from '!!raw-loader!./example-zitadel-config.yaml'
|
||||||
import Disclaimer from './_disclaimer.mdx'
|
import ExampleZitadelSecretsSource from '!!raw-loader!./example-zitadel-secrets.yaml'
|
||||||
import DefaultUser from './_defaultuser.mdx'
|
import ExampleZitadelInitStepsSource from '!!raw-loader!./example-zitadel-init-steps.yaml'
|
||||||
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 setup is tested against Docker version 20.10.17 and Docker Compose version v2.2.3
|
The Traefik container and the login container call the Zitadel container via the internal Docker network at `h2c://zitadel:8080`
|
||||||
|
|
||||||
## Docker compose
|
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 file:
|
By executing the commands below, you will download the following files:
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>docker-compose.yaml</summary>
|
<summary>docker-compose.yaml</summary>
|
||||||
<CodeBlock language="yaml">{DockerComposeSource}</CodeBlock>
|
<CodeBlock language="yaml">{DockerComposeSource}</CodeBlock>
|
||||||
</details>
|
</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
|
```bash
|
||||||
# Download the docker compose example configuration.
|
# Download the docker compose example configuration.
|
||||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/docker-compose.yaml
|
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/docker-compose.yaml
|
||||||
|
|
||||||
# Run the database and application containers.
|
# Download and adjust the example configuration file containing standard configuration.
|
||||||
docker compose up --detach
|
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
|
||||||
|
docker compose pull
|
||||||
|
|
||||||
|
# Run the containers
|
||||||
|
docker compose up
|
||||||
```
|
```
|
||||||
|
|
||||||
<DefaultUser components={props.components} />
|
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.
|
||||||
|
|
||||||
<NoteInstanceNotFound/>
|
Read more about [the login process](/guides/integrate/login/oidc/login-users).
|
||||||
|
|
||||||
## VideoGuide
|
|
||||||
<iframe width="100%" height="315" src="https://www.youtube.com/embed/-02FaoN9Fko" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
|
||||||
|
|
||||||
## Docker compose with service account
|
|
||||||
|
|
||||||
By executing the commands below, you will download the following file:
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>docker-compose-sa.yaml</summary>
|
|
||||||
<CodeBlock language="yaml">{DockerComposeSaSource}</CodeBlock>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Download the docker compose example configuration.
|
|
||||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/docker-compose-sa.yaml -O docker-compose.yaml
|
|
||||||
|
|
||||||
# create the machine key directory
|
|
||||||
mkdir machinekey
|
|
||||||
|
|
||||||
# Run the database and application containers.
|
|
||||||
docker compose up --detach
|
|
||||||
|
|
||||||
# then you can move your machine key
|
|
||||||
mv ./machinekey/zitadel-admin-sa.json $HOME/zitadel-admin-sa.json
|
|
||||||
```
|
|
||||||
|
|
||||||
This key can be used to provision resources with for example [Terraform](/docs/guides/manage/terraform-provider).
|
|
||||||
|
|
||||||
<Next components={props.components} />
|
|
||||||
<Disclaimer components={props.components} />
|
|
@@ -1,49 +0,0 @@
|
|||||||
services:
|
|
||||||
zitadel:
|
|
||||||
# The user should have the permission to write to ./machinekey
|
|
||||||
user: "${UID:-1000}"
|
|
||||||
restart: 'always'
|
|
||||||
networks:
|
|
||||||
- 'zitadel'
|
|
||||||
image: 'ghcr.io/zitadel/zitadel:latest'
|
|
||||||
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled'
|
|
||||||
environment:
|
|
||||||
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
|
|
||||||
ZITADEL_EXTERNALSECURE: false
|
|
||||||
ZITADEL_FIRSTINSTANCE_MACHINEKEYPATH: /machinekey/zitadel-admin-sa.json
|
|
||||||
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_USERNAME: zitadel-admin-sa
|
|
||||||
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_NAME: Admin
|
|
||||||
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINEKEY_TYPE: 1
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: 'service_healthy'
|
|
||||||
ports:
|
|
||||||
- '8080:8080'
|
|
||||||
volumes:
|
|
||||||
- ./machinekey:/machinekey
|
|
||||||
|
|
||||||
db:
|
|
||||||
restart: 'always'
|
|
||||||
image: postgres:17-alpine
|
|
||||||
environment:
|
|
||||||
PGUSER: postgres
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
networks:
|
|
||||||
- 'zitadel'
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready", "-d", "zitadel", "-U", "postgres"]
|
|
||||||
interval: '10s'
|
|
||||||
timeout: '30s'
|
|
||||||
retries: 5
|
|
||||||
start_period: '20s'
|
|
||||||
|
|
||||||
networks:
|
|
||||||
zitadel:
|
|
@@ -1,41 +1,117 @@
|
|||||||
services:
|
services:
|
||||||
zitadel:
|
|
||||||
restart: 'always'
|
db:
|
||||||
networks:
|
image: postgres:17-alpine
|
||||||
- 'zitadel'
|
restart: unless-stopped
|
||||||
image: 'ghcr.io/zitadel/zitadel:latest'
|
|
||||||
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled'
|
|
||||||
environment:
|
environment:
|
||||||
ZITADEL_DATABASE_POSTGRES_HOST: db
|
- POSTGRES_USER=root
|
||||||
ZITADEL_DATABASE_POSTGRES_PORT: 5432
|
- POSTGRES_PASSWORD=postgres
|
||||||
ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
|
networks:
|
||||||
ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel
|
- 'storage'
|
||||||
ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: zitadel
|
healthcheck:
|
||||||
ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
|
test: [ "CMD-SHELL", "pg_isready", "-d", "db_prod" ]
|
||||||
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
|
interval: 10s
|
||||||
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres
|
timeout: 60s
|
||||||
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
|
retries: 5
|
||||||
ZITADEL_EXTERNALSECURE: false
|
start_period: 10s
|
||||||
|
volumes:
|
||||||
|
- 'data:/var/lib/postgresql/data:rw'
|
||||||
|
|
||||||
|
zitadel-init:
|
||||||
|
restart: 'no'
|
||||||
|
networks:
|
||||||
|
- 'storage'
|
||||||
|
image: 'ghcr.io/zitadel/zitadel:v4.0.0-rc.2'
|
||||||
|
command: [ init, --config, /example-zitadel-config.yaml, --config, /example-zitadel-secrets.yaml ]
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: 'service_healthy'
|
condition: 'service_healthy'
|
||||||
ports:
|
volumes:
|
||||||
- '8080:8080'
|
- './example-zitadel-config.yaml:/example-zitadel-config.yaml:ro'
|
||||||
|
- './example-zitadel-secrets.yaml:/example-zitadel-secrets.yaml:ro'
|
||||||
|
|
||||||
db:
|
zitadel-setup:
|
||||||
restart: 'always'
|
restart: 'no'
|
||||||
image: postgres:17-alpine
|
|
||||||
environment:
|
|
||||||
PGUSER: postgres
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
networks:
|
networks:
|
||||||
- 'zitadel'
|
- '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:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready", "-d", "zitadel", "-U", "postgres"]
|
test: [ "CMD", "/app/zitadel", "ready", "--config", "/example-zitadel-config.yaml", "--config", "/example-zitadel-secrets.yaml" ]
|
||||||
interval: '10s'
|
interval: 10s
|
||||||
timeout: '30s'
|
timeout: 60s
|
||||||
retries: 5
|
retries: 5
|
||||||
start_period: '20s'
|
start_period: 10s
|
||||||
|
|
||||||
|
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'
|
||||||
|
# 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
|
||||||
|
user: "${UID:-1000}"
|
||||||
|
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
|
||||||
|
depends_on:
|
||||||
|
zitadel:
|
||||||
|
condition: 'service_healthy'
|
||||||
|
login:
|
||||||
|
condition: 'service_started'
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
zitadel:
|
storage:
|
||||||
|
backend:
|
||||||
|
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data:
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
|
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
|
||||||
|
|
||||||
ExternalSecure: true
|
ExternalSecure: true
|
||||||
ExternalDomain: 127.0.0.1.sslip.io
|
|
||||||
ExternalPort: 443
|
ExternalPort: 443
|
||||||
|
|
||||||
# Traefik terminates TLS. Inside the Docker network, we use plain text.
|
# Traefik terminates TLS. Inside the Docker network, we use plain text.
|
||||||
@@ -16,12 +15,6 @@ Database:
|
|||||||
User.SSL.Mode: 'disable'
|
User.SSL.Mode: 'disable'
|
||||||
Admin.SSL.Mode: 'disable'
|
Admin.SSL.Mode: 'disable'
|
||||||
|
|
||||||
# By default, ZITADEL should redirect to /ui/v2/login
|
|
||||||
OIDC:
|
|
||||||
DefaultLoginURLV2: "/ui/v2/login/login?authRequest=" # ZITADEL_OIDC_DEFAULTLOGINURLV2
|
|
||||||
DefaultLogoutURLV2: "/ui/v2/login/logout?post_logout_redirect=" # ZITADEL_OIDC_DEFAULTLOGOUTURLV2
|
|
||||||
SAML.DefaultLoginURLV2: "/ui/v2/login/login?authRequest=" # ZITADEL_SAML_DEFAULTLOGINURLV2
|
|
||||||
|
|
||||||
# Access logs allow us to debug Network issues
|
# Access logs allow us to debug Network issues
|
||||||
LogStore.Access.Stdout.Enabled: true
|
LogStore.Access.Stdout.Enabled: true
|
||||||
|
|
@@ -1,12 +1,11 @@
|
|||||||
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/setup/steps.yaml
|
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/setup/steps.yaml
|
||||||
FirstInstance:
|
FirstInstance:
|
||||||
PatPath: '/pat'
|
LoginClientPatPath: '/current-dir/login-client-pat'
|
||||||
Org:
|
Org:
|
||||||
# We want to authenticate immediately at the console without changing the password
|
# We want to authenticate immediately at the console without changing the password
|
||||||
Human:
|
Human.PasswordChangeRequired: false
|
||||||
PasswordChangeRequired: false
|
LoginClient:
|
||||||
Machine:
|
Machine:
|
||||||
Machine:
|
Username: 'login-client'
|
||||||
Username: 'login-container'
|
Name: 'Automatically Initialized IAM Login Client'
|
||||||
Name: 'Login Container'
|
|
||||||
Pat.ExpirationDate: '2029-01-01T00:00:00Z'
|
Pat.ExpirationDate: '2029-01-01T00:00:00Z'
|
@@ -1 +0,0 @@
|
|||||||
.env-file
|
|
@@ -1,157 +0,0 @@
|
|||||||
services:
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: postgres:17-alpine
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
- POSTGRES_USER=root
|
|
||||||
- POSTGRES_PASSWORD=postgres
|
|
||||||
networks:
|
|
||||||
- 'storage'
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready", "-d", "db_prod"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 60s
|
|
||||||
retries: 5
|
|
||||||
start_period: 10s
|
|
||||||
volumes:
|
|
||||||
- 'data:/var/lib/postgresql/data:rw'
|
|
||||||
|
|
||||||
zitadel-init:
|
|
||||||
restart: 'no'
|
|
||||||
networks:
|
|
||||||
- 'storage'
|
|
||||||
image: 'ghcr.io/zitadel/zitadel:latest'
|
|
||||||
command: 'init --config /example-zitadel-config.yaml --config /example-zitadel-secrets.yaml'
|
|
||||||
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'
|
|
||||||
# We use the debug image so we have the environment to
|
|
||||||
# - create the .env file for the login to authenticate at Zitadel
|
|
||||||
# - set the correct permissions for the .env-file folder
|
|
||||||
image: 'ghcr.io/zitadel/zitadel:latest-debug'
|
|
||||||
user: root
|
|
||||||
entrypoint: '/bin/sh'
|
|
||||||
command:
|
|
||||||
- -c
|
|
||||||
- >
|
|
||||||
/app/zitadel setup
|
|
||||||
--config /example-zitadel-config.yaml
|
|
||||||
--config /example-zitadel-secrets.yaml
|
|
||||||
--steps /example-zitadel-init-steps.yaml
|
|
||||||
--masterkey ${ZITADEL_MASTERKEY} &&
|
|
||||||
mv /pat /.env-file/pat || exit 0 &&
|
|
||||||
echo ZITADEL_SERVICE_USER_TOKEN=$(cat /.env-file/pat) > /.env-file/.env &&
|
|
||||||
chown -R 1001:${GID} /.env-file &&
|
|
||||||
chmod -R 770 /.env-file
|
|
||||||
environment:
|
|
||||||
- GID
|
|
||||||
depends_on:
|
|
||||||
zitadel-init:
|
|
||||||
condition: 'service_completed_successfully'
|
|
||||||
restart: false
|
|
||||||
volumes:
|
|
||||||
- './.env-file:/.env-file:rw'
|
|
||||||
- './example-zitadel-config.yaml:/example-zitadel-config.yaml:ro'
|
|
||||||
- './example-zitadel-secrets.yaml:/example-zitadel-secrets.yaml:ro'
|
|
||||||
- './example-zitadel-init-steps.yaml:/example-zitadel-init-steps.yaml:ro'
|
|
||||||
|
|
||||||
zitadel:
|
|
||||||
restart: 'unless-stopped'
|
|
||||||
networks:
|
|
||||||
- 'backend'
|
|
||||||
- 'storage'
|
|
||||||
image: 'ghcr.io/zitadel/zitadel:latest'
|
|
||||||
command: >
|
|
||||||
start --config /example-zitadel-config.yaml
|
|
||||||
--config /example-zitadel-secrets.yaml
|
|
||||||
--masterkey ${ZITADEL_MASTERKEY}
|
|
||||||
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'
|
|
||||||
ports:
|
|
||||||
- "8080:8080"
|
|
||||||
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
|
|
||||||
|
|
||||||
# The use-new-login service configures Zitadel to use the new login v2 for all applications.
|
|
||||||
# It also gives the setupped machine user the necessary IAM_LOGIN_CLIENT role.
|
|
||||||
use-new-login:
|
|
||||||
restart: 'on-failure'
|
|
||||||
user: "1001"
|
|
||||||
networks:
|
|
||||||
- 'backend'
|
|
||||||
image: 'badouralix/curl-jq:alpine'
|
|
||||||
entrypoint: '/bin/sh'
|
|
||||||
command:
|
|
||||||
- -c
|
|
||||||
- >
|
|
||||||
curl -X PUT -H "Host: 127.0.0.1.sslip.io" -H "Authorization: Bearer $(cat ./.env-file/pat)" --insecure http://zitadel:8080/v2/features/instance -d '{"loginV2": {"required": true}}' &&
|
|
||||||
LOGIN_USER=$(curl --fail-with-body -H "Host: 127.0.0.1.sslip.io" -H "Authorization: Bearer $(cat ./.env-file/pat)" --insecure http://zitadel:8080/auth/v1/users/me | jq -r '.user.id') &&
|
|
||||||
curl -X PUT -H "Host: 127.0.0.1.sslip.io" -H "Authorization: Bearer $(cat ./.env-file/pat)" --insecure http://zitadel:8080/admin/v1/members/$${LOGIN_USER} -d '{"roles": ["IAM_OWNER", "IAM_LOGIN_CLIENT"]}'
|
|
||||||
volumes:
|
|
||||||
- './.env-file:/.env-file:ro'
|
|
||||||
depends_on:
|
|
||||||
zitadel:
|
|
||||||
condition: 'service_healthy'
|
|
||||||
restart: false
|
|
||||||
|
|
||||||
login:
|
|
||||||
restart: 'unless-stopped'
|
|
||||||
networks:
|
|
||||||
- 'backend'
|
|
||||||
image: 'ghcr.io/zitadel/login:main'
|
|
||||||
environment:
|
|
||||||
- ZITADEL_API_URL=http://zitadel:8080
|
|
||||||
- CUSTOM_REQUEST_HEADERS=Host:127.0.0.1.sslip.io
|
|
||||||
- NEXT_PUBLIC_BASE_PATH="/ui/v2/login"
|
|
||||||
user: "${UID:-1000}"
|
|
||||||
volumes:
|
|
||||||
- './.env-file:/.env-file:ro'
|
|
||||||
depends_on:
|
|
||||||
zitadel:
|
|
||||||
condition: 'service_healthy'
|
|
||||||
restart: false
|
|
||||||
|
|
||||||
traefik:
|
|
||||||
restart: 'unless-stopped'
|
|
||||||
networks:
|
|
||||||
- 'backend'
|
|
||||||
image: "traefik:latest"
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
volumes:
|
|
||||||
- "./example-traefik.yaml:/etc/traefik/traefik.yaml"
|
|
||||||
depends_on:
|
|
||||||
zitadel:
|
|
||||||
condition: 'service_healthy'
|
|
||||||
login:
|
|
||||||
condition: 'service_started'
|
|
||||||
|
|
||||||
networks:
|
|
||||||
storage:
|
|
||||||
backend:
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
data:
|
|
@@ -1,40 +0,0 @@
|
|||||||
log:
|
|
||||||
level: DEBUG
|
|
||||||
|
|
||||||
accessLog: {}
|
|
||||||
|
|
||||||
entrypoints:
|
|
||||||
websecure:
|
|
||||||
address: ":443"
|
|
||||||
|
|
||||||
providers:
|
|
||||||
file:
|
|
||||||
filename: /etc/traefik/traefik.yaml
|
|
||||||
|
|
||||||
http:
|
|
||||||
routers:
|
|
||||||
login:
|
|
||||||
entryPoints:
|
|
||||||
- websecure
|
|
||||||
service: login
|
|
||||||
rule: 'Host(`127.0.0.1.sslip.io`) && PathPrefix(`/ui/v2/login`)'
|
|
||||||
tls: {}
|
|
||||||
zitadel:
|
|
||||||
entryPoints:
|
|
||||||
- websecure
|
|
||||||
service: zitadel
|
|
||||||
rule: 'Host(`127.0.0.1.sslip.io`) && !PathPrefix(`/ui/v2/login`)'
|
|
||||||
tls: {}
|
|
||||||
|
|
||||||
services:
|
|
||||||
login:
|
|
||||||
loadBalancer:
|
|
||||||
servers:
|
|
||||||
- url: http://login:3000
|
|
||||||
passHostHeader: true
|
|
||||||
zitadel:
|
|
||||||
loadBalancer:
|
|
||||||
servers:
|
|
||||||
- url: h2c://zitadel:8080
|
|
||||||
passHostHeader: true
|
|
||||||
|
|
@@ -1,74 +0,0 @@
|
|||||||
---
|
|
||||||
title: A Zitadel Load Balancing Example
|
|
||||||
---
|
|
||||||
|
|
||||||
import CodeBlock from '@theme/CodeBlock';
|
|
||||||
import DockerComposeSource from '!!raw-loader!./docker-compose.yaml'
|
|
||||||
import ExampleTraefikSource from '!!raw-loader!./example-traefik.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'
|
|
||||||
|
|
||||||
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.0.4 and Docker Compose version v2.34.0
|
|
||||||
|
|
||||||
By executing the commands below, you will download the following files:
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>docker-compose.yaml</summary>
|
|
||||||
<CodeBlock language="yaml">{DockerComposeSource}</CodeBlock>
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>example-traefik.yaml</summary>
|
|
||||||
<CodeBlock language="yaml">{ExampleTraefikSource}</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/loadbalancing-example/docker-compose.yaml
|
|
||||||
|
|
||||||
# Download the Traefik example configuration.
|
|
||||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/loadbalancing-example/example-traefik.yaml
|
|
||||||
|
|
||||||
# Download and adjust the example configuration file containing standard configuration.
|
|
||||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/loadbalancing-example/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/loadbalancing-example/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/loadbalancing-example/example-zitadel-init-steps.yaml
|
|
||||||
|
|
||||||
# A single ZITADEL instance always needs the same 32 bytes long masterkey
|
|
||||||
# Generate one to a file if you haven't done so already and pass it as environment variable
|
|
||||||
LC_ALL=C tr -dc '[:graph:]' </dev/urandom | head -c 32 > ./zitadel-masterkey
|
|
||||||
export ZITADEL_MASTERKEY="$(cat ./zitadel-masterkey)"
|
|
||||||
|
|
||||||
# Run the database and application containers
|
|
||||||
docker compose up --detach --wait
|
|
||||||
```
|
|
||||||
|
|
||||||
Open your favorite internet browser at https://127.0.0.1.sslip.io/ui/console?login_hint=zitadel-admin@zitadel.127.0.0.1.sslip.io.
|
|
||||||
Your browser warns you about the insecure self-signed TLS certificate. As 127.0.0.1.sslip.io resolves to your localhost, you can safely proceed.
|
|
||||||
Use the password *Password1!* to log in.
|
|
||||||
|
|
||||||
Read more about [the login process](/guides/integrate/login/oidc/login-users).
|
|
@@ -1084,7 +1084,6 @@ module.exports = {
|
|||||||
"self-hosting/deploy/devcontainer",
|
"self-hosting/deploy/devcontainer",
|
||||||
"self-hosting/deploy/knative",
|
"self-hosting/deploy/knative",
|
||||||
"self-hosting/deploy/kubernetes",
|
"self-hosting/deploy/kubernetes",
|
||||||
"self-hosting/deploy/loadbalancing-example/loadbalancing-example",
|
|
||||||
"self-hosting/deploy/troubleshooting/troubleshooting",
|
"self-hosting/deploy/troubleshooting/troubleshooting",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user