| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .idea | ||
| configs | ||
| .env | ||
| .gitignore | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| docker-compose.yml | ||
| LICENSE | ||
| Projekt.md | ||
| README.md | ||
Zitadel – Zentraler Login / IdP (Stack-Template)
Selbst gehostete Identity-Plattform (OIDC) auf dem Hetzner-Server. Stellt einen
einzigen, zentralen Login https://login.example.com bereit, den interne
und externe Mandanten (IHR_PROJEKT, MANDANT_2) nutzen. TLS macht das vorhandene
zentrale Traefik, Zitadel laeuft als reiner Service dahinter.
Template-Hinweis: Dieses Repo enthaelt nur Platzhalter (
CHANGE_ME,example.com). Vor dem Produktiveinsatz alle Platzhalter in der.envundconfigs/firstinstance.yamlersetzen.
1. Voraussetzungen
-
Docker + Docker Compose v2 auf dem Hetzner-Server
-
Das zentrale Traefik laeuft dort bereits (Entrypoints
web-http/websecure-https, certresolverletsEncrypt, Middlewaresredirect-to-https@file/security-headers@file) -
Das externe Docker-Netz existiert:
docker network create traefik_proxy_network # falls noch nicht vorhanden -
DNS-A-Record zeigt auf die oeffentliche Hetzner-IP:
login.example.com -> <oeffentliche Hetzner-IP>
2. Einrichtung (Schritt fuer Schritt)
-
.envanpassen (alle Platzhalter ersetzen):-
ZITADEL_EXTERNALDOMAIN/HOSTRULE→ eure Login-Domain -
ZITADEL_MASTERKEY→ 32-Zeichen-Key:openssl rand -base64 32 | tr -d '+/=' | cut -c1-32 -
PG_PASSWORD→ sicheres Passwort:openssl rand -base64 24 -
SMTP (
SMTP_HOST,SMTP_USER,SMTP_PASSWORD,SMTP_FROM,SMTP_FROMNAME,SMTP_TLS) → Daten des Mailproviders. Siehe Abschnitt SMTP unten.
-
-
configs/firstinstance.yamlanpassen: Org-Name (= erster Mandant), Admin-Email und initialesPasswordsetzen. -
Image-Tag pinnen: in
docker-compose.ymldie aktuelle stable eintragen (https://github.com/zitadel/zitadel/releases). -
Starten:
docker compose up -dDer Ordner
volumes/wird beim ersten Start automatisch erstellt (ist in.gitignore– kommt niemals ins Git). -
Logs pruefen – erwartete Erfolgsmeldung:
docker logs zitadel --tail 30TLS enabled : false External Secure : true Console URL : https://login.example.com/ui/console server is listening on [::]:8080
3. Echten Admin-Login ermitteln (wichtig!)
Zitadel baut den Login-Namen nicht aus UserName@ExternalDomain, sondern aus
UserName@<org-domain-aus-org-namen>.<ExternalDomain>. Den exakten Namen niemals raten,
sondern direkt aus der DB holen:
docker exec zitadel-db psql -U zitadel -d zitadel \
-c "SELECT user_id, login_name, is_primary FROM projections.login_names3;"
Beispiel: aus Org IHR_PROJEKT + Domain login.example.com wird:
admin@ihr-projekt.login.example.com
Erster Login: https://login.example.com/ui/console mit diesem Namen und
dem in firstinstance.yaml gesetzten Passwort. Wegen PasswordChangeRequired: true
fordert Zitadel sofort zur Passwortaenderung auf (danach 2FA einrichten).
4. Worauf besonders achten (Stolpersteine)
- gRPC / h2c: Der Traefik-Service muss auf
scheme=h2cstehen (ist gesetzt). Ohne das laedt zwar die Login-Seite, aber die Console haengt. --tlsMode external: Pflicht, weil Traefik TLS terminiert. Ohne TLS-Mode bricht Zitadel mit "TLS is enabled: please specify a key/cert or disable TLS" ab.disabledwaere falsch (dann erzeugt Zitadel http-URLs hinter https-Traefik).--steps /firstinstance.yamlmuss imcommandstehen und der Volume-Mount aktiv sein, sonst legt Zitadel den Default-Admin (zitadel-admin) an.- ExternalDomain ist im Issuer eingebrannt. Nachtraeglich aendern = Re-Init.
- SMTP nur an DefaultInstance, nicht FirstInstance. SMTP in
firstinstance.yamlwird ignoriert. Siehe Abschnitt SMTP.
SMTP / Mailversand
Zitadel braucht SMTP fuer Verifizierungs-, Einladungs- und Passwort-Mails. Ohne
Config scheitert jede Mail mit Errors.SMTPConfig.NotFound.
Wichtig: SMTP laesst sich nur an DefaultInstance vorkonfigurieren, nicht
an FirstInstance. Deshalb erfolgt die Konfiguration ueber Env-Variablen
(ZITADEL_DEFAULTINSTANCE_SMTPCONFIGURATION_* in docker-compose.yml), die Werte
stehen in der .env (SMTP_*).
- Greift nur beim allerersten Start (leere DB). Bei bestehender Instanz: Console → Default Settings → Notifications → SMTP Settings.
SMTP_FROMundSMTP_FROMNAMEmuessen gesetzt sein (leer = Init-Fehler, vgl. https://github.com/zitadel/zitadel/issues/7009).SMTP_TLS=true→ implizites TLS (Port 465);false→ STARTTLS (Port 587).SMTP_HOSTimmer mit Port, z. B.smtp.provider.de:587.- Fuer Zustellbarkeit am Absender-Domain SPF/DKIM hinterlegen (sonst Spam).
Nach dem Start pruefen, ob der Mail-Kanal sauber initialisiert wurde:
docker logs zitadel 2>&1 | grep -i smtp
5. Re-Init (kompletter Neuaufbau)
docker compose up -d bei laufendem Container startet ihn nur neu, durchlaeuft aber
start-from-init nicht erneut. Fuer einen sauberen Neuaufbau die DB zuruecksetzen:
docker compose down
sudo rm -rf volumes/db # DB-Datenverzeichnis leeren
docker compose up -d
6. OIDC-Clients anbinden (spaeter)
Pro Anwendung (cf-review, Metabase, NocoDB, n8n, ...) in der jeweiligen Org eine
Application anlegen und dort Issuer, Client-ID/Secret und die Redirect-URIs
hinterlegen. Der Issuer ist fuer alle identisch:
https://login.example.com
7. Nuetzliche Befehle
docker compose config -q # Konfiguration validieren (.env-Aufloesung)
docker compose up -d # Starten
docker compose logs -f zitadel # Live-Logs
docker compose down # Stoppen
Lizenz
Copyright (C) 2026 Christian Säum – web-seo-consulting.eu
Dieses Projekt steht unter der GNU Affero General Public License, Version 3
oder (nach deiner Wahl) einer späteren Version (AGPL-3.0-or-later). Der
vollständige Lizenztext steht in der Datei LICENSE.
Du darfst die Software nutzen, weitergeben und – auch kommerziell – verkaufen.
Gibst du eine veränderte Fassung weiter oder betreibst du sie über ein
Netzwerk (z. B. als Dienst), muss deren vollständiger Quellcode ebenfalls
unter der AGPL-3.0-or-later verfügbar sein. Der Copyright-Hinweis und die
Nennung des ursprünglichen Autors dürfen nicht entfernt werden.
Diese Angabe betrifft nur die in diesem Repository enthaltenen eigenen Dateien (Konfiguration, Skripte, Anpassungen). Eingebundene Fremdsoftware und Container-Images unterliegen weiterhin ihren eigenen Lizenzen.