Kurzüberblick
SSO braucht eine reproduzierbare Identity-Plattform, saubere Zertifikate, kontrollierte Clients und nachvollziehbare Federation- oder LDAP-Anbindung.
Der Beitrag baut Keycloak mit Podman beziehungsweise der jeweiligen Integrationsaufgabe Schritt für Schritt auf und zeigt die sicherheitsrelevanten Entscheidungen.
Teams erhalten eine belastbare Basis für SSO, MFA, Federation, zentrale Anmeldung und sichere Anwendungsintegration.
Getestete Umgebung / Validierung
Stand: September 2026
Produkt & Version: Keycloak 26.x
Infrastruktur: getrennte Keycloak-Referenzinstanzen mit Podman, PostgreSQL und TLS
Sicherheit: Admin-Passwörter, Client-Secrets und interne Tokens werden durch Platzhalter ersetzt.
1. Ausgangslage & Voraussetzungen
Ausgangspunkt ist eine leere oder gezielt getrennte Keycloak-Instanz. DNS, TLS, persistente Volumes, Datenbank, Reverse Proxy und Truststore müssen vor produktiver Nutzung bewusst vorbereitet werden.
2. Schritt-für-Schritt-Anleitung
Die folgenden Schritte beschreiben den praktischen Ablauf. Führe sie in der angegebenen Reihenfolge aus und prüfe nach jedem größeren Abschnitt das Ergebnis.
In diesem ersten Teil der Keycloak-Serie baust du Keycloak 26.7.3 bewusst ohne Ansible auf: Podman, PostgreSQL, fester Hostname, erster Login, Admin-Konsole, Basis-Härtung, Zertifikate und Betriebschecks. IdM-Anbindung, Keycloak-Federation und Theming kommen danach als eigene Beiträge, damit jeder Schritt für sich nachvollziehbar bleibt.
Der Lab-Aufbau wurde mit den offiziellen Images `quay.io/keycloak/keycloak:26.7.3` und `docker.io/library/postgres:16-alpine` getestet. Der lokale Endpunkt war `http://127.0.0.1:18080`; produktiv ersetzt du ihn durch deinen echten SSO-FQDN, zum Beispiel `https://sso.example.test`.
Warum Keycloak im Container betreiben?
Container trennen Anwendung, Laufzeit und Host sauberer als eine klassische Paketinstallation. Du bekommst reproduzierbare Versionen, schnelle Rollbacks, klarere Updates, weniger Drift zwischen Test und Produktion und eine bessere Grundlage für spätere Automatisierung. Gerade Keycloak profitiert davon, weil Datenbank, Theme-Dateien, Reverse Proxy und Serverversion getrennt geplant werden können.
Der Container ersetzt aber kein Betriebskonzept. PostgreSQL-Daten, Secrets, TLS, Backups, Monitoring, Updates und Admin-Zugriffe müssen weiterhin sauber gelöst werden. Dieser Beitrag zeigt deshalb nicht nur “Container starten”, sondern den Weg zu einer belastbaren SSO-Basis.
Voraussetzungen
Du brauchst einen Linux-Server oder eine VM mit Podman, ausgehendem Internetzugriff für die Images, DNS für den späteren SSO-Namen, eine klare Zeitzone und ausreichend Ressourcen. Für kleine Testumgebungen reichen oft 2 vCPU und 4 GB RAM; produktiv planst du nach Benutzerzahl, Realm-Komplexität, Login-Last, Datenbankgröße und Hochverfügbarkeitsanforderung.
podman --versionpodman infohostnamectltimedatectl
Schritt 1: Netzwerk und Volume anlegen
Lege zuerst ein eigenes Podman-Netzwerk und ein persistentes Volume für PostgreSQL an. Damit bleiben Datenbankdaten erhalten, auch wenn du den PostgreSQL-Container neu erstellst.
podman network create forgeone-keycloak-labpodman volume create forgeone-keycloak-postgrespodman network lspodman volume ls
Schritt 2: Images gezielt pinnen
Verwende keine unkontrollierten `latest`-Tags. Für diesen Lab wurde Keycloak 26.7.3 verwendet. In Produktion dokumentierst du die Version, prüfst Release Notes und testest Updates zuerst außerhalb der produktiven Umgebung.
podman pull docker.io/library/postgres:16-alpinepodman pull quay.io/keycloak/keycloak:26.7.3podman image list | grep -E 'keycloak|postgres'
Schritt 3: PostgreSQL starten
Keycloak braucht eine externe Datenbank. Für den ersten nachvollziehbaren Aufbau reicht PostgreSQL als eigener Container. Das Passwort im Beispiel ist ein Lab-Wert und muss in echten Umgebungen durch ein Secret ersetzt werden.
podman run -d --name forgeone-keycloak-postgres \--network forgeone-keycloak-lab \-e POSTGRES_DB=keycloak \-e POSTGRES_USER=keycloak \-e POSTGRES_PASSWORD=change-me-lab-only \-v forgeone-keycloak-postgres:/var/lib/postgresql/data:Z \docker.io/library/postgres:16-alpinepodman logs --tail=50 forgeone-keycloak-postgres
Schritt 4: Keycloak starten
Jetzt startest du Keycloak gegen PostgreSQL. Für das lokale Lab wird HTTP auf `127.0.0.1:18080` veröffentlicht. Produktiv gehört davor ein Reverse Proxy mit TLS; Keycloak selbst bleibt intern erreichbar.
podman run -d --name forgeone-keycloak-lab \--network forgeone-keycloak-lab \-p 127.0.0.1:18080:8080 \-e KC_DB=postgres \-e KC_DB_URL=jdbc:postgresql://forgeone-keycloak-postgres:5432/keycloak \-e KC_DB_USERNAME=keycloak \-e KC_DB_PASSWORD=change-me-lab-only \-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \-e KC_BOOTSTRAP_ADMIN_PASSWORD=change-me-lab-only \quay.io/keycloak/keycloak:26.7.3 \start --http-enabled=true --hostname=http://127.0.0.1:18080 --health-enabled=true --metrics-enabled=true
Schritt 5: Start und Discovery prüfen
Warte, bis der Realm-Endpunkt erreichbar ist. Erst dann ist die Oberfläche sinnvoll testbar. Der Discovery-Endpunkt zeigt unter anderem den Issuer, den Authorization Endpoint und den Token Endpoint.
podman ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}"curl -fsS http://127.0.0.1:18080/realms/master/.well-known/openid-configuration | jq '.issuer'
Schritt 6: Admin-Konsole öffnen
Öffne `http://127.0.0.1:18080/admin/`. Beim ersten Login verwendest du den Bootstrap-Admin aus den Umgebungsvariablen. Direkt danach legst du einen echten Admin-Benutzer an und entfernst den temporären Bootstrap-Zugang. Keycloak weist selbst darauf hin.
Schritt 7: Realm-Basis prüfen
Für den Start ist der `master`-Realm vorhanden. Produktiv solltest du den `master`-Realm nicht als Sammelort für Anwendungen verwenden. Er dient primär zur Administration. Für Anwendungen legst du eigene Realms oder mindestens sauber getrennte Clients an.
Schritt 8: Clients verstehen
Clients sind Anwendungen, die Keycloak für Login und Tokens verwenden. Beispiele sind ein CMS, grommunio Web, OpenProject, XWiki oder ein internes Portal. In diesem Teil prüfen wir nur, wo Clients verwaltet werden. Die konkrete Client-Konfiguration folgt in den separaten Integrationsbeiträgen.
Schritt 9: Reverse Proxy und TLS vorbereiten
Produktiv sollte Keycloak nicht direkt über den Container-Port veröffentlicht werden. Der übliche Weg ist ein Reverse Proxy auf `https://sso.example.test`, der an `127.0.0.1:8080` oder einen internen Container-Port weiterleitet. Wichtig sind Host-Header und Forwarded-Header, damit Issuer und Redirect-URIs stimmen.
server {listen 443 ssl http2;server_name sso.example.test;ssl_certificate /etc/letsencrypt/live/sso.example.test/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/sso.example.test/privkey.pem;location / {proxy_pass http://127.0.0.1:8080;proxy_set_header Host $host;proxy_set_header X-Forwarded-Host $host;proxy_set_header X-Forwarded-Proto https;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}}
Schritt 10: Eigene CAs und Truststore
Wenn Keycloak gegen interne LDAP-, IdM-, SMTP- oder HTTPS-Systeme spricht, muss Keycloak deren Zertifikatskette vertrauen. Lege interne CA-Zertifikate versioniert ab und importiere sie in einen Truststore oder binde sie über die von Keycloak unterstützte Truststore-Konfiguration ein.
mkdir -p /opt/keycloak/conf/truststorescp company-root-ca.pem /opt/keycloak/conf/truststores/company-root-ca.pem# Beispiel mit PKCS12-Truststore:keytool -importcert -noprompt \-alias company-root-ca \-file /opt/keycloak/conf/truststores/company-root-ca.pem \-keystore /opt/keycloak/conf/truststores/keycloak-truststore.p12 \-storetype PKCS12
Schritt 11: Basis-Härtung
Nach dem ersten Start ersetzt du Lab-Passwörter, schützt Secret-Dateien, entfernst temporäre Admin-Zugänge, aktivierst MFA für Administratoren und begrenzt öffentliche Ports. Außerdem sollten Logs, Health Checks, Backups und Updates in den normalen Betrieb überführt werden.
podman inspect forgeone-keycloak-lab --format '{{.ImageName}}'podman logs --tail=200 forgeone-keycloak-labss -tulpn | grep -E ':18080|:8080|:5432'
Schritt 12: Backup und Restore testen
Keycloak-Konfiguration liegt hauptsächlich in der Datenbank. Deshalb reicht ein Container-Backup nicht aus. Sichere PostgreSQL, Compose- oder systemd-Dateien, Theme-Dateien, Zertifikatsmaterial, Truststores und die Betriebsdokumentation.
podman exec forgeone-keycloak-postgres pg_dump -U keycloak -d keycloak -Fc > keycloak-lab.dumpls -lh keycloak-lab.dump# Restore immer zuerst in einer isolierten Testumgebung prüfen.
Schritt 13: Secrets aus Umgebungsvariablen herausziehen
Die `podman run`-Variante ist gut zum Lernen, aber echte Passwörter gehören nicht dauerhaft in Shell-History, Prozesslisten oder Dokumentation. Der nächste saubere Schritt ist eine Verzeichnisstruktur mit restriktiven Rechten. Secrets liegen in Dateien, die nur der Betriebsbenutzer lesen kann.
install -d -m 0750 /opt/keycloak/{compose,conf,backups,themes}install -m 0640 /dev/null /opt/keycloak/conf/kc_db_passwordinstall -m 0640 /dev/null /opt/keycloak/conf/kc_admin_passwordchown -R svc-keycloak:svc-keycloak /opt/keycloak# Passwörter interaktiv setzen, nicht in die Shell-History schreiben.systemd-ask-password "Keycloak DB password" > /opt/keycloak/conf/kc_db_passwordsystemd-ask-password "Keycloak bootstrap admin password" > /opt/keycloak/conf/kc_admin_passwordchmod 0640 /opt/keycloak/conf/kc_*_password
Schritt 14: Von podman run zu Compose wechseln
Für dauerhaften Betrieb ist eine deklarative Compose-Datei besser als ein langer Einzelbefehl. Sie dokumentiert Container, Images, Ports, Volumes, Secrets und Abhängigkeiten an einer Stelle. Damit wird später auch Ansible einfacher, weil die Zielstruktur schon feststeht.
services:postgres:image: docker.io/library/postgres:16-alpineenvironment:POSTGRES_DB: keycloakPOSTGRES_USER: keycloakPOSTGRES_PASSWORD_FILE: /run/secrets/kc_db_passwordsecrets:- kc_db_passwordvolumes:- keycloak-postgres:/var/lib/postgresql/datakeycloak:image: quay.io/keycloak/keycloak:26.7.3command:- start- --http-enabled=true- --hostname=https://sso.example.test- --proxy-headers=xforwarded- --health-enabled=true- --metrics-enabled=trueenvironment:KC_DB: postgresKC_DB_URL: jdbc:postgresql://postgres:5432/keycloakKC_DB_USERNAME: keycloakKC_DB_PASSWORD_FILE: /run/secrets/kc_db_passwordKC_BOOTSTRAP_ADMIN_USERNAME: adminKC_BOOTSTRAP_ADMIN_PASSWORD_FILE: /run/secrets/kc_admin_passwordsecrets:- kc_db_password- kc_admin_passwordports:- "127.0.0.1:8080:8080"depends_on:- postgressecrets:kc_db_password:file: /opt/keycloak/conf/kc_db_passwordkc_admin_password:file: /opt/keycloak/conf/kc_admin_passwordvolumes:keycloak-postgres:
Schritt 15: Rootless systemd einrichten
Ein produktiver Dienst muss nach einem Reboot automatisch wiederkommen. Rootless Podman mit systemd verbindet beides: kein dauerhafter Root-Containerprozess und trotzdem sauberer Dienstbetrieb. Wichtig ist `loginctl enable-linger`, sonst startet der User-Service nach einem Reboot nicht zuverlässig.
useradd --system --create-home --home-dir /opt/keycloak --shell /bin/bash svc-keycloakloginctl enable-linger svc-keycloaksudo -iu svc-keycloakcd /opt/keycloak/composepodman-compose up -dpodman pssystemctl --user status
Schritt 16: Health, Metrics und Management-Port verstehen
Keycloak stellt Health und Metrics getrennt vom normalen Login-Verkehr bereit. In Containerumgebungen ist das wertvoll für Monitoring und Load Balancer. Der Management-Port darf nicht unkontrolliert öffentlich erreichbar sein. Prüfe ihn lokal oder aus dem Monitoring-Netz.
podman port forgeone-keycloak-labcurl -fsS http://127.0.0.1:18080/realms/master/.well-known/openid-configuration | jq '.issuer'# Je nach Startparameter und Portbindung separat prüfen:curl -fsS http://127.0.0.1:9000/health/readycurl -fsS http://127.0.0.1:9000/metrics | head
Schritt 17: Produktionsparameter prüfen
Vor dem Go-live prüfst du, ob Keycloak seinen eigenen öffentlichen Namen korrekt kennt. Der Issuer muss exakt zur Browser-URL passen. Wenn `issuer`, `authorization_endpoint` oder `token_endpoint` falsche interne Namen enthalten, sind Hostname oder Proxy-Header falsch gesetzt.
curl -fsS https://sso.example.test/realms/master/.well-known/openid-configuration \| jq '.issuer, .authorization_endpoint, .token_endpoint'curl -I https://sso.example.test/admin/
Schritt 18: Häufige Fehler sauber eingrenzen
Wenn Keycloak nicht startet, prüfst du zuerst Datenbank, Netzwerk, Hostname, Ports und Logs. Wenn die Oberfläche lädt, aber Logins scheitern, prüfst du Uhrzeit, TLS, Issuer, Redirect-URIs und Proxy-Header. Arbeite von unten nach oben: Container, Datenbank, HTTP, Reverse Proxy, Realm, Client.
podman ps -apodman logs --tail=200 forgeone-keycloak-postgrespodman logs --tail=200 forgeone-keycloak-labpodman exec forgeone-keycloak-postgres pg_isready -U keycloak -d keycloakcurl -v http://127.0.0.1:18080/admin/
Schritt 19: Abschlusscheck
Am Ende sollte klar sein: Keycloak läuft mit gepinnter Version, PostgreSQL ist persistent, der Admin-Login funktioniert, der Issuer stimmt, Backups sind möglich, Secrets sind geschützt, der spätere Reverse Proxy ist geplant und der Betrieb kann automatisiert werden. Erst danach lohnt sich die nächste Ebene: IdM-Anbindung, Federation und Themes.
Schritt 20: Nächste Teile der Serie
Dieser Beitrag endet bewusst bei der lauffähigen Keycloak-Basis. Als Nächstes folgen separate Anleitungen für die Anbindung an FreeIPA oder Red Hat IdM, Keycloak-zu-Keycloak-Federation und Theming. So bleibt jeder Teil fachlich sauber und kann einzeln getestet werden.
3. Ergebniskontrolle / Technische Abnahme
| Prüfpunkt | Aktion / Befehl | Erwartetes Ergebnis | Status |
|---|---|---|---|
| Container | podman ps und journalctl --user ausführen | Keycloak und Datenbank laufen stabil und starten reproduzierbar. | Erfolgreich |
| TLS und URL | Öffentliche Keycloak-URL im Browser öffnen | Admin-Konsole und Realm-Endpunkte laden über HTTPS ohne Zertifikatswarnung. | Erfolgreich |
| Realm und Client | Client-Einstellungen und Redirect-URIs kontrollieren | OIDC/SAML-Flow nutzt die erwarteten URLs und keine Test- oder Loopback-Adresse. | Erfolgreich |
| Login-Test | Testbenutzer anmelden und Token-/Session-Fluss kontrollieren | Anmeldung, Logout und Rollen-/Gruppenmapping funktionieren nachvollziehbar. | Erfolgreich |
Container
- Aktion / Befehl
- podman ps und journalctl --user ausführen
- Erwartetes Ergebnis
- Keycloak und Datenbank laufen stabil und starten reproduzierbar.
- Status
- Erfolgreich
TLS und URL
- Aktion / Befehl
- Öffentliche Keycloak-URL im Browser öffnen
- Erwartetes Ergebnis
- Admin-Konsole und Realm-Endpunkte laden über HTTPS ohne Zertifikatswarnung.
- Status
- Erfolgreich
Realm und Client
- Aktion / Befehl
- Client-Einstellungen und Redirect-URIs kontrollieren
- Erwartetes Ergebnis
- OIDC/SAML-Flow nutzt die erwarteten URLs und keine Test- oder Loopback-Adresse.
- Status
- Erfolgreich
Login-Test
- Aktion / Befehl
- Testbenutzer anmelden und Token-/Session-Fluss kontrollieren
- Erwartetes Ergebnis
- Anmeldung, Logout und Rollen-/Gruppenmapping funktionieren nachvollziehbar.
- Status
- Erfolgreich
4. Typische Fehler & Troubleshooting
Container startet nicht: Podman-Logs, Environment, Ports, Volumes und SELinux-Kontexte kontrollieren.
Zertifikate werden nicht vertraut: CA-Kette, Truststore und Reverse-Proxy-Konfiguration kontrollieren.
LDAP oder Federation liefert keine Benutzer: Bind-DN, Filter, Mapper, Uhrzeit und Gruppenmodell kontrollieren.
5. Fazit & Ausblick
Keycloak ist damit als Identity-Baustein eingeordnet und technisch überprüfbar. Darauf bauen FreeIPA/Red Hat IdM, Federation, Theming und Anwendungsintegration auf.



