Guide de déploiement

ZITADEL sur VPS : IAM open source pour développeurs

Déployer sur un VPS Cloud →

Tutoriel

ZITADEL sur VPS : IAM open source pour développeurs

Self-hosting11 min de lecture8 étapes

ZITADEL est une plateforme IAM open source écrite en Go : SSO OIDC/OAuth 2.0, passkeys et multi-tenant natif, en self-hosted. Ce guide la déploie sur un VPS ServOrbit avec Docker Compose, corrige les chiffres que l'ancienne version répétait sans source, et documente ce qui ne marche pas encore : la découverte de domaine (Domain Discovery), ouverte en bug sur la v4 depuis septembre 2025. Guide fourni, sans prise en charge.

Sommaire· Pourquoi choisir ZITADEL plutôt qu'Authentik ou Keycloak ?1/18
  1. 01Pourquoi choisir ZITADEL plutôt qu'Authentik ou Keycloak ?
  2. 02Prérequis chiffrés
  3. 03Installer ZITADEL depuis le Marketplace
  4. 04Installation en 3 étapes
  5. 05Ce que déploie le template
  6. 06Domaine externe, TLS et reverse proxy
  7. 07Créer votre première application OIDC
  8. 08Intégrer ZITADEL avec vos applications self-hosted
  9. 09Gérer le multi-tenant : organisations et projets
  10. 10Conseil : activer les passkeys dès le départ
  11. 11Découverte de domaine : ce qui doit fonctionner
  12. 12Limites connues : le ticket zitadel/zitadel n°10662
  13. 13Ticket n°10662 : confirmé et rapporté
  14. 14Dépannage de la connexion SSO et du domaine vérifié
  15. 15Diagnostic en 5 étapes
  16. 16Mises à jour et sécurité
  17. 17Avant de mettre à jour
  18. 18Installer ZITADEL via le Marketplace ServOrbit

Pourquoi choisir ZITADEL plutôt qu'Authentik ou Keycloak ?

ZITADEL occupe un créneau précis parmi les plateformes d'authentification open source. Contrairement à Authelia (proxy d'authentification sans gestion d'utilisateurs propre) ou Authentik (IdP full-stack riche en fonctionnalités), il vise les équipes de développement qui veulent un IAM de niveau entreprise dès le départ : multi-tenant natif, APIs gRPC + REST complètes, provider Terraform officiel (zitadel/zitadel sur le registre Terraform).

Sur la mémoire, restez prudent. La documentation d'exploitation indique que ZITADEL lui-même demande environ 512 Mo de RAM et moins d'un cœur CPU, base de données non comprise, avec des pics CPU au hachage des mots de passe. L'ancienne version de cet article annonçait « moins de 100 Mo » : ce chiffre ne figure pas dans la documentation, ne dimensionnez pas votre VPS dessus. Le comparatif de ressources avec Keycloak n'est pas chiffré ici faute de mesure sourcée.

