3 Punkte von GN⁺ 2024-02-12 | 1 Kommentare | Auf WhatsApp teilen
  • Dies ist ein Bereitstellungsverfahren, bei dem Keycloak auf einer einzelnen Linux-VM isoliert mit rootless Docker läuft und das System-nginx die TLS-Terminierung sowie den Reverse Proxy übernimmt
  • Voraussetzungen sind SSH-Zugriff, eine Domain oder Subdomain für Keycloak, ein A-Record, ein passwortloser Benutzer keycloak, das Home-Verzeichnis /srv/keycloak und eine rootless-Docker-Installation
  • docker-compose.yml verwendet postgres:16 und quay.io/keycloak/keycloak:25.0.1; Keycloak bindet nur an 127.0.0.1:8080 und verwaltet Passwörter sowie KC_HOSTNAME in .env
  • nginx leitet HTTP-Anfragen für your.tld.com auf HTTPS um und gibt sie per proxy_pass weiter; nach der Zertifikatsausstellung mit Certbot wird KC_PROXY_HEADERS: xforwarded aktiviert
  • Wenn ein benutzerdefiniertes Theme oder der Start mit --optimized erforderlich ist, kann ein eigenes Image mit einem Multi-Stage-Dockerfile erstellt werden; im Betrieb lassen sich zusätzlich die JGroups-Puffergröße und die Quarkus-Transaktionswiederherstellung anpassen

Bereitstellungsstruktur und Voraussetzungen

  • Keycloak ist eine Open-Source-IAM-Option, wenn es schwierig ist, Benutzerverwaltung und SSO direkt in einer Webanwendung selbst zu implementieren
  • Es ist mit wichtigen SSO-Protokollen wie OpenID Connect (OIDC), OAuth 2.0 und SAML interoperabel
  • Die Konfiguration wurde auf Basis von Keycloak 23.0.6 geschrieben und bis 25.0.5 getestet
  • Die Gesamtarchitektur nutzt nginx als zentralen Reverse Proxy und leitet Traffic pro Dienst an localhost innerhalb separater rootless-Docker-Namespaces weiter
    • Web-Traffic kommt auf 0.0.0.0:80 und 0.0.0.0:443 an, und nginx leitet ihn an Keycloak auf 127.0.0.1:8080 weiter
    • Ziel ist eine kosteneffiziente Konfiguration, die Dienstumgebungen trennt und gleichzeitig die Ressourcen eines einzelnen Hosts gemeinsam nutzt

Vorbereitungen

  • Als Grundumgebung werden eine Linux-VM, SSH-Fernzugriff sowie eine Domain oder Subdomain für den Keycloak-Dienst benötigt
    • Für die Domain wird ein A-Record benötigt; optional kann ein AAAA-Record hinzugefügt werden
  • Für die rootless-Docker-Grundkonfiguration wird dem Verfahren in einem separaten Mastodon-Beitrag gefolgt
    • Einen neuen non-root-Benutzer keycloak ohne Passwort anlegen
    • Das Home-Verzeichnis auf /srv/keycloak setzen
    • In /etc/subuid und /etc/subgid einen Bereich für den Benutzer keycloak hinzufügen
    • rootless Docker mit dockerd-rootless-setuptool.sh installieren
    • Den automatischen Dienststart für den Benutzer keycloak konfigurieren

