Files
zitadel/apps/docs/content/self-hosting/deploy/kubernetes/installation.mdx
T
Florian ForsterandGitHub 413f8ba585 docs: add missing k8s example (#11474)
This pull request significantly expands and restructures the Kubernetes
deployment documentation for Zitadel. It introduces detailed,
task-focused guides for installation, configuration, ingress, and
database setup, replacing the previous minimal documentation. The new
docs provide comprehensive instructions and best practices for deploying
Zitadel on Kubernetes using Helm, including security, scaling, and high
availability considerations.

The most important changes are:

**Documentation Restructuring and Overview**
- Added a new `index.mdx` providing an overview of the Zitadel Helm
chart, architecture, prerequisites, and quick links to relevant
resources and next steps.
- Removed the old minimal Kubernetes deployment page and replaced it
with a structured, multi-page documentation set.

**Installation and Setup**
- Added an `installation.mdx` guide with step-by-step instructions for
preparing prerequisites, creating Kubernetes secrets, configuring
`values.yaml`, installing the Helm chart, and verifying the deployment.

**Configuration and Best Practices**
- Added a `configuration.mdx` guide covering Helm chart configuration
options, including replica count, container images, security contexts,
external domain setup, secrets management, scaling, autoscaling, pod
disruption budgets, and anti-affinity rules.

**Ingress and Database Configuration**
- Added an `ingress.mdx` guide detailing how to configure Kubernetes
ingress resources for Zitadel and Login containers, including TLS
termination and certificate management.
- Added a `database.mdx` guide explaining how to connect Zitadel to
PostgreSQL with various TLS/security options and how to manage database
credentials and certificates using Kubernetes secrets.
2026-01-30 08:27:01 +01:00

226 lines
5.6 KiB
Plaintext

---
title: Installation
sidebar_label: Installation
---
This guide walks you through deploying Zitadel on Kubernetes using Helm.
## Prerequisites
You need a running Kubernetes cluster. Supported versions:
- Kubernetes 1.30.13+
- Kubernetes 1.31.9+
- Kubernetes 1.32.5+
- Kubernetes 1.33.1+
### An Ingress Controller
Zitadel requires an ingress controller to route traffic to the Zitadel and Login pods. The chart creates standard Kubernetes Ingress resources that work with any ingress controller, including Traefik, NGINX, and cloud-native options like AWS ALB or GCP Cloud Load Balancer.
TLS must be terminated at the ingress controller. The Zitadel and Login containers do not handle TLS termination. Your ingress controller is responsible for obtaining and renewing TLS certificates (via ACME, cert-manager, or manually), terminating TLS connections, and forwarding traffic to the Zitadel pods.
Without an ingress controller and valid TLS certificates, Zitadel will not work. The chart configures the ingress to use HTTP/2 for communication between the ingress controller and Zitadel pods.
### A PostgreSQL Database
Zitadel requires PostgreSQL 14 or later. You can use a managed PostgreSQL service such as Amazon RDS, Google Cloud SQL, or Azure Database for PostgreSQL, or run PostgreSQL in your cluster using a Helm chart or operator. The database must be accessible from the Zitadel pods.
Zitadel uses two database users: an admin user for schema migrations and an application user for normal operations. See the [Database](./database) page for connection options.
### Helm
Install Helm 3.x or 4.x following the [official instructions](https://helm.sh/docs/intro/install/). Verify your installation:
```bash
helm version
```
### kubectl
Install kubectl following the [Kubernetes documentation](https://kubernetes.io/docs/tasks/tools/). Verify connectivity to your cluster:
```bash
kubectl cluster-info
```
## Add the Helm Repository
Add the Zitadel Helm repository:
```bash
helm repo add zitadel https://charts.zitadel.com
```
Update your local repository cache:
```bash
helm repo update
```
Verify the repository was added:
```bash
helm search repo zitadel
```
You should see output similar to:
```
NAME CHART VERSION APP VERSION DESCRIPTION
zitadel/zitadel 9.x.x v4.x.x A Helm chart for Zitadel
```
## Install
### Step 1: Create Secrets
Create the masterkey secret:
```bash
kubectl create secret generic zitadel-masterkey \
--from-literal=masterkey="$(tr -dc A-Za-z0-9 </dev/urandom | head -c 32)"
```
Create the database credentials secret:
```bash
kubectl create secret generic zitadel-db-credentials \
--from-literal=config.yaml="
Database:
Postgres:
User:
Password: your-secure-app-password
Admin:
Password: your-secure-admin-password
"
```
### Step 2: Configure Values
Create a `values.yaml` file. Replace `zitadel.example.com` with your actual domain:
```yaml
replicaCount: 2
zitadel:
masterkeySecretName: zitadel-masterkey
configSecretName: zitadel-db-credentials
configmapConfig:
ExternalDomain: "zitadel.example.com"
ExternalSecure: true
ExternalPort: 443
TLS:
Enabled: false
Database:
Postgres:
Host: "postgres.database.svc.cluster.local"
Port: 5432
Database: "zitadel"
User:
Username: "zitadel"
SSL:
Mode: "verify-full"
Admin:
Username: "postgres"
SSL:
Mode: "verify-full"
FirstInstance:
Org:
Human:
UserName: "admin"
FirstName: "Zitadel"
LastName: "Admin"
Email: "[email protected]"
Password: "YourSecurePassword123!"
PasswordChangeRequired: true
ingress:
enabled: true
className: traefik
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
hosts:
- host: zitadel.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: zitadel-tls
hosts:
- zitadel.example.com
podDisruptionBudget:
enabled: true
minAvailable: 1
```
### Step 3: Install the Chart
```bash
helm install zitadel zitadel/zitadel --values values.yaml
```
Install Zitadel:
```bash
helm install my-zitadel zitadel/zitadel --values values.yaml
```
## Verify Deployment
Watch the pods come up:
```bash
kubectl get pods --watch
```
You should see:
1. `my-zitadel-init-*` job completes
2. `my-zitadel-setup-*` job completes
3. `my-zitadel-*` deployment pods become Ready
Check the deployment status:
```bash
helm status my-zitadel
```
Verify all pods are running:
```bash
kubectl get pods --selector app.kubernetes.io/name=zitadel
```
You should see output similar to:
```
NAME READY STATUS RESTARTS AGE
my-zitadel-xxxxxxxxx-xxxxx 1/1 Running 0 5m
my-zitadel-xxxxxxxxx-xxxxx 1/1 Running 0 5m
```
## Access the UI
Access Zitadel at:
```
https://zitadel.example.com/ui/console
```
## First Login
Access the console at `https://zitadel.example.com/ui/console` and log in with the admin credentials configured in your `values.yaml`.
## Next Steps
- [Configuration](./configuration) — Customize Zitadel settings
- [Configuring the Ingress](./ingress) — Set up ingress for Zitadel and Login containers
- [Configuring the Database](./database) — Connect to PostgreSQL
- [Operations](./operations) — Learn about upgrades and scaling
- [Uninstalling](./uninstalling) — Remove Zitadel from your cluster