Prérequis chiffrés

  • VPS : 2 vCPU et 2 Go de RAM (le guide Docker Compose amont demande au moins 2 Go), Ubuntu 24.04. Prévoyez davantage dès que la base grossit : l'amont compte environ 4 Go de RAM par cœur de base de données.
  • Docker : Docker Engine 24 ou plus avec Compose v2 ; l'ancien binaire docker-compose (v1) n'est pas pris en charge.
  • PostgreSQL : les versions 14 à 18 sont prises en charge. Le template ServOrbit déploie PostgreSQL 16.
  • Ports : ZITADEL écoute en interne sur 8080. Seul 443 doit être public (plus 80 si vous laissez Let's Encrypt émettre le certificat). Le template lie 8080 à 127.0.0.1 et laisse nginx servir l'extérieur.
  • Domaine : un nom ou sous-domaine pointant vers l'IP du VPS, par exemple auth.votre-domaine.com, en HTTPS.
  • Masterkey : ZITADEL_MASTERKEY doit faire exactement 32 caractères et ne peut plus changer après l'initialisation sans perdre l'accès aux données chiffrées. Le template la génère ; sauvegardez-la hors du VPS.

Installer ZITADEL depuis le Marketplace

Installation en 3 étapes

  1. Créer le VPS

    Depuis votre espace client ServOrbit, choisissez la gamme VPS et cliquez sur Configurer. Dans le champ Application, sélectionnez ZITADEL. Saisissez votre domaine (ex. auth.votre-domaine.com).

    Si vous n'avez pas de domaine, le sous-domaine gratuit ServOrbit est disponible immédiatement, HTTPS inclus.

  2. Démarrage automatique

    Le script d'installation génère le MASTERKEY, le mot de passe PostgreSQL et le mot de passe admin, puis lance PostgreSQL 16 et ZITADEL via Docker Compose. Durée habituelle : 2 à 4 minutes.

  3. Accéder à la console

    Une fois l'installation terminée, vos identifiants sont affichés dans l'espace client.
    - URL : https://<votre-domaine>/ui/console
    - Identifiant : admin. Si la page le refuse, essayez admin@zitadel.<votre-domaine> : ZITADEL compose les noms de connexion sous la forme [email protected], comme dans l'exemple [email protected] de l'amont.
    - Mot de passe : celui qui a été généré

    Connectez-vous et changez-le immédiatement.

Ce que déploie le template

Le template est un fichier Docker Compose de deux services : db (PostgreSQL 16) et zitadel, lancé avec start-from-init --tlsMode disabled --masterkeyFromEnv. Le TLS est donc terminé par nginx, pas par ZITADEL. L'image suivie est le tag stable de ghcr.io/zitadel/zitadel, ce qui signifie que la version réellement démarrée dépend du jour où l'image a été tirée : contrôlez-la avec docker compose images (voir la section sur les mises à jour).

Le domaine est transmis à ZITADEL_EXTERNALDOMAIN, avec ZITADEL_EXTERNALPORT=443 et ZITADEL_EXTERNALSECURE=true. Le template considère le domaine comme figé au premier démarrage : choisissez le bon dès le départ.

Domaine externe, TLS et reverse proxy

  • Trois valeurs à aligner — ZITADEL_EXTERNALDOMAIN, ZITADEL_EXTERNALPORT et ZITADEL_EXTERNALSECURE doivent décrire l'URL publique réelle. ZITADEL ne sert que les requêtes envoyées au protocole, à l'hôte et au port attendus ; sinon vous obtenez « Instance not found ».
  • Changer de domaine — l'amont documente que ces options peuvent être modifiées à tout moment, à condition de rejouer la phase de setup. Ce n'est donc pas impossible comme l'affirmait l'ancienne version, mais ce n'est pas un geste anodin : toute application cliente référence l'ancienne URL.
  • Hôte conservé — le reverse proxy doit transmettre l'en-tête Host d'origine et X-Forwarded-Proto: https. L'exemple nginx amont termine le TLS puis parle à ZITADEL en HTTP/2 non chiffré (h2c) avec grpc_pass.
  • HTTP/2 de bout en bout — la console exige HTTP/2 jusqu'à ZITADEL. Les proxys testés par l'amont sont Traefik v3, NGINX 1.x stable, Caddy v2 et Apache httpd 2.4.
  • CDN ou WAF devant — la documentation précise qu'un proxy, un WAF ou un CDN placé devant ZITADEL doit lui aussi supporter HTTP/2. Testez la console après toute bascule de DNS vers un mode proxifié.

Créer votre première application OIDC

Une fois connecté à la console ZITADEL :

1. Allez dans Projects puis Create
2. Nommez votre projet (ex. My App)
3. Cliquez sur Add Application
4. Choisissez le type : Web (applications serveur), Native (mobile/desktop) ou API (machine-to-machine)
5. Pour une app Web, choisissez PKCE (recommandé) et renseignez vos Redirect URIs

ZITADEL génère le Client ID. Notez le discovery endpoint OIDC : https://<votre-domaine>/.well-known/openid-configuration.

Intégrer ZITADEL avec vos applications self-hosted

Toute application qui parle OIDC peut s'appuyer sur ZITADEL : il suffit du Client ID, du secret éventuel et du discovery endpoint. Exemples courants :

  • Gitea : Administration du site, Authentification, ajouter une source OAuth2 de type OpenID Connect, puis saisir Client ID, secret et discovery endpoint
  • Grafana : section [auth.generic_oauth] de grafana.ini avec les URL d'autorisation, de jeton et d'informations utilisateur de ZITADEL
  • Nextcloud : application Social Login ou OpenID Connect user backend
  • Toute autre application OIDC : renseignez le discovery endpoint, le Client ID et les Redirect URIs déclarées dans le projet ; consultez la documentation de l'application pour les réglages exacts

Gérer le multi-tenant : organisations et projets

ZITADEL repose sur un modèle multi-tenant natif : vous créez plusieurs Organisations (par exemple une par client de votre SaaS), chacune avec ses utilisateurs et ses politiques de connexion. Chaque organisation peut avoir ses Projets et Rôles.

Attention : les rôles ne sont pas inscrits dans les jetons automatiquement, contrairement à ce qu'affirmait l'ancienne version. Il faut cocher Assert Roles on Authentication dans le projet pour les obtenir via userinfo, ou User Roles Inside ID Token dans l'application, et demander le scope de rôles urn:zitadel:iam:org:project:{projectId}:roles. Ajoutez aussi urn:zitadel:iam:org:project:id:{projectId}:aud si vous obtenez « Invalid audience ».

Conseil : activer les passkeys dès le départ

Dans les paramètres de l'instance, activez l'authentification Passkey/WebAuthn. Vos utilisateurs s'authentifient sans mot de passe depuis leur navigateur.

Découverte de domaine : ce qui doit fonctionner

La découverte de domaine (Domain Discovery) route un utilisateur vers la bonne organisation d'après le domaine de son adresse e-mail. Dans le scénario décrit par l'amont, un utilisateur de [email protected] est redirigé vers le fournisseur d'identité de son entreprise, tandis qu'un utilisateur de [email protected] voit une page de connexion par mot de passe et MFA, et qu'un domaine inconnu tombe dans l'organisation par défaut.

Les conditions décrites dans le guide amont sont les suivantes :

  • Instance — dans Login Behavior and Security, l'option « Domain discovery allowed » est activée
  • Organisation par défaut — elle reçoit tous les utilisateurs sans correspondance
  • Domaine vérifié — chaque domaine est vérifié dans les Organization Domains de l'organisation, par enregistrement DNS TXT ou défi HTTP ; gardez l'enregistrement DNS, car ZITADEL revérifie périodiquement
  • Politique de connexion de l'organisation — « External IDP allowed » activé, et pour une organisation purement fédérée « Username Password allowed » désactivé
  • Fournisseur d'identité — configuré et rattaché à cette organisation ; avec un seul fournisseur la redirection est automatique, avec plusieurs l'utilisateur choisit
  • Connexion par e-mail — le nom de connexion saisi doit pouvoir être une adresse e-mail dont le domaine correspond

Limites connues : le ticket zitadel/zitadel n°10662

Sur ZITADEL v4.1.2 auto-hébergé, la découverte de domaine ne fonctionne pas pour certains déploiements malgré des organisations au domaine vérifié et un fournisseur d'identité configuré. Le ticket n°10662 (« Domain Discovery doesn't work ») a été ouvert en septembre 2025 et est toujours ouvert à la rédaction de cet article. Le tableau sépare ce que l'équipe ou la documentation établit de ce que des utilisateurs rapportent.

