diff --git a/docs/docs/self-hosting/deploy/.gitignore b/docs/docs/self-hosting/deploy/.gitignore
new file mode 100644
index 0000000000..83754bbee4
--- /dev/null
+++ b/docs/docs/self-hosting/deploy/.gitignore
@@ -0,0 +1 @@
+login-client-pat
diff --git a/docs/docs/self-hosting/deploy/compose.mdx b/docs/docs/self-hosting/deploy/compose.mdx
index 370c0e7f5d..f47a33da16 100644
--- a/docs/docs/self-hosting/deploy/compose.mdx
+++ b/docs/docs/self-hosting/deploy/compose.mdx
@@ -1,67 +1,65 @@
---
-title: Set up ZITADEL with Docker Compose
+title: Set up Zitadel with Docker Compose
sidebar_label: Docker Compose
---
import CodeBlock from '@theme/CodeBlock';
import DockerComposeSource from '!!raw-loader!./docker-compose.yaml'
-import DockerComposeSaSource from '!!raw-loader!./docker-compose-sa.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';
+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 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:
docker-compose.yaml
{DockerComposeSource}
+
+ example-zitadel-config.yaml
+ {ExampleZitadelConfigSource}
+
+
+ example-zitadel-secrets.yaml
+ {ExampleZitadelSecretsSource}
+
+
+ example-zitadel-init-steps.yaml
+ {ExampleZitadelInitStepsSource}
+
```bash
# Download the docker compose example configuration.
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/docker-compose.yaml
-# Run the database and application containers.
-docker compose up --detach
+# 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
+docker compose pull
+
+# Run the containers
+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.
-
-
-## VideoGuide
-
-
-## Docker compose with service account
-
-By executing the commands below, you will download the following file:
-
-
- docker-compose-sa.yaml
- {DockerComposeSaSource}
-
-
-```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).
-
-
-
+Read more about [the login process](/guides/integrate/login/oidc/login-users).
\ No newline at end of file
diff --git a/docs/docs/self-hosting/deploy/docker-compose-sa.yaml b/docs/docs/self-hosting/deploy/docker-compose-sa.yaml
deleted file mode 100644
index 9edd95faa0..0000000000
--- a/docs/docs/self-hosting/deploy/docker-compose-sa.yaml
+++ /dev/null
@@ -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:
diff --git a/docs/docs/self-hosting/deploy/docker-compose.yaml b/docs/docs/self-hosting/deploy/docker-compose.yaml
index f5164eb3b7..23d651efc9 100644
--- a/docs/docs/self-hosting/deploy/docker-compose.yaml
+++ b/docs/docs/self-hosting/deploy/docker-compose.yaml
@@ -1,41 +1,117 @@
services:
- zitadel:
- restart: 'always'
- networks:
- - 'zitadel'
- image: 'ghcr.io/zitadel/zitadel:latest'
- command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled'
+
+ db:
+ image: postgres:17-alpine
+ restart: unless-stopped
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
+ - 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:v4.0.0-rc.2'
+ command: [ init, --config, /example-zitadel-config.yaml, --config, /example-zitadel-secrets.yaml ]
depends_on:
db:
condition: 'service_healthy'
- ports:
- - '8080:8080'
+ volumes:
+ - './example-zitadel-config.yaml:/example-zitadel-config.yaml:ro'
+ - './example-zitadel-secrets.yaml:/example-zitadel-secrets.yaml:ro'
- db:
- restart: 'always'
- image: postgres:17-alpine
- environment:
- PGUSER: postgres
- POSTGRES_PASSWORD: postgres
+ zitadel-setup:
+ restart: 'no'
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:
- test: ["CMD-SHELL", "pg_isready", "-d", "zitadel", "-U", "postgres"]
- interval: '10s'
- timeout: '30s'
+ test: [ "CMD", "/app/zitadel", "ready", "--config", "/example-zitadel-config.yaml", "--config", "/example-zitadel-secrets.yaml" ]
+ interval: 10s
+ timeout: 60s
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:
- zitadel:
+ storage:
+ backend:
+
+
+volumes:
+ data:
diff --git a/docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-config.yaml b/docs/docs/self-hosting/deploy/example-zitadel-config.yaml
similarity index 60%
rename from docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-config.yaml
rename to docs/docs/self-hosting/deploy/example-zitadel-config.yaml
index af5bb5145c..baacd6cefe 100644
--- a/docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-config.yaml
+++ b/docs/docs/self-hosting/deploy/example-zitadel-config.yaml
@@ -1,7 +1,6 @@
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
ExternalSecure: true
-ExternalDomain: 127.0.0.1.sslip.io
ExternalPort: 443
# Traefik terminates TLS. Inside the Docker network, we use plain text.
@@ -16,14 +15,8 @@ Database:
User.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
LogStore.Access.Stdout.Enabled: true
# Skipping the MFA init step allows us to immediately authenticate at the console
-DefaultInstance.LoginPolicy.MfaInitSkipLifetime: "0s"
\ No newline at end of file
+DefaultInstance.LoginPolicy.MfaInitSkipLifetime: "0s"
diff --git a/docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-init-steps.yaml b/docs/docs/self-hosting/deploy/example-zitadel-init-steps.yaml
similarity index 58%
rename from docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-init-steps.yaml
rename to docs/docs/self-hosting/deploy/example-zitadel-init-steps.yaml
index 9bdf41269d..373c6ae744 100644
--- a/docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-init-steps.yaml
+++ b/docs/docs/self-hosting/deploy/example-zitadel-init-steps.yaml
@@ -1,12 +1,11 @@
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/setup/steps.yaml
FirstInstance:
- PatPath: '/pat'
+ LoginClientPatPath: '/current-dir/login-client-pat'
Org:
# We want to authenticate immediately at the console without changing the password
- Human:
- PasswordChangeRequired: false
- Machine:
+ Human.PasswordChangeRequired: false
+ LoginClient:
Machine:
- Username: 'login-container'
- Name: 'Login Container'
+ Username: 'login-client'
+ Name: 'Automatically Initialized IAM Login Client'
Pat.ExpirationDate: '2029-01-01T00:00:00Z'
\ No newline at end of file
diff --git a/docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-secrets.yaml b/docs/docs/self-hosting/deploy/example-zitadel-secrets.yaml
similarity index 100%
rename from docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-secrets.yaml
rename to docs/docs/self-hosting/deploy/example-zitadel-secrets.yaml
diff --git a/docs/docs/self-hosting/deploy/loadbalancing-example/.gitignore b/docs/docs/self-hosting/deploy/loadbalancing-example/.gitignore
deleted file mode 100644
index 8a28618b17..0000000000
--- a/docs/docs/self-hosting/deploy/loadbalancing-example/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-.env-file
\ No newline at end of file
diff --git a/docs/docs/self-hosting/deploy/loadbalancing-example/docker-compose.yaml b/docs/docs/self-hosting/deploy/loadbalancing-example/docker-compose.yaml
deleted file mode 100644
index 96a87fa8d7..0000000000
--- a/docs/docs/self-hosting/deploy/loadbalancing-example/docker-compose.yaml
+++ /dev/null
@@ -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:
\ No newline at end of file
diff --git a/docs/docs/self-hosting/deploy/loadbalancing-example/example-traefik.yaml b/docs/docs/self-hosting/deploy/loadbalancing-example/example-traefik.yaml
deleted file mode 100644
index a3af425172..0000000000
--- a/docs/docs/self-hosting/deploy/loadbalancing-example/example-traefik.yaml
+++ /dev/null
@@ -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
-
diff --git a/docs/docs/self-hosting/deploy/loadbalancing-example/loadbalancing-example.mdx b/docs/docs/self-hosting/deploy/loadbalancing-example/loadbalancing-example.mdx
deleted file mode 100644
index 3fb4784ea0..0000000000
--- a/docs/docs/self-hosting/deploy/loadbalancing-example/loadbalancing-example.mdx
+++ /dev/null
@@ -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:
-
-
- docker-compose.yaml
- {DockerComposeSource}
-
-
- example-traefik.yaml
- {ExampleTraefikSource}
-
-
- example-zitadel-config.yaml
- {ExampleZITADELConfigSource}
-
-
- example-zitadel-secrets.yaml
- {ExampleZITADELSecretsSource}
-
-
- example-zitadel-init-steps.yaml
- {ExampleZITADELInitStepsSource}
-
-
-```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:]' ./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).
\ No newline at end of file
diff --git a/docs/sidebars.js b/docs/sidebars.js
index 578a337da9..105251f20c 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -1084,7 +1084,6 @@ module.exports = {
"self-hosting/deploy/devcontainer",
"self-hosting/deploy/knative",
"self-hosting/deploy/kubernetes",
- "self-hosting/deploy/loadbalancing-example/loadbalancing-example",
"self-hosting/deploy/troubleshooting/troubleshooting",
],
},