Keycloak : un SSO pour vos applications auto-hébergées
Dès que l'on héberge plus de deux ou trois services sur un VPS Linux, la gestion des comptes devient un problème en soi : un mot de passe pour Nextcloud, un autre pour Grafana, un troisième pour Portainer, chacun avec sa propre politique de double authentification. Keycloak règle ce problème en centralisant l'authentification. C'est un fournisseur d'identité open source, créé chez Red Hat, bâti sur Quarkus et hébergé par la CNCF (Cloud Native Computing Foundation) comme projet en incubation depuis avril 2023. Il parle les protocoles standard OpenID Connect (OIDC), OAuth 2.0 et SAML 2.0 : toute application compatible délègue sa page de connexion à Keycloak, qui gère les utilisateurs, les mots de passe, les rôles, les sessions et la 2FA par code OTP ou clé WebAuthn.
Concrètement, un utilisateur se connecte une seule fois (single sign-on, SSO) et accède ensuite à Nextcloud, Grafana, Portainer, Proxmox VE ou Jellyfin (via un plugin communautaire) sans ressaisir ses identifiants. Désactiver un compte dans Keycloak le coupe partout en même temps. Ce guide déploie Keycloak en mode production avec Docker Compose et PostgreSQL, derrière un reverse proxy nginx ou Traefik en HTTPS, puis crée un realm, un client OIDC et des utilisateurs, et branche Grafana comme première application. Il couvre aussi la mémoire de la JVM, la sauvegarde de la base et les erreurs classiques de hostname et de redirection.
Les commandes sont prévues pour Ubuntu 24.04 LTS ou Debian 13 et la branche Keycloak 26.8 (version 26.8.2 au moment de la rédaction).
Prérequis
- Un VPS Linux avec au moins 4 Go de RAM : Keycloak seul réclame 2 Go pour un petit déploiement de production, et PostgreSQL, nginx et vos autres conteneurs ont besoin du reste ;
- Docker Engine et Docker Compose v2 installés (installer Docker sur un VPS) ; pour la syntaxe des fichiers Compose, voir Docker Compose sur VPS Linux ;
- Un sous-domaine dédié, par exemple
sso.exemple.fr, avec un enregistrement DNS de type A vers l'adresse IP publique du VPS ; - Les ports 80 et 443 ouverts dans le pare-feu (ouvrir des ports avec UFW) ;
- Un accès SSH par clé avec un utilisateur non root membre du groupe
docker(sécuriser SSH sur VPS Linux).
Pourquoi pas start-dev : mode développement et mode production
La plupart des tutoriels lancent Keycloak avec la commande start-dev. C'est le mode développement : il accepte le HTTP en clair, stocke les données dans une base de fichiers dev-file embarquée et ne vérifie pas le hostname. La documentation officielle le déconseille explicitement pour un serveur exposé. Le mode start impose un hostname, une vraie base de données et une terminaison TLS, ce qui est exactement ce que l'on veut sur un VPS.
| Réglage | start-dev | start (production) |
|---|---|---|
| Base de données par défaut | dev-file (fichier local, données perdues si le conteneur est recréé sans volume) | À fournir : PostgreSQL, MariaDB, MySQL, Oracle ou SQL Server |
| Hostname | Déduit de chaque requête (hostname-strict à false) | Obligatoire via KC_HOSTNAME, sinon le serveur refuse de démarrer |
| Transport | HTTP sur le port 8080 | HTTPS sur 8443, ou HTTP sur 8080 si KC_HTTP_ENABLED=true derrière un reverse proxy |
| Cache | local | ispn (Infinispan, prêt pour un cluster) |
| Usage | Poste de développement, tests | Tout serveur accessible depuis Internet |
Préparer le projet et les secrets
Créez un répertoire dédié et un fichier .env qui contiendra les secrets. Docker Compose lit ce fichier automatiquement pour remplacer les variables ${...} du fichier YAML, ce qui évite d'écrire les mots de passe en clair dans docker-compose.yml :
mkdir -p ~/keycloak && cd ~/keycloak
cat > .env <<EOF
DB_PASSWORD=$(openssl rand -base64 32 | tr -d '/+=')
KC_ADMIN_USER=bootstrap
KC_ADMIN_PASSWORD=$(openssl rand -base64 24 | tr -d '/+=')
EOF
chmod 600 .env && cat .envNotez le mot de passe du compte bootstrap : il sert une seule fois, pour la première connexion à la console d'administration. Keycloak crée ce compte dans le realm master au premier démarrage uniquement, le marque comme temporaire et affiche une bannière tant qu'il existe. Vous le remplacerez par un administrateur permanent un peu plus loin.
Le fichier docker-compose.yml : Keycloak et PostgreSQL
La pile tient en deux services : la base de données PostgreSQL 17 et Keycloak lui-même, lancé avec start. Keycloak teste officiellement PostgreSQL 18 et prend en charge les versions 14 à 18.
cat > docker-compose.yml <<'EOF'
services:
db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U keycloak -d keycloak"]
interval: 10s
timeout: 5s
retries: 5
keycloak:
image: quay.io/keycloak/keycloak:26.8
restart: unless-stopped
command: start
depends_on:
db:
condition: service_healthy
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://db:5432/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: ${DB_PASSWORD}
KC_HOSTNAME: https://sso.exemple.fr
KC_HTTP_ENABLED: "true"
KC_PROXY_HEADERS: xforwarded
KC_HEALTH_ENABLED: "true"
KC_METRICS_ENABLED: "true"
KC_BOOTSTRAP_ADMIN_USERNAME: ${KC_ADMIN_USER}
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD}
ports:
- 127.0.0.1:8080:8080
deploy:
resources:
limits:
memory: 2G
healthcheck:
test:
- CMD
- bash
- -c
- >-
{ printf 'HEAD /health/ready HTTP/1.0\r\n\r\n' >&0;
grep -q 'HTTP/1.0 200'; } 0<>/dev/tcp/localhost/9000
interval: 30s
timeout: 5s
retries: 5
start_period: 90s
volumes:
pgdata:
EOFRemplacez sso.exemple.fr par votre sous-domaine. Chaque variable KC_* correspond à une option de la ligne de commande kc.sh et joue un rôle précis :
| Variable | Rôle |
|---|---|
KC_DB, KC_DB_URL, KC_DB_USERNAME, KC_DB_PASSWORD | Connexion JDBC à PostgreSQL. db est le nom du service Compose, résolu sur le réseau interne de la pile. |
KC_HOSTNAME | URL publique de Keycloak. Avec le schéma https://, Keycloak fixe lui-même le protocole et le port dans toutes les URL qu'il génère (découverte OIDC, redirections, liens de réinitialisation) au lieu de les déduire de la requête. |
KC_HTTP_ENABLED | Autorise l'écoute en HTTP sur le port 8080. Le chiffrement TLS est assuré par le reverse proxy, qui termine le HTTPS (mode edge). |
KC_PROXY_HEADERS | xforwarded fait lire à Keycloak les en-têtes X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host et X-Forwarded-Port envoyés par nginx ou Traefik. La valeur forwarded attend l'en-tête Forwarded de la RFC 7239. Sans cette option, les requêtes passées par le proxy qui vérifient leur origine reçoivent une erreur 403. |
KC_PROXY_TRUSTED_ADDRESSES (optionnel) | Liste d'adresses ou de plages CIDR dont les en-têtes X-Forwarded-* sont acceptés. Par défaut, tout est accepté. Avec nginx installé sur l'hôte, mettez la plage du réseau Docker de la pile (docker network inspect keycloak_default). |
KC_HEALTH_ENABLED, KC_METRICS_ENABLED | Activent les endpoints /health/* et /metrics sur le port de management 9000, que l'on ne publie pas. Le healthcheck Compose utilise bash et /dev/tcp parce que l'image officielle ne contient pas curl. |
KC_BOOTSTRAP_ADMIN_USERNAME, KC_BOOTSTRAP_ADMIN_PASSWORD | Compte administrateur temporaire, créé au premier démarrage seulement. Les anciennes variables KEYCLOAK_ADMIN et KEYCLOAK_ADMIN_PASSWORD des tutoriels d'avant Keycloak 26 ne sont plus la méthode documentée. |
Le port 8080 n'est exposé que sur 127.0.0.1 : seul le reverse proxy local peut joindre Keycloak. Le port 9000 n'est pas publié du tout. Si vous préférez Traefik dans un conteneur, retirez le bloc ports et ajoutez les labels présentés plus bas.
Reverse proxy nginx ou Traefik en HTTPS
Keycloak n'accepte pas un déploiement sans TLS, et derrière un proxy il a besoin de connaître le protocole et l'hôte vus par le navigateur. La documentation demande que le reverse proxy écrase les en-têtes X-Forwarded-* plutôt que de les compléter, pour qu'un client ne puisse pas injecter sa propre valeur. D'où $remote_addr plutôt que $proxy_add_x_forwarded_for dans la configuration nginx ci-dessous. Si nginx n'est pas encore installé, suivez d'abord nginx en reverse proxy sur VPS Linux.
sudo apt update && sudo apt install -y nginx certbot python3-certbot-nginx
sudo nano /etc/nginx/sites-available/keycloak.confserver {
listen 80;
server_name sso.exemple.fr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# Console d'administration et realm master : uniquement depuis vos adresses
location ~ ^/(admin|realms/master)/ {
allow 203.0.113.42; # votre IP fixe
allow 100.64.0.0/10; # plage Tailscale, si vous l'utilisez
deny all;
proxy_pass http://127.0.0.1:8080;
}
location / {
proxy_pass http://127.0.0.1:8080;
}
}sudo ln -s /etc/nginx/sites-available/keycloak.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d sso.exemple.frCertbot ajoute le bloc listen 443 ssl, le certificat Let's Encrypt et la redirection HTTP vers HTTPS, puis renouvelle le certificat tout seul (Certbot et Let's Encrypt sur VPS Linux). La restriction sur /admin/ et /realms/master/ suit la recommandation officielle de ne pas exposer la console d'administration à tout Internet. Si vous n'avez pas d'IP fixe, passez par un réseau privé Tailscale entre votre poste et le VPS : faites résoudre sso.exemple.fr vers l'adresse Tailscale du serveur dans le fichier hosts de votre poste, et nginx verra arriver la console depuis la plage 100.64.0.0/10.
Un mot sur le chiffrement entre nginx et le conteneur : ici TLS s'arrête au proxy et Keycloak écoute en HTTP sur la boucle locale, ce que la documentation appelle le mode edge. Elle lui préfère le mode re-encrypt, où le proxy rechiffre vers Keycloak. Sur un VPS unique où ce trafic ne quitte jamais 127.0.0.1, le mode edge est le compromis habituel ; dès que le proxy et Keycloak tournent sur deux machines, configurez un certificat côté Keycloak (KC_HTTPS_CERTIFICATE_FILE et KC_HTTPS_CERTIFICATE_KEY_FILE) et retirez KC_HTTP_ENABLED.
Variante Traefik. Traefik renseigne de lui-même X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host et X-Forwarded-Port vers le conteneur cible, donc KC_PROXY_HEADERS=xforwarded reste valable. Dans le service keycloak, remplacez le bloc ports par le réseau partagé avec Traefik et ces labels :
labels:
- traefik.enable=true
- traefik.http.routers.keycloak.rule=Host(`sso.exemple.fr`)
- traefik.http.routers.keycloak.entrypoints=websecure
- traefik.http.routers.keycloak.tls.certresolver=letsencrypt
- traefik.http.services.keycloak.loadbalancer.server.port=8080Le nom du certresolver et de l'entrypoint dépendent de votre configuration Traefik. Pour une vue d'ensemble des façons de publier un conteneur en HTTPS, voir publier un service en HTTPS sur un VPS Linux.
Démarrer Keycloak et créer l'administrateur permanent
docker compose up -d
docker compose logs -f keycloakSans image pré-construite, le premier démarrage exécute une phase de build interne puis applique les migrations de schéma sur PostgreSQL : comptez une à deux minutes. La ligne de log qui annonce started in puis Listening on: http://0.0.0.0:8080 indique que le serveur est prêt, et docker compose ps doit afficher healthy après le délai de grâce de 90 secondes du healthcheck.
Ouvrez https://sso.exemple.fr/admin/ et connectez-vous avec le compte bootstrap. La console affiche un avertissement : ce compte est temporaire. Créez tout de suite votre administrateur définitif dans le realm master :
- Users, puis Create new user : renseignez le nom d'utilisateur et l'e-mail, validez avec Create ;
- onglet Credentials, Set password, avec Temporary désactivé ;
- onglet Role mapping, Assign role, filtrez sur les rôles de realm et cochez
admin; - déconnectez-vous, reconnectez-vous avec ce nouveau compte, puis supprimez l'utilisateur
bootstrap. Vous pouvez aussi retirer les deux variablesKC_BOOTSTRAP_*du fichier Compose : elles ne servent qu'au tout premier démarrage.
Activez immédiatement la double authentification sur ce compte depuis la console du compte, https://sso.exemple.fr/realms/master/account/, rubrique Signing in. Un administrateur Keycloak sans 2FA, c'est la clé de toutes vos applications derrière un seul mot de passe.
Créer un realm, des utilisateurs et imposer la 2FA
Un realm est un espace isolé : ses utilisateurs, ses rôles, ses clients et ses réglages de sécurité ne sont partagés avec aucun autre realm. Le realm master est réservé à l'administration de Keycloak. Vos applications et vos utilisateurs vont dans un realm dédié :
- Menu Manage realms, bouton Create realm, nom
homelab, puis Create. Le realm créé devient le realm courant ; - Realm roles, Create role : créez
admin,editoretviewer. Ces trois rôles seront traduits en rôles Grafana plus loin ; - Users, Create new user : nom d'utilisateur, e-mail, prénom, nom, Create, puis onglet Credentials pour le mot de passe et onglet Role mapping pour attribuer les rôles. Vous pouvez laisser Temporary activé : l'utilisateur devra changer son mot de passe à la première connexion.
Pour la double authentification, allez dans Authentication, onglet Required actions, et activez Set as default action sur la ligne Configure OTP. Tout nouvel utilisateur devra enregistrer une application TOTP (FreeOTP, Google Authenticator, Aegis ou tout autre client compatible) à sa première connexion. Pour les comptes déjà créés, ajoutez Configure OTP dans le champ Required user actions de leur fiche. L'onglet Policies permet de régler le type de code (TOTP ou HOTP), sa longueur et sa durée.
L'URL de découverte OpenID Connect du realm, à fournir aux applications qui savent se configurer seules, est https://sso.exemple.fr/realms/homelab/.well-known/openid-configuration. Ouvrez-la dans un navigateur : si les champs issuer, authorization_endpoint et token_endpoint commencent bien par https://sso.exemple.fr, le hostname et les en-têtes de proxy sont corrects.
Créer un client OIDC
Dans le vocabulaire Keycloak, un client est une application autorisée à demander l'authentification des utilisateurs du realm. Chaque application auto-hébergée a son propre client, avec son identifiant, son secret et la liste des URL de redirection autorisées. Exemple pour Grafana :
- Clients, Create client : type OpenID Connect, Client ID
grafana, puis Next ; - Étape Capability config : activez Client authentication (client confidentiel, avec secret) et laissez Standard flow coché, c'est le flux authorization code utilisé par les applications web ; Next ;
- Étape Login settings : Root URL
https://grafana.exemple.fr, Valid redirect URIshttps://grafana.exemple.fr/login/generic_oauth, Web originshttps://grafana.exemple.fr, puis Save ; - onglet Credentials : copiez le Client secret.
La liste Valid redirect URIs est le réglage le plus sensible : Keycloak refuse toute redirection vers une URL qui n'y figure pas, et c'est voulu. Évitez le joker * seul, qui autoriserait n'importe quel site à récupérer un code d'autorisation. Sous l'onglet Client scopes, le scope roles est assigné par défaut : il place les rôles de realm de l'utilisateur dans le jeton d'accès, sous le claim realm_access.roles. Le sous-onglet Evaluate permet de générer un jeton d'exemple pour un utilisateur et de vérifier les claims réellement envoyés.
Brancher une première application : Grafana
Grafana prend en charge n'importe quel fournisseur OIDC via sa section [auth.generic_oauth]. Chaque clé de grafana.ini se surcharge par une variable d'environnement de la forme GF_<SECTION>_<CLÉ>, les points de la section devenant des tirets bas. Si Grafana tourne déjà en conteneur, comme dans notre guide Grafana et Prometheus sur VPS Linux, ajoutez ces variables à son service Compose :
environment:
GF_SERVER_ROOT_URL: https://grafana.exemple.fr
GF_AUTH_GENERIC_OAUTH_ENABLED: "true"
GF_AUTH_GENERIC_OAUTH_NAME: Keycloak
GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP: "true"
GF_AUTH_GENERIC_OAUTH_CLIENT_ID: grafana
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET: le-secret-copie-dans-keycloak
GF_AUTH_GENERIC_OAUTH_SCOPES: openid email profile offline_access roles
GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_PATH: email
GF_AUTH_GENERIC_OAUTH_LOGIN_ATTRIBUTE_PATH: preferred_username
GF_AUTH_GENERIC_OAUTH_NAME_ATTRIBUTE_PATH: name
GF_AUTH_GENERIC_OAUTH_AUTH_URL: https://sso.exemple.fr/realms/homelab/protocol/openid-connect/auth
GF_AUTH_GENERIC_OAUTH_TOKEN_URL: https://sso.exemple.fr/realms/homelab/protocol/openid-connect/token
GF_AUTH_GENERIC_OAUTH_API_URL: https://sso.exemple.fr/realms/homelab/protocol/openid-connect/userinfo
GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH: "contains(realm_access.roles[*], 'admin') && 'Admin' || contains(realm_access.roles[*], 'editor') && 'Editor' || 'Viewer'"Après docker compose up -d, la page de connexion de Grafana propose un bouton Sign in with Keycloak. L'expression role_attribute_path est évaluée en JMESPath sur le jeton d'identité, puis la réponse userinfo, puis le jeton d'accès : un utilisateur porteur du rôle de realm admin devient administrateur Grafana, editor devient éditeur, et tous les autres sont lecteurs. GF_SERVER_ROOT_URL garantit que l'URL de retour /login/generic_oauth est construite avec le bon domaine derrière le reverse proxy.
Et Nextcloud ? Le principe est identique avec l'application OpenID Connect user backend (user_oidc), installable depuis le catalogue d'applications. Créez un client nextcloud dans Keycloak avec https://cloud.exemple.fr/* en URL de redirection, puis déclarez le fournisseur en une commande sur votre instance (voir installer Nextcloud avec Docker Compose) :
docker compose exec --user www-data app php occ user_oidc:provider keycloak \
--clientid=nextcloud --clientsecret=le-secret \
--discoveryuri=https://sso.exemple.fr/realms/homelab/.well-known/openid-configurationPortainer (fournisseur OAuth personnalisé), Proxmox VE (realm de type OpenID Connect) et Jellyfin (plugin SSO communautaire) se branchent de la même façon : un client par application, l'URL de découverte du realm, et les rôles ou groupes Keycloak pour les droits.
Mémoire : dimensionner la JVM de Keycloak
Keycloak tourne dans une machine virtuelle Java, et la taille de son tas (heap) se calcule à partir de la mémoire du conteneur : par défaut, l'image fixe -XX:MaxRAMPercentage=70 (tas maximal à 70 % de la mémoire du conteneur) et -XX:InitialRAMPercentage=50 (tas initial à 50 %). D'où la règle de la documentation : toujours définir une limite mémoire sur le conteneur. Sans limite, la JVM considère toute la RAM du VPS comme sienne, peut grimper jusqu'à 70 % de celle-ci et ne la rend que lentement au système, au détriment de PostgreSQL et de vos autres services.
La limite de 2 Go du fichier Compose correspond à la recommandation officielle pour un petit déploiement de production. En dessous, la documentation indique un plancher de 750 Mo pour retrouver l'ancien plafond de tas de 512 Mo : c'est viable pour quelques utilisateurs, mais sans marge pour les pics d'activité. Pour ajuster finement, la variable JAVA_OPTS_KC_HEAP remplace les options de tas par défaut :
JAVA_OPTS_KC_HEAP: "-XX:MaxRAMPercentage=65 -XX:MaxHeapFreeRatio=30"Surveillez la consommation réelle avec docker stats keycloak-keycloak-1 et, sur le VPS lui-même, avec htop ou btop. Un conteneur qui disparaît avec le code de sortie 137 a été tué par le noyau faute de mémoire : augmentez la limite ou passez sur un VPS mieux doté plutôt que de rogner sur la JVM.
Sauvegarder Keycloak : la base PostgreSQL
Tout l'état de Keycloak vit dans PostgreSQL : realms, clients, secrets, utilisateurs, mots de passe hachés, secrets OTP, sessions hors ligne. Sauvegarder la base, c'est sauvegarder Keycloak. Un pg_dump au format personnalisé, compressé, lancé depuis le conteneur de base :
mkdir -p ~/backups/keycloak
docker compose -f ~/keycloak/docker-compose.yml exec -T db \
pg_dump -U keycloak -Fc keycloak > ~/backups/keycloak/keycloak-$(date +%F).dumpPour restaurer sur une base vide, par exemple sur un nouveau VPS après avoir relancé la pile :
docker compose exec -T db pg_restore -U keycloak -d keycloak --clean --if-exists \
< ~/backups/keycloak/keycloak-2026-11-07.dump
docker compose restart keycloakPlanifiez la sauvegarde chaque nuit avec un timer systemd ou une tâche cron, puis copiez les fichiers hors du serveur (sauvegarder un VPS avec rsync). Ces dumps contiennent les secrets de tous vos clients OIDC : chiffrez-les avant de les envoyer hors site. En complément, Realm settings, menu Action, Partial export produit un fichier JSON de la configuration du realm (clients, rôles, groupes) sans les utilisateurs, pratique pour versionner ou rejouer la configuration sur une instance de test. Avant toute mise à jour de l'image Keycloak, faites un dump : les migrations de schéma sont automatiques mais pas réversibles.
Erreurs classiques de hostname et de redirection
Neuf problèmes sur dix avec Keycloak derrière un reverse proxy viennent du trio hostname, en-têtes de proxy et URL de redirection. La page de diagnostic intégrée aide à trancher : ajoutez KC_HOSTNAME_DEBUG: "true" au service, relancez, puis ouvrez https://sso.exemple.fr/realms/homelab/hostname-debug. Elle affiche les en-têtes reçus et les URL que Keycloak en déduit. Retirez l'option ensuite.
| Symptôme | Cause probable | Correction |
|---|---|---|
Keycloak s'arrête au démarrage en mode start en réclamant un hostname | KC_HOSTNAME absent : en production, hostname-strict vaut true | Définir KC_HOSTNAME avec l'URL publique complète |
| Erreur 403 sur la console d'administration ou sur une page de login passée par le proxy | KC_PROXY_HEADERS absent, ou proxy qui n'envoie pas les X-Forwarded-* | Ajouter KC_PROXY_HEADERS=xforwarded et vérifier les proxy_set_header nginx |
| Message HTTPS required sur la page de connexion | Keycloak croit recevoir du HTTP en clair : X-Forwarded-Proto manquant ou non pris en compte | Même correction que ci-dessus ; ne pas baisser le réglage Require SSL du realm |
Liens générés en http://, avec le port 8080, ou vers un mauvais hôte ; boucle de redirection | KC_HOSTNAME réduit au nom d'hôte sans schéma, ou X-Forwarded-Host et X-Forwarded-Port absents | Écrire KC_HOSTNAME=https://sso.exemple.fr avec le schéma, contrôler via hostname-debug |
| Invalid parameter: redirect_uri au moment de se connecter à une application | L'URL de retour envoyée par l'application ne figure pas dans Valid redirect URIs du client | Ajouter l'URL exacte (schéma, hôte, chemin) ; côté Grafana, vérifier GF_SERVER_ROOT_URL |
| Erreur Invalid client credentials ou unauthorized_client | Secret erroné, ou Client authentication désactivé alors que l'application envoie un secret | Régénérer le secret dans l'onglet Credentials et le recopier |
Configuration copiée d'un ancien tutoriel : KC_PROXY=edge, KEYCLOAK_ADMIN, PROXY_ADDRESS_FORWARDING | Options d'anciennes versions : l'option proxy et le hostname v1 ont été retirés dans Keycloak 26 | Utiliser KC_PROXY_HEADERS, KC_HOSTNAME et KC_BOOTSTRAP_ADMIN_* |
| Le conteneur redémarre en boucle, code 137 | Limite mémoire trop basse pour la JVM | Remonter la limite à 2 Go, vérifier la RAM libre du VPS |
Mettre à jour Keycloak
Le tag 26.8 suit les correctifs de la branche : docker compose pull puis docker compose up -d appliquent la dernière version 26.8.x. Les versions correctives arrivent souvent et corrigent des failles sérieuses : la 26.8.1 du 13 octobre 2026 en comptait plus de quinze, dont un contournement de la 2FA obligatoire et une élévation de privilèges d'un administrateur délégué. Un fournisseur d'identité en retard d'un correctif expose toutes les applications qu'il protège. Avant de changer de version mineure (26.8 vers 26.9), lisez le guide de migration officiel et faites un dump de la base. Pensez aussi à nettoyer les anciennes images Docker après quelques mises à jour.
Conclusion
Avec deux services Compose, un sous-domaine et une dizaine de variables KC_*, vous disposez d'un fournisseur d'identité de niveau professionnel sur votre VPS Linux : SSO OpenID Connect pour toutes vos applications auto-hébergées, double authentification imposée au niveau du realm, rôles centralisés et une seule base PostgreSQL à sauvegarder. Les trois réglages à ne jamais improviser sont KC_HOSTNAME avec son schéma https://, KC_PROXY_HEADERS accordé aux en-têtes réellement envoyés par nginx ou Traefik, et la limite mémoire du conteneur. Si la pile grossit, un serveur dédié permet d'ajouter un second nœud Keycloak et une base PostgreSQL répliquée sans changer la configuration des applications.
FiveM
Minecraft
Rust
RedM
Hytale