Ticket n°10662 : confirmé et rapporté

Faites défiler le tableau

PointConfirmé (équipe ou documentation)Rapporté par des utilisateurs, non confirmé
SymptômeLe ticket est ouvert, classé priorité moyenne en octobre 2026, avec les étiquettes area/console, area/loginV1 et ng-v4-legacyMessage « User not found in the system » pour une adresse au domaine vérifié, sur v4.1.2, identique sous OKD et sous Docker
Correctif annoncéUn mainteneur a indiqué en octobre 2025 que la PR n°10729 le corrigeait, puis le ticket a été rouvertLe défaut persiste sur v4.3.1, puis en Login V1 sur v4.5.0, v4.6.3, v4.7.0 et v4.11.0
CauseAucune cause n'est établie publiquementAucune hypothèse vérifiée
PérimètreDes sous-tickets existent (état du 16 juillet 2026 : un terminé, deux en cours, un non démarré), rattachés au chantier parent n°12337Reproduit en Login V2 (rapport initial) puis en Login V1 ; le cas de plusieurs domaines dans une même organisation reste sans réponse
ConsoleLe 27 juillet 2026, une contributrice indique que la Console doit être dépréciée dans les 12 mois et qu'aucun correctif n'est priorisé d'ici là ; le ticket est maintenu ouvertRien à signaler
ContournementAucun contournement n'est documenté dans le filAucun n'est éprouvé par les participants