Keycloak mit Docker Compose starten

  • Um in den neu angelegten Benutzer keycloak zu wechseln, wird machinectl shell keycloak@ verwendet
    • Die Methode sudo -u keycloak -H bash wird vermieden, da dabei die Umgebungsvariable XDG_RUNTIME_DIR nicht vorbereitet ist
  • Zuerst werden Verzeichnisse für persistente Daten und Docker-Dateien erstellt
    • Der PostgreSQL-Datenpfad ist /srv/keycloak/data/postgres16
    • Die Docker-Dateien liegen unter ~/docker
  • docker-compose.yml verwendet direkt das offizielle Keycloak-Image und PostgreSQL
    • Das PostgreSQL-Image ist postgres:16
    • Das Keycloak-Image ist quay.io/keycloak/keycloak:25.0.1
    • Für Produktionsumgebungen wird empfohlen, statt :latest einen konkreten Image-Tag zu verwenden
  • Die wichtigsten Einstellungen des Keycloak-Containers sind wie folgt
    • KC_DB: postgres
    • KC_DB_URL: jdbc:postgresql://postgres_db/keycloak
    • KC_HOSTNAME: ${KC_HOSTNAME:-your.tld.com}
    • KC_HTTP_ENABLED: true
    • HTTP_ADDRESS_FORWARDING: true
    • KEYCLOAK_ADMIN: admin
    • Der Port wird mit '127.0.0.1:8080:8080' nur an localhost gebunden
  • In .env stehen sensible oder umgebungsspezifische Werte
    • POSTGRES_PASSWORD
    • KEYCLOAK_ADMIN_PASSWORD
    • KC_HOSTNAME
  • Die Syntax ${KC_HOSTNAME:-your.tld.com} verwendet den Wert aus .env, wenn dort KC_HOSTNAME gesetzt ist; andernfalls wird your.tld.com als Standardwert verwendet
  • /srv/keycloak/data/postgres16 enthält die persistenten Daten von PostgreSQL und sollte daher regelmäßig gesichert werden
    • Für eine vollständige Initialisierung kann dieses PostgreSQL-Verzeichnis gelöscht und neu erstellt werden; beim nächsten Start wird es erneut angelegt
  • Wenn ~/docker als Git-Repository verwaltet wird, kann .env in .gitignore aufgenommen und nur docker-compose.yml committet werden

Lokaler Test

  • Den Docker-Compose-Stack starten und die Logs prüfen
docker compose up -d && docker compose logs --follow
  • Um auf den lokalen Keycloak-Port der VM zuzugreifen, wird ein umgekehrter SSH-Tunnel eingerichtet
ssh you@111.11.11.11 -L :8080:127.0.0.1:8080 -p 22 -N -v
  • Im Browser 127.0.0.1:8080 öffnen und den Keycloak-Willkommensbildschirm prüfen

nginx-Reverse-Proxy und TLS

  • Nach dem Abmelden vom Benutzer keycloak wird die System-nginx-Konfiguration vorgenommen
  • your.tld.com durch die echte Domain ersetzen und beim Domain-Registrar einen A-Record hinzufügen, damit DNS-Anfragen an die IP der VM gehen
  • Die nginx-Site-Konfigurationsdatei erstellen und aktivieren
nano /etc/nginx/sites-available/your.tld.com.conf
ln -s /etc/nginx/sites-available/your.tld.com.conf /etc/nginx/sites-enabled/
  • Die nginx-Konfiguration leitet HTTP-Anfragen auf HTTPS um und proxyt im HTTPS-Serverblock an Keycloak
    • proxy_set_header Host $host
    • proxy_set_header X-Real-IP $remote_addr
    • proxy_set_header X-Forwarded-For $remote_addr
    • proxy_set_header X-Forwarded-Proto $scheme
    • proxy_pass http://127.0.0.1:8080
  • Für die SSL-Konfiguration wird empfohlen, mit dem Mozilla SSL configurator for nginx passende Standardwerte für die verwendete nginx-Version zu erzeugen
  • Nach dem Test der Konfiguration nginx neu laden
nginx -t
systemctl reload nginx
  • Wenn mit Certbot ein Zertifikat ausgestellt wird, werden die erforderlichen Zeilen in your.tld.com.conf automatisch aktualisiert
certbot --nginx -d your.tld.com
  • Danach ssl_trusted_certificate /etc/letsencrypt/live/your.tld.com/chain.pem; aktivieren und nginx erneut neu laden
  • Anschließend KC_PROXY_HEADERS: xforwarded in docker-compose.yml aktivieren, damit der Betrieb hinter nginx korrekt funktioniert, und den Docker-Stack neu starten
docker compose down && docker compose up -d && docker compose logs --follow

Debugging-Pfade

  • Nach der Konfiguration your.tld.com aufrufen und die Anmeldung des Benutzers admin mit dem Passwort aus .env prüfen
  • Die erste Prüfstation sind die Docker-Compose-Logs
docker compose logs --follow
  • nginx-Zugriffs- und Fehler-Logs lassen sich über folgende Dateien verfolgen
tail -f /var/log/nginx/your.tld.com-access.log
tail -f /var/log/nginx/your.tld.com-error.log
  • Wenn die Keycloak-Datenbank direkt geprüft werden muss, zum Benutzer keycloak wechseln und psql im PostgreSQL-Container ausführen
machinectl shell keycloak@
cd ~/docker
docker compose exec postgres_db /bin/bash
psql -h localhost -p 5432 -U keycloak keycloak

Benutzerdefiniertes Image und Start mit optimized

  • Die Grundkonfiguration verwendet das vorgebaute Image von quay.io
  • Wenn Theme-Anpassungen oder der Start im Modus --optimized erforderlich sind, wird ein eigenes Image gebaut
  • Das Dockerfile verwendet auf Basis des offiziellen Keycloak-Images einen Multi-Stage-Build
    • Im Builder-Schritt ENV KC_DB=postgres setzen
    • /opt/keycloak/bin/kc.sh build ausführen
    • /opt/keycloak/ in das finale Image kopieren
    • ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] festlegen
  • In docker-compose.yml wird dies wie folgt geändert
    • Die Zeile image: entfernen oder auskommentieren
    • build: . aktivieren
    • command: start --optimized hinzufügen
  • Danach den Docker-Stack herunterfahren, optional einen expliziten Build ausführen und wieder starten
docker compose down
docker compose build
docker compose up -d && docker compose logs --follow

Zusätzliche Anpassungen in der Produktionsumgebung

  • Warnungen zu JGroups-bezogenen MulticastSocket-Empfangspuffern werden gelöst, indem auf dem Host in /etc/sysctl.conf Pufferwerte ergänzt werden
net.core.rmem_max = 26214400
net.core.wmem_max = 1048576
  • Zum Übernehmen der Konfiguration sysctl -p ausführen
  • Die Quarkus-Warnung zur XA-Transaktionswiederherstellung wird behoben, indem dem Keycloak-Dienst ein Volume-Mount und eine Umgebungsvariable hinzugefügt werden
    • Volume: /srv/keycloak/data/keycloak/ObjectStore/:/ObjectStore/
    • Umgebungsvariable: QUARKUS_TRANSACTION_MANAGER_ENABLE_RECOVERY: true
  • Vor dem Start auf dem Host das ObjectStore-Verzeichnis anlegen und im Container den Besitzer von /ObjectStore auf Benutzer-ID 1000 ändern

Schritte nach der Konfiguration

  • Der Endzustand ist eine Konfiguration, bei der der Keycloak-Dienst in rootless Docker hinter dem System-nginx-Reverse-Proxy läuft und nginx die SSL-Terminierung übernimmt
  • Für automatische Container-Updates wird auf das Auto-Update-Verfahren in einem separaten Mastodon-Beitrag verwiesen
  • Der nächste Konfigurationsschritt ist das Hinzufügen einer E-Mail im Keycloak-Admin-Console
  • Danach können weitere Realms hinzugefügt und Themes konfiguriert werden
    • Für Themes können keycloakify und keycloakify-starter verwendet werden
    • Das Dockerfile enthält eine auskommentierte Zeile, die ein keycloakify-Theme-JAR nach /opt/keycloak/providers/ kopiert

1 Kommentare

 
GN⁺ 2024-02-12
Meinungen auf Hacker News
  • Ich habe mich kürzlich für Authelia entschieden, als ich mein Homelab mit Authentifizierung versehen habe
    Keycloak funktioniert zwar auch, ist aber viel zu groß, und wenn man es mit traefik forward auth nutzen will, braucht man zusätzliche Services
    Authelia hat keine UI zum Bearbeiten von Nutzern und auch keine bidirektionale Synchronisierung mit einem LDAP-Backend-Server, lässt sich aber nur mit statischen Dateien und Umgebungsvariablen konfigurieren und passt deshalb in vielen Fällen gut
    Wenn es nur darum geht, einigen Services Authentifizierung hinzuzufügen und dort, wo es möglich ist, SSO einzubinden, lohnt es sich, mit Authelia anzufangen

    • Ich arbeite bei FusionAuth
      Wenn ihr SSO, einfache Einrichtung und eine Admin-UI braucht, ist auch FusionAuth einen Blick wert. UI/UX fühlt sich zwar nach Mitte der 2000er an, aber man kann es selbst herunterladen und ausführen[0], es ist Docker-freundlich[1] und bietet mehrere Konfigurationswege[2], etwa die Verwaltung von OIDC oder anderen Einstellungen per Terraform[3]
      Es kann kostenlos genutzt werden, ist aber nicht Open Source[4]
      0: https://fusionauth.io/download
      1: https://fusionauth.io/docs/get-started/download-and-install/...
      2: https://fusionauth.io/docs/operate/deploy/configuration-mana...
      3: https://fusionauth.io/docs/operate/deploy/terraform
      4: https://fusionauth.io/license-faq#28
    • Ich betreibe Authelia seit über zwei Jahren und habe die LDAP-Anbindung mit LLDAP[0], einer leichtgewichtigen LDAP-Implementierung, eingerichtet
      Ich nutze Caddy als Reverse Proxy und habe es mit Authelia integriert[1], was gut funktioniert
      Ich habe alle Services mit solider Zwei-Faktor-Authentifizierung versehen und habe das Gefühl, dass der Zugriff auf meine selbst gehosteten Apps auch ohne VPN ausreichend sicher ist
      Allerdings gab es seit über einem Jahr kein neues Authelia-Release mehr, was mir aus Sicherheitssicht Sorgen macht
      [0] https://github.com/lldap/lldap
      [1] https://www.authelia.com/integration/proxies/caddy/
    • Ich bin kürzlich denselben Weg gegangen und habe mich persönlich für caddy-security[1], ein Caddy-Plugin, entschieden
      [1] https://github.com/greenpau/caddy-security
    • Authelia hat den sehr besonderen Vorteil eines kleinen Installationsumfangs, und Keycloak oder authentik passen in diesem Bereich nur schwer
      Für Homelab-Umgebungen ist das ein sehr guter Anwendungsfall, besonders wenn man die Funktionen der größeren Lösungen nicht braucht oder nicht will
    • Nebenbei gefragt: Gibt es heutzutage eigentlich eine LDAP-Alternative?
      Ich habe gesucht, aber nichts in Richtung einfaches Schema, JSON oder HTTP gefunden, und ich kann kaum glauben, dass fast alle alles neu gebaut haben, aber niemand LDAP neu erfunden hat
      Soweit ich weiß, ist Active Directory faktisch der einzige andere Standard
      Außerdem frage ich mich, ob es einen Standard oder ein Protokoll gibt, um Zugriffskontrolle nach außen auszulagern
      Authelia kann Zugriffe über URL-Muster steuern, aber bei einem Dateiserver würde ich zum Beispiel erwarten, dass er anhand der authentifizierten Nutzer-ID und eines Schlüssels in der Datenbank beim LDAP-Server die Berechtigungen abfragt
      Das wirkt wie die umgekehrte Richtung von OAuth2, bei dem ein Server Zugriffsrechte auf einen Drittanbieter-Service erhält
  • Ich habe mir kürzlich angesehen, wie ich in meinem Homelab ein relativ einfaches SSO einrichten kann; das Hauptziel war, sich unkompliziert per Google- oder GitHub-Authentifizierung anzumelden.
    In einem früheren Job habe ich sowohl JetBrains Hub[1] als auch Keycloak verwendet, und beide waren ziemlich mühsam zu konfigurieren.
    JetBrains Hub ließ sich wirklich leicht starten, und so war auch meine frühere Erfahrung, aber es war unpraktisch, dass es im Docker-Registry kein latest-Tag gibt.
    Ich weiß, dass das Festpinnen von Versionen gut ist, aber für den privaten Gebrauch möchte man normalerweise alle Docker-Container auf einmal aktualisieren.
    Keycloak dagegen war sehr umständlich in Gang zu bringen; im Entwicklungsmodus war es einfach, aber die Produktionskonfiguration hat mich ausgebremst.
    Soweit ich mich erinnere, hatte es mit einem Wildcard-Zertifikat von Let's Encrypt zu tun, und nach ein paar Stunden habe ich aufgegeben.
    Am Ende habe ich mich für Dex[2] entschieden. Wegen der dürftigen Dokumentation hatte ich es aufgeschoben, aber die eigentliche Einrichtung war sehr einfach: eine einfache YAML-Datei, eine SQLite-Datenbank und eine Subdomain reichten aus.
    Ich habe Dex mit dem hervorragenden OAuth2 Proxy[3] und einer eigenen Vorlage für den Nginx Proxy Manager kombiniert, sodass pro internem Dienst eine zweizeilige SSO-Konfiguration genügt, und außerdem ein Dex-Docker-Template[4] für unRAID erstellt.
    Dazu habe ich für den Zugriff von außerhalb des Hauses Cloudflare Access und WAF ergänzt, um die Sicherheit zu erhöhen; jetzt möchte ich nur noch CrowdSec hinzufügen, um etwas mehr Einblick zu bekommen.

    1. https://www.jetbrains.com/hub/
    2. https://dexidp.io/
    3. https://github.com/oauth2-proxy/oauth2-proxy
    4. https://github.com/alex3305/unraid-docker-templates
    • Ich nutze obligator als temporären Speicher, ohne Datenbank und mit 100 % codebasierter Konfiguration.
      Persönlich halte ich das für die einfachste Option.
      https://github.com/lastlogin-io/obligator
    • Ich frage mich, welche Funktionen oauth2-proxy bietet, die Dex nicht hat.
  • Ich habe eine unvollständige Vergleichstabelle mehrerer selbst hostbarer OpenID-Connect-Server erstellt[0].
    Eines der überraschenden Dinge war, dass die Keycloak-Codebasis wirklich riesig ist.
    [0]: https://github.com/lastlogin-io/obligator?tab=readme-ov-file...

  • Die Vorstellung, dass Keycloak Sicherheitsprobleme löst, ist amüsant.
    Wenn man sich die CVE-Liste ansieht, versteht man, was ich meine.

  • Allein dass in dem Artikel https://www.keycloakify.dev/ erwähnt wurde, ist sehr nützlich.
    Es sieht nach einer hervorragenden Alternative zum Standard-Ansatz für Themes aus.

    • Ein großartiges Projekt.
      Ich nutze es seit zwei Jahren und kann nur Gutes darüber sagen.
      Der Maintainer reagiert sehr schnell, und kürzlich sind sowohl in Keycloak als auch in keycloakify Änderungen eingeflossen, die die zukünftige Kompatibilität des Theme-Ansatzes verbessern.
      Derzeit werden offiziell nur mit create-react-app erstellte Apps unterstützt, aber ein vite-Branch ist in Entwicklung, und ich persönlich nutze es schon seit einiger Zeit mit vite.
    • Ich arbeite bei einem Wettbewerber, und da wir gerade das Theme-System überarbeiten, scheint dieses Projekt gut geeignet zu sein, um es zu prüfen und als Modell für die Überarbeitung zu verwenden.
  • Habe authentik[1] und authelia[2] im Blick
    Authelia sieht sehr gut aus, aber Keycloak hat einen Connector für Angular, während man bei Authelia zum Beispiel ein OIDC-Angular-Plugin selbst konfigurieren müsste, daher war ich etwas vorsichtig
    Trotzdem dürfte der Einstieg einfacher werden, wenn es eine Konfiguration für Keycloak gibt
    [1] https://goauthentik.io/
    [2] https://www.authelia.com/

    • Wer authentik in Betracht zieht, den würde ich warnen: „Hier lauern Drachen“
      Ich schütze dauerhaft mehr als 10 Services in Docker und Kubernetes; wenn man es nicht genießt, die Schutzkonfiguration für jeden Service einzeln vorzunehmen, wird man mit authentik leiden
      authentik hat einen schwerwiegenden Bug[0]: Wenn man mehrere Subdomains (app1.example.com, app2.example.com usw.) mit einer einzigen Konfiguration schützt, werden Benutzer nach Ablauf der Session und erneuter Authentifizierung zufällig auf einen anderen Service umgeleitet
      [0]: https://github.com/goauthentik/authentik/issues/6886
    • Authentik hat die Implementierung des OAuth-Client-Credentials-Grants komplett vermasselt
      Das lässt sich nicht ohne Breaking Changes beheben und funktioniert mit vielen Tools, die den cc-Grant verwenden, nicht
      Nachdem ich das gesehen hatte, habe ich es komplett von der Kandidatenliste gestrichen
      https://github.com/goauthentik/authentik/issues/6139
    • Ich bin einer der Core-Maintainer von Authelia
      Wenn ich bei der Angular-Konfiguration helfen kann, unterstütze ich gern über GitHub Discussions
    • Ich stehe gerade vor derselben Entscheidung
      Authentik sah besser aus, aber die in anderen Antworten erwähnten Bugs sehen ziemlich übel aus
  • Das Problem mit Keycloak ist, dass es ein altes Projekt ist und sich enorm viel verändert hat
    Es begann als JBOSS-Projekt, und seine Nützlichkeit als IdP glänzt bei der Authentifizierung von On-Premises-Clustern, aber meiner Meinung nach endet es dort
    Ich habe in einer Fortune-500-Abteilung Keycloak in großem Maßstab auf AWS ECS implementiert, und es korrekt zu clustern fühlte sich an wie der Hundertjährige Krieg
    DNS-Discovery funktionierte nicht richtig, und die Cluster-Discovery war UDP-basiert, was in Cloud-Umgebungen nicht funktioniert hat
    Ein zustandsbehafteter Login auf einem Server war auf einem anderen nicht vorhanden, daher war simples Load Balancing unmöglich; Sticky Sessions waren die einzige Option
    Keycloak per docker run zu starten und wie Auth0 einzustecken ist einfach, aber es fühlt sich an, als würde man einen Ford F-150 Baujahr 1996 mit 250.000 Meilen kaufen
    Er fährt und funktioniert, aber die Wartung ist wirklich schrecklich

    • Ich habe das in kleinerem Maßstab in einem On-Premises-Docker-Swarm gemacht, und es war tatsächlich schmerzhaft
      Soweit ich mich erinnere, nutzt die Standard-Discovery Multicast, das in typischen Cloud-Netzwerken oder Swarm-/Kubernetes-Overlay-Netzwerken nicht aktiviert ist
      Ich habe auch Database Ping gesehen, das ein RDBMS als eine Art Quorum-Mechanismus nutzt, aber es wirkte sehr fragil und eher wie ein letzter Ausweg
      Am Ende konnte ich einen Kubernetes-Cluster-Treiber verwenden, der die Nodes über das DNS des Swarm-Clusters entdeckt
      Es war ziemlich mühsam, es zum Laufen zu bringen, aber seitdem ist es meines Wissens stabil
      Heutzutage scheint es auch einen nativen EC2-Networking-Treiber zu geben, aber ich habe ihn nicht selbst untersucht
    • Ich habe gehört, dass es Verbesserungen gab, nachdem es vollständig auf Quarkus umgezogen ist
      Mich würde interessieren, wann die ECS-Bereitstellung war
    • OAuth und OpenID Connect sowie die Möglichkeit, Apps und Clients zu einem Realm hinzuzufügen, waren die Rettung für Keycloak und der einzige Grund, warum wir daran festgehalten haben
    • Dass die Cluster-Discovery UDP war, klingt schmerzhaft
      Bei uns ist UDP nur für DNS erlaubt
  • Keycloak ist großartig, kann für Anfänger aber ziemlich verwirrend sein
    Es hat viele Funktionen, und die Dokumentation ist nicht die beste
    Kürzlich habe ich Zitadel ausprobiert, und es war deutlich einfacher zu benutzen
    Allerdings kann man es nicht mit einer eingebauten Datenbank ausführen, daher ist Self-Hosting etwas schwieriger

    • Genau, es braucht eine eigene Datenbank
      Künftig geht die Richtung dahin, Postgres als Datenbank zu verwenden; ich hoffe, dass es dadurch einfacher wird, es zusammen mit anderen Tools bereitzustellen
  • Mein Chef nannte Keycloak kürzlich etwas, „das immer weiter Geschenke macht“, meinte damit aber eigentlich, dass ständig neue Jira-Tickets entstehen, um herauszufinden, wie man etwas tun soll
    Trotzdem haben wir Terraform, das einen EKS-Cluster erstellt und Keycloak deployt, SAML-/OIDC-Clients anlegt, externe Identity Provider hinzufügt und sogar einen AWS IAM Identity Provider konfiguriert
    Sobald man herausgefunden hat, was man tun kann, wie man es in der UI macht und wie man es mit mrparkers Terraform Provider automatisiert, ist die Nutzung selbst sehr einfach

    • Ich frage mich, ob dieses Terraform irgendwo als Open Source veröffentlicht ist
      Ein Freund bräuchte es :)
  • Nachdem ich Keycloak ein paar Jahre genutzt hatte, war ich ehrlich gesagt all die merkwürdigen Eigenheiten leid und begann, nach Alternativen zu suchen
    Mehrere Kandidaten wie Authentik sahen in Ordnung aus, aber Zitadel[1] fiel mir auf, und seitdem habe ich nicht mehr zurückgeblickt
    [1] https://zitadel.com/blog/zitadel-vs-keycloak

    • Schön, dass es dir gefällt
      Mich würde interessieren, was dich letztlich überzeugt hat