- Procédure de déploiement SSO qui exécute Keycloak de façon isolée avec Docker rootless sur une seule VM Linux, tandis que le nginx système prend en charge la terminaison TLS et le reverse proxy
- Les prérequis sont un accès SSH, un domaine ou sous-domaine pour Keycloak, un enregistrement
A, un utilisateur keycloak sans mot de passe, un répertoire personnel /srv/keycloak et une installation Docker rootless
docker-compose.yml utilise postgres:16 et quay.io/keycloak/keycloak:25.0.1 ; Keycloak est lié uniquement à 127.0.0.1:8080 et les mots de passe ainsi que KC_HOSTNAME sont gérés dans .env
- nginx redirige les requêtes HTTP de
your.tld.com vers HTTPS et les transmet avec proxy_pass ; après l’émission du certificat Certbot, KC_PROXY_HEADERS: xforwarded est activé
- Si un thème personnalisé ou une exécution avec
--optimized est nécessaire, il faut construire sa propre image avec un Dockerfile multistage ; en production, on peut aussi ajuster la taille des buffers JGroups et la configuration de récupération des transactions Quarkus
Architecture de déploiement et prérequis
- Keycloak est une option IAM open source utilisable lorsqu’il est difficile d’implémenter directement la gestion des utilisateurs et le SSO dans une application web
- Il est interopérable avec les principaux protocoles SSO comme
OpenID Connect (OIDC), OAuth 2.0 et SAML
- La configuration a été rédigée pour Keycloak
23.0.6 et testée jusqu’à 25.0.5
- L’architecture globale consiste à placer nginx comme reverse proxy central, puis à transmettre le trafic vers localhost dans des espaces de noms Docker rootless propres à chaque service
- Le trafic web arrive sur
0.0.0.0:80 et 0.0.0.0:443, et nginx le transmet à Keycloak sur 127.0.0.1:8080
- L’objectif est une configuration économique qui partage les ressources d’un seul hôte tout en isolant les environnements de service
Préparation
- L’environnement de base nécessite une VM Linux, un accès distant SSH et un domaine ou sous-domaine pour le service Keycloak
- Le domaine nécessite un enregistrement
A et peut éventuellement recevoir un enregistrement AAAA
- La configuration de base de Docker rootless suit la procédure d’un autre billet Mastodon
- Création d’un nouvel utilisateur non-root
keycloak sans mot de passe
- Définition du répertoire personnel sur
/srv/keycloak
- Ajout de la plage de l’utilisateur
keycloak dans /etc/subuid et /etc/subgid
- Installation de Docker rootless avec
dockerd-rootless-setuptool.sh
- Configuration du démarrage automatique du service pour l’utilisateur
keycloak
Exécuter Keycloak avec Docker Compose
- Pour se connecter avec l’utilisateur
keycloak nouvellement créé, utiliser machinectl shell keycloak@
- La méthode
sudo -u keycloak -H bash est à éviter, car la variable d’environnement XDG_RUNTIME_DIR n’est pas préparée
- Créer d’abord les répertoires pour les données persistantes et les fichiers Docker
- Le chemin des données PostgreSQL est
/srv/keycloak/data/postgres16
- Les fichiers Docker sont placés dans
~/docker
docker-compose.yml utilise directement l’image officielle Keycloak et PostgreSQL
- L’image PostgreSQL est
postgres:16
- L’image Keycloak est
quay.io/keycloak/keycloak:25.0.1
- En production, il est recommandé d’utiliser un tag d’image précis plutôt que
:latest
- Les principaux paramètres du conteneur Keycloak sont les suivants
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
- Le port est lié uniquement à localhost avec
'127.0.0.1:8080:8080'
.env contient les valeurs sensibles ou variables selon l’environnement
POSTGRES_PASSWORD
KEYCLOAK_ADMIN_PASSWORD
KC_HOSTNAME
- La syntaxe
${KC_HOSTNAME:-your.tld.com} utilise la valeur de KC_HOSTNAME si elle existe dans .env, sinon your.tld.com comme valeur par défaut
/srv/keycloak/data/postgres16 contient les données persistantes de PostgreSQL et doit donc faire l’objet de sauvegardes régulières
- Pour une réinitialisation complète, supprimer puis recréer ce dossier PostgreSQL ; il sera recréé au démarrage suivant
- Si
~/docker est géré comme dépôt Git, ajouter .env à .gitignore et ne commiter que docker-compose.yml
Test local
- Démarrer la stack Docker Compose et consulter les logs
docker compose up -d && docker compose logs --follow
- Pour accéder au port local Keycloak de la VM, créer un tunnel SSH inverse
ssh you@111.11.11.11 -L :8080:127.0.0.1:8080 -p 22 -N -v
- Ouvrir
127.0.0.1:8080 dans le navigateur pour vérifier l’écran d’accueil de Keycloak
Reverse proxy nginx et TLS
- Après s’être déconnecté de l’utilisateur
keycloak, configurer le nginx système
- Remplacer
your.tld.com par le domaine réel et ajouter un enregistrement A chez le registrar pour que les requêtes DNS pointent vers l’IP de la VM
- Créer et activer le fichier de configuration du site nginx
nano /etc/nginx/sites-available/your.tld.com.conf
ln -s /etc/nginx/sites-available/your.tld.com.conf /etc/nginx/sites-enabled/
- La configuration nginx redirige les requêtes HTTP vers HTTPS et, dans le bloc serveur HTTPS, fait proxy vers 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
- Pour la configuration SSL, il est recommandé d’utiliser le Mozilla SSL configurator for nginx afin de générer des valeurs par défaut adaptées à la version de nginx
- Tester la configuration puis recharger nginx
nginx -t
systemctl reload nginx
- Lors de l’émission du certificat avec Certbot, les lignes nécessaires dans
your.tld.com.conf sont automatiquement mises à jour
certbot --nginx -d your.tld.com
- Activer ensuite
ssl_trusted_certificate /etc/letsencrypt/live/your.tld.com/chain.pem; et recharger nginx
- Activer
KC_PROXY_HEADERS: xforwarded dans docker-compose.yml pour fonctionner derrière nginx, puis redémarrer la stack Docker
docker compose down && docker compose up -d && docker compose logs --follow
Pistes de débogage
- Après la configuration, se connecter à
your.tld.com et vérifier la connexion de l’utilisateur admin avec le mot de passe de .env
- Le premier point à vérifier est les logs Docker Compose
docker compose logs --follow
- Suivre les logs d’accès et d’erreur nginx dans les fichiers suivants
tail -f /var/log/nginx/your.tld.com-access.log
tail -f /var/log/nginx/your.tld.com-error.log
- S’il faut inspecter directement la base de données Keycloak, se connecter avec l’utilisateur
keycloak et exécuter psql dans le conteneur PostgreSQL
machinectl shell keycloak@
cd ~/docker
docker compose exec postgres_db /bin/bash
psql -h localhost -p 5432 -U keycloak keycloak
Image personnalisée et exécution optimisée
- La configuration de base utilise l’image préconstruite de
quay.io
- Si une personnalisation de thème ou une exécution en mode
--optimized est nécessaire, construire sa propre image
- Le Dockerfile utilise un build multistage basé sur l’image officielle Keycloak
- Définir
ENV KC_DB=postgres à l’étape builder
- Exécuter
/opt/keycloak/bin/kc.sh build
- Copier
/opt/keycloak/ dans l’image finale
- Spécifier
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
- Dans
docker-compose.yml, modifier comme suit
- Supprimer ou commenter la ligne
image:
- Activer
build: .
- Ajouter
command: start --optimized
- Ensuite, arrêter la stack Docker, lancer éventuellement un build explicite, puis redémarrer
docker compose down
docker compose build
docker compose up -d && docker compose logs --follow
Ajustements supplémentaires en production
- Les avertissements de buffer de réception
MulticastSocket liés à JGroups se corrigent en ajoutant les valeurs de buffer suivantes dans /etc/sysctl.conf sur l’hôte
net.core.rmem_max = 26214400
net.core.wmem_max = 1048576
- Exécuter
sysctl -p pour appliquer la configuration
- L’avertissement de récupération des transactions XA de Quarkus se corrige en ajoutant un montage de volume et une variable d’environnement au service Keycloak
- Volume :
/srv/keycloak/data/keycloak/ObjectStore/:/ObjectStore/
- Variable d’environnement :
QUARKUS_TRANSACTION_MANAGER_ENABLE_RECOVERY: true
- Avant le démarrage, créer le répertoire ObjectStore sur l’hôte et, dans le conteneur, changer le propriétaire de
/ObjectStore pour l’ID utilisateur 1000
Étapes après configuration
- L’état final est une configuration où le service Keycloak dans Docker rootless s’exécute derrière le reverse proxy nginx système, nginx prenant en charge la terminaison SSL
- Pour la mise à jour automatique des conteneurs, se référer à la procédure de mise à jour automatique d’un autre billet Mastodon
- L’étape de configuration suivante consiste à ajouter l’e-mail dans la console d’administration Keycloak
- Ensuite, il est possible d’ajouter des realms et de configurer les thèmes
- Pour les thèmes, on peut utiliser keycloakify et keycloakify-starter
- Le Dockerfile contient une ligne commentée qui copie le JAR du thème keycloakify vers
/opt/keycloak/providers/
1 commentaires
Avis sur Hacker News
J’ai récemment ajouté une couche d’authentification à mon homelab et j’ai choisi Authelia
Keycloak fonctionne aussi, mais c’est trop massif, et il faut encore des services supplémentaires pour l’utiliser avec traefik forward auth
Authelia n’a pas d’interface UI pour modifier les utilisateurs et ne propose pas non plus de synchronisation bidirectionnelle avec un serveur LDAP backend, mais il se configure uniquement avec des fichiers statiques et des variables d’environnement, ce qui le rend bien adapté dans de nombreux cas
Si l’objectif est simplement d’ajouter de l’authentification à quelques services et du SSO là où c’est possible, cela vaut le coup de commencer par Authelia
Si vous avez besoin de SSO, d’une configuration simple et d’une UI d’administration, FusionAuth vaut aussi le détour. L’UI/UX a un petit côté milieu des années 2000, mais on peut le télécharger et l’exécuter soi-même[0], c’est Docker-friendly[1], et il propose plusieurs méthodes de configuration[2], comme la gestion d’OIDC ou d’autres paramètres avec Terraform[3]
C’est utilisable gratuitement, mais ce n’est pas 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
J’utilise Caddy comme reverse proxy et il fonctionne bien avec l’intégration d’Authelia[1]
J’ai ajouté une authentification à deux facteurs solide à tous les services, et je trouve l’ensemble suffisamment sûr pour accéder à mes applications auto-hébergées même sans VPN
Cela dit, Authelia n’a pas eu de nouvelle release depuis plus d’un an, ce qui m’inquiète du point de vue de la sécurité
[0] https://github.com/lldap/lldap
[1] https://www.authelia.com/integration/proxies/caddy/
[1] https://github.com/greenpau/caddy-security
C’est un excellent cas d’usage pour un homelab, surtout si l’on n’a pas besoin ou pas envie des fonctionnalités de solutions plus lourdes
Même en cherchant, je ne trouve rien de type schéma simple, JSON ou HTTP, et j’ai du mal à croire que tous ceux qui ont tout reconstruit n’aient pas aussi refait LDAP
À ma connaissance, le seul autre standard de fait est Active Directory
Je me demande aussi s’il existe un standard ou un protocole pour déléguer le contrôle d’accès à un service externe
Authelia peut contrôler l’accès à partir de motifs d’URL, mais pour quelque chose comme un serveur de fichiers, je m’attendrais plutôt à vérifier les autorisations sur un serveur LDAP en fonction de l’ID de l’utilisateur authentifié et des clés de la base de données
Cela semble aller dans le sens inverse d’OAuth2, où c’est le serveur qui obtient l’autorisation d’accéder à un service tiers
Récemment, j’ai étudié la mise en place d’un SSO relativement simple dans mon homelab, avec comme objectif principal de pouvoir se connecter facilement via l’authentification Google ou GitHub
Dans mon précédent emploi, j’avais utilisé à la fois JetBrains Hub[1] et Keycloak, et tous deux étaient assez pénibles à configurer
JetBrains Hub permettait vraiment de démarrer très facilement, et cela correspondait aussi à mon expérience passée, mais l’absence du tag
latestsur le registre Docker était gênanteJe sais qu’il est préférable d’épingler les versions, mais pour un usage personnel, je veux généralement mettre à jour tous mes conteneurs Docker d’un coup
À l’inverse, Keycloak était très pénible à prendre en main : c’était simple en mode développement, mais je me suis retrouvé bloqué sur la configuration de production
Si je me souviens bien, c’était lié à un certificat wildcard Let’s Encrypt, et j’ai abandonné après quelques heures
Au final, j’ai choisi Dex[2]. J’avais repoussé son adoption à cause d’une documentation insuffisante, mais la configuration réelle a été très simple : un YAML de base, une base de données SQLite et un sous-domaine suffisaient
J’ai combiné Dex avec l’excellent OAuth2 Proxy[3] et un modèle personnalisé de Nginx Proxy Manager, ce qui m’a permis de ramener la configuration SSO de chaque service interne à deux lignes, et j’ai aussi créé un modèle Docker Dex pour unRAID[4]
En complément, j’ai ajouté Cloudflare Access et un WAF pour renforcer la sécurité depuis l’extérieur du domicile, et je voudrais simplement ajouter CrowdSec pour obtenir un peu plus de visibilité
Personnellement, je pense que c’est l’option la plus simple
https://github.com/lastlogin-io/obligator
J’ai créé un tableau comparatif inachevé de plusieurs serveurs OpenID Connect auto-hébergeables[0]
L’un des points surprenants, c’est à quel point la base de code de Keycloak est énorme
[0]: https://github.com/lastlogin-io/obligator?tab=readme-ov-file...
L’idée que Keycloak résout les problèmes de sécurité est assez comique
Il suffit de regarder la liste des CVE pour comprendre ce que cela veut dire
Il serait aussi ridicule de dire qu’une solution fermée et opaque, sans CVE signalées, est « sûre »
Et la dernière version publiée, la 22.0.2, n’a que 3 vulnérabilités connues
https://www.cvedetails.com/vulnerability-list/vendor_id-25/p...
Au moins, le fait que l’article mentionne https://www.keycloakify.dev/ est très utile
Cela semble être une excellente alternative à l’approche standard des thèmes
Je l’utilise depuis 2 ans et je n’ai que du bien à en dire
Le mainteneur répond très vite, et récemment des changements ont aussi été apportés, côté Keycloak comme côté keycloakify, pour améliorer la compatibilité future de l’approche par thèmes
Pour l’instant, seules les applications créées avec create-react-app sont officiellement prises en charge, mais la branche vite est en cours de développement, et personnellement je l’utilise déjà avec vite depuis quelque temps
Je garde un œil sur authentik[1] et authelia[2]
Authelia a l’air très bien, mais alors que Keycloak dispose d’un connecteur pour Angular, avec Authelia il faut par exemple configurer soi-même un plugin OIDC pour Angular, ce qui me rendait un peu prudent
Cela dit, s’il existe une configuration pour Keycloak, le démarrage devrait être plus facile
[1] https://goauthentik.io/
[2] https://www.authelia.com/
Je protège en permanence plus de 10 services avec Docker et Kubernetes, et si vous n’aimez pas gérer la protection de chaque service de façon indépendante, authentik va vous faire souffrir
authentik a un bug critique[0] lorsqu’on protège plusieurs sous-domaines (app1.example.com, app2.example.com, etc.) avec une seule configuration : après l’expiration de la session, une nouvelle authentification redirige aléatoirement l’utilisateur vers un autre service
[0]: https://github.com/goauthentik/authentik/issues/6886
Il est impossible de corriger ça sans changement cassant, et cela ne fonctionne pas avec de nombreux outils qui utilisent le grant cc
Après avoir vu ça, je l’ai complètement retiré de ma liste de candidats
https://github.com/goauthentik/authentik/issues/6139
S’il y a quoi que ce soit sur la configuration Angular pour lequel je peux aider, je le ferai volontiers via GitHub Discussions
Authentik semblait meilleur, mais le bug mentionné dans une autre réponse a l’air assez inquiétant
Le problème de Keycloak, c’est que c’est un vieux projet qui a connu énormément de changements
Il a commencé comme un projet JBOSS, et son utilité en tant qu’IdP brille pour l’authentification de clusters on-premise, mais pas vraiment au-delà
J’ai déployé Keycloak à grande échelle sur AWS ECS dans un service d’une entreprise du Fortune 500, et parvenir à un clustering correct a ressemblé à une guerre de Cent Ans
La découverte DNS ne fonctionnait pas correctement, et la découverte de cluster reposait sur UDP, donc cela ne marchait pas dans le cloud
Les connexions avec état présentes sur un serveur n’existaient pas sur les autres, donc un simple équilibrage de charge était impossible, et les sessions persistantes étaient la seule option
Lancer Keycloak avec
docker runpour l’utiliser comme Auth0, c’est facile, mais ça donne l’impression d’acheter un Ford F-150 de 1996 avec 250 000 miles au compteurÇa roule et ça fonctionne, mais la maintenance est vraiment horrible
Si je me souviens bien, le mode de découverte par défaut utilise le multicast, qui n’est pas activé dans les réseaux cloud classiques ni dans les réseaux overlay de Swarm/Kubernetes
J’ai aussi vu le ping base de données, qui utilise le SGBDR comme une sorte de mécanisme de quorum, mais cela semblait très fragile, presque comme une solution de dernier recours
Au final, on a pu utiliser le driver de cluster Kubernetes pour découvrir les nœuds via le DNS du cluster Swarm
C’était assez difficile à faire fonctionner, mais une fois en place, à ma connaissance, c’est resté stable
Il semble qu’il existe aujourd’hui un driver réseau EC2 natif, mais je ne l’ai pas exploré moi-même
Je me demande quand ce déploiement sur ECS a eu lieu
Chez nous, l’UDP n’est autorisé que pour le DNS
Keycloak est excellent, mais il peut être assez déroutant pour les débutants
Il a beaucoup de fonctionnalités et la documentation n’est pas exceptionnelle
J’ai récemment essayé Zitadel, et c’était bien plus simple à utiliser
En revanche, on ne peut pas l’exécuter avec une base de données intégrée, donc l’auto-hébergement est un peu plus compliqué
À l’avenir, ils vont utiliser Postgres comme base de données, donc j’espère que cela facilitera le déploiement avec d’autres outils
Mon manager a récemment qualifié Keycloak de « cadeau qui continue de donner », ce qui voulait en fait dire que de nouveaux tickets Jira apparaissaient sans cesse juste pour comprendre comment faire telle ou telle chose
Malgré ça, nous avons du Terraform pour créer un cluster EKS, déployer Keycloak, créer des clients SAML/OIDC, ajouter des fournisseurs d’identité externes, et même configurer AWS IAM Identity Provider
Une fois qu’on a compris ce qu’il est possible de faire, comment le faire dans l’UI, et comment l’automatiser avec le provider Terraform de mrparkers, l’utilisation elle-même devient très simple
Un ami en aurait besoin :)
Après avoir utilisé Keycloak pendant plusieurs années, j’ai honnêtement commencé à en avoir assez de tous ses comportements bizarres et j’ai commencé à chercher une alternative
Plusieurs candidats, dont Authentik, semblaient corrects, mais Zitadel[1] a retenu mon attention, et je ne me suis pas retourné depuis
[1] https://zitadel.com/blog/zitadel-vs-keycloak
Je suis curieux de savoir ce qui t’a convaincu de façon décisive