En pratique : ne bâtissez pas une architecture SSO d'entreprise sur la seule découverte de domaine tant que ce ticket est ouvert. Prévoyez un second chemin (lien de connexion par fournisseur, voir plus bas) et testez le routage avec un utilisateur réel avant la mise en production. Le 27 octobre 2026, un membre de l'équipe a demandé la vérification de l'état du ticket : suivez-le plutôt que cet article pour son issue.

Dépannage de la connexion SSO et du domaine vérifié

Diagnostic en 5 étapes

  1. Contrôler l'instance

    Dans les paramètres de l'instance, section Login Behavior and Security, vérifiez que « Domain discovery allowed » est bien activé. Sans lui, aucune règle d'organisation n'est consultée.

  2. Contrôler le domaine

    Dans l'organisation visée, ouvrez les Organization Domains : le domaine doit être au statut vérifié. Si la vérification échoue, rétablissez l'enregistrement TXT ou le défi HTTP demandé, et ne supprimez jamais l'enregistrement après coup.

  3. Contrôler la politique de connexion

    Dans la même organisation, « External IDP allowed » doit être activé et le fournisseur d'identité actif. Si « Username Password allowed » reste activé, l'utilisateur peut atterrir sur la saisie du mot de passe au lieu d'être redirigé, symptôme décrit dans le ticket.

  4. Tester le nom de connexion

    En navigation privée, saisissez une adresse complète dont le domaine est exactement celui qui est vérifié. Une faute de domaine, un sous-domaine ou un utilisateur déjà existant dans une autre organisation changent le résultat.

  5. Court-circuiter la découverte

    Si tout est conforme et que « User not found in the system » persiste, vous êtes probablement dans le cas du ticket n°10662. Le scope urn:zitadel:iam:org:idp:id:<idp_id> redirige directement l'utilisateur vers le fournisseur d'identité choisi : la documentation le décrit, mais il n'a pas été éprouvé sur ce défaut.

  • « User not found in the system » : appliquez les cinq étapes ci-dessus ; si elles sont conformes, c'est le défaut du ticket
  • « Instance not found » (404) : le couple hôte, port et protocole reçu ne correspond pas à ZITADEL_EXTERNALDOMAIN, ZITADEL_EXTERNALPORT et ZITADEL_EXTERNALSECURE ; vérifiez que nginx conserve l'en-tête Host
  • Console blanche ou appels API en échec derrière un proxy ou un CDN : contrôlez HTTP/2 de bout en bout
  • Identifiant admin refusé : essayez la forme admin@zitadel.<votre-domaine> indiquée plus haut
  • Vérification de domaine qui échoue : le guide amont précise que le défi ACME de vérification peut être désactivé dans les réglages par défaut, mais ne le faites qu'en connaissance de cause

Mises à jour et sécurité

  • Version courante — à la rédaction, la dernière version stable publiée est la v4.20.0, parue en octobre 2026 ; lisez les notes de version avant chaque montée
  • Avis GHSA-jh92-5mrj-p2w2 — prise de contrôle de compte par des identifiants de session prévisibles dans le Login V2 (sévérité haute, aucun identifiant CVE indiqué). Versions 4.0.0 à 4.19.1 touchées, correctif en 4.19.2 ; un déploiement qui n'utilise que le Login V1 n'est pas concerné
  • Secret de cookie de session — le correctif demande ZITADEL_SESSION_COOKIE_SECRET (32 caractères au moins, identique sur tous les réplicas) ; les utilisateurs doivent se reconnecter après la montée
  • Branche 3.x — elle est arrivée en fin de vie le 31 août 2026 et ne recevra pas de correctif : migrez vers une 4.x récente

Avant de mettre à jour

Sauvegardez la base avec pg_dump et la masterkey, puis lancez docker compose pull suivi de docker compose up -d depuis le dossier du Compose. Comme le template suit le tag stable, vérifiez ensuite la version démarrée avec docker compose images.

Installer ZITADEL via le Marketplace ServOrbit

Vous pouvez installer ZITADEL directement depuis le [Marketplace ServOrbit](/marketplace/security/zitadel) : VPS préconfiguré avec Docker Compose, nginx, HTTPS et secrets générés automatiquement. Le template est fourni comme point de départ, sans prise en charge de votre configuration d'identité.

Déployer ZITADEL sur votre VPS

IAM open source, OIDC/OAuth 2.0, passkeys et multi-tenant natif — pré-configuré avec Docker Compose et HTTPS inclus.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet