Auto-héberger Zitadel sur un VPS avec Docker
Zitadel recommande 4 cœurs et 8 Go de RAM. Configurez PostgreSQL, la masterkey, TLS, SMTP et les sauvegardes, puis anticipez l’effet d’une mise à niveau.
Ce qu’il faut pour auto-héberger Zitadel sur un VPS
Pour auto-héberger Zitadel sur un VPS, vous avez besoin d’un hôte Docker, d’un nom DNS public qui pointe vers celui-ci, de PostgreSQL et d’environ 4 cœurs CPU avec 8 Go de RAM. Zitadel est un fournisseur d’identité. Il émet des tokens via OIDC (OpenID Connect) et SAML (security assertion markup language), afin que vos autres services n’aient plus à gérer leurs propres listes d’utilisateurs. L’installation repose sur un curl et un docker compose up. Les éléments qui déterminent si l’installation restera fonctionnelle sont la masterkey, l’utilisateur de la base de données, SMTP (simple mail transfer protocol), la sauvegarde et la première mise à niveau.
Tout ce qui suit suppose que vous utilisez Ubuntu 24.04, Docker Engine 24 ou une version plus récente avec le plugin Compose, et qu’un nom tel que auth.example.com résout déjà vers le serveur.
De quelles ressources VPS Zitadel a-t-il besoin ?
Le démarrage rapide avec Compose de la documentation de Zitadel demande 2 GB de RAM. Cette valeur correspond à un ordinateur portable. Le guide de mise en production de Zitadel indique d’autres valeurs.
The data behind this chart
[
{
"config": "Process floor, no load",
"cpu_cores": 0.5,
"ram_gb": 0.5
},
{
"config": "Single node, reduced setup",
"cpu_cores": 4,
"ram_gb": 8
},
{
"config": "HA node, logs and metrics on",
"cpu_cores": 4,
"ram_gb": 16
}
]Il s’agit de recommandations publiées, pas de mesures effectuées sur un serveur en fonctionnement. Considérez-les comme une indication de la charge à prévoir. Le processus Zitadel lui-même est peu gourmand : il utilise environ 0.5 GB de RAM au repos. Les cœurs servent au hachage des mots de passe. Cette opération est volontairement lente, donc une vague de connexions entraîne un pic d’utilisation du CPU. PostgreSQL représente l’autre partie des ressources : le même guide prévoit environ un cœur pour 100 requêtes par seconde et 4 GB de RAM par cœur. En combinant les deux, on obtient les 4 cœurs et les 8 GB indiqués par le guide pour un nœud unique, ou 16 GB par nœud une fois la journalisation et les métriques activées.
Un VPS de 2 GB démarrera donc cette stack, mais cette configuration reste inférieure aux recommandations du projet pour une utilisation réelle. L’authentification est le service dont dépendent tous les autres services. Lorsqu’elle est indisponible, aucun service qui lui fait confiance n’autorise les utilisateurs à se connecter. Décider que 8 GB représentent une dépense excessive pour l’authentification est un choix raisonnable. Il coûte bien moins cher de le faire maintenant qu’après une migration. La comparaison de Keycloak, Authentik et Zitadel présente la consommation mémoire et la charge d’exploitation de chacun, et un serveur Authentik auto-hébergé constitue généralement la solution retenue sur un serveur moins puissant.
Récupérez la stack et figez une version
mkdir zitadel-compose && cd zitadel-compose
curl -fsSLO https://raw.githubusercontent.com/zitadel/zitadel/main/deploy/compose/docker-compose.yml
curl -fsSLO https://raw.githubusercontent.com/zitadel/zitadel/main/deploy/compose/.env.example
cp .env.example .env
chmod 600 .envCe fichier définit les quatre services que vous allez réellement exécuter. Traefik est le reverse proxy : il route les requêtes selon le chemin et, avec l’overlay présenté plus loin, assure la terminaison TLS (transport layer security). zitadel-api est le binaire Go qui écoute sur le port 8080. zitadel-login est l’interface de connexion servie à l’adresse /ui/v2/login. postgres contient l’ensemble des éléments. Un cache Redis et un collecteur OpenTelemetry se trouvent dans le même fichier, derrière des profils Compose, et restent désactivés tant que vous ne les activez pas.
N’exécutez pas encore docker compose up. Le premier démarrage crée l’instance, et plusieurs paramètres ci-dessous ne peuvent plus être modifiés ensuite sans opérations supplémentaires.
Le .env que vous avez copié fixe les tags d’image utilisés :
ZITADEL_VERSION=v4.16.0
TRAEFIK_IMAGE=traefik:v3.7.7
POSTGRES_IMAGE=postgres:17.10-alpineLa version v4 actuelle est v4.17.1, publiée le 14 August 2026. Définissez ZITADEL_VERSION sur la version que vous prévoyez d’exécuter et restez sur la branche v4 au lieu de suivre la version la plus récente. Le curl ci-dessus récupère docker-compose.yml depuis la branche main, qui n’est associée à aucun commit fixe. Enregistrez donc une copie des deux fichiers dans un dépôt git. Sinon, la même commande exécutée sur une nouvelle machine le mois prochain produira un fichier différent, sans que vous sachiez ce qui a changé.
Donner à Postgres son propre utilisateur et un vrai mot de passe
Le fichier .env fourni connecte Zitadel à PostgreSQL en tant que superutilisateur, avec le mot de passe postgres :
POSTGRES_ADMIN_USER=postgres
POSTGRES_ADMIN_PASSWORD=postgres
ZITADEL_DATABASE_POSTGRES_DSN=postgresql://postgres:postgres@postgres:5432/zitadel?sslmode=disableCette étape de durcissement comporte un piège. La documentation de Zitadel vous demande d’ajouter POSTGRES_ZITADEL_PASSWORD à .env, mais le fichier docker-compose.yml de base ne lit jamais cette variable. La définir ne change donc rien. Modifier uniquement POSTGRES_ADMIN_PASSWORD interromprait au contraire la connexion, car le mot de passe est également écrit en clair dans la chaîne DSN (data source name). La DSN détermine la manière dont Zitadel se connecte.
Les commentaires de .env.example l’indiquent clairement : lorsqu’une DSN est configurée, Zitadel utilise directement cet utilisateur et n’en crée pas automatiquement un sans privilèges. Le rôle doit donc exister avant le premier démarrage. Générez un mot de passe, démarrez Postgres seul, puis créez le rôle.
tr -dc A-Za-z0-9 </dev/urandom | head -c 32; echo
docker compose --env-file .env -f docker-compose.yml up -d postgres
docker compose --env-file .env -f docker-compose.yml exec -T postgres \
psql -U postgres -d postgres <<'SQL'
CREATE ROLE zitadel LOGIN PASSWORD 'the-password-you-generated';
ALTER DATABASE zitadel OWNER TO zitadel;
SQL
docker compose --env-file .env -f docker-compose.yml exec -T postgres \
psql -U postgres -d zitadel -c 'ALTER SCHEMA public OWNER TO zitadel;'Les commandes psql s’exécutent dans le conteneur via son socket local, auquel l’image officielle Postgres fait confiance. Elles ne demandent donc pas de mot de passe. C’est la propriété qui compte ici. Avec PostgreSQL 15 et les versions ultérieures, un simple GRANT ALL PRIVILEGES ON DATABASE ne permet plus à un rôle de créer des tables dans le schéma public. La phase de configuration de Zitadel échoue alors avec une erreur de permissions lors de la création de ses schémas. Faire du rôle le propriétaire de la base de données et du schéma évite ce problème.
Modifiez maintenant la DSN pour utiliser le nouveau rôle, puis définissez un vrai mot de passe administrateur dans le fichier :
POSTGRES_ADMIN_PASSWORD=a-32-character-random-string
ZITADEL_DATABASE_POSTGRES_DSN=postgresql://zitadel:the-password-you-generated@postgres:5432/zitadel?sslmode=disablesslmode=disable convient ici, car Postgres est uniquement accessible sur le réseau Compose privé et son port n’est jamais publié sur l’hôte. Après le premier démarrage complet, vérifiez que le rôle possède bien ses données :
docker compose exec -T postgres psql -U zitadel -d zitadel -c '\dn'La commande doit afficher un schéma eventstore et un schéma projections. Une liste vide signifie que la phase de configuration n’est pas allée jusque-là. Le journal du conteneur API indiquera pourquoi.
La masterkey et le coût de sa perte
Zitadel chiffre les secrets avant de les stocker : secrets client, identifiants des fournisseurs d’identité, mot de passe SMTP, seeds de mots de passe à usage unique et clés de machine. La masterkey déverrouille toutes ces données. Elle comporte exactement 32 caractères. La documentation est claire sur la conséquence : il est impossible de la modifier sans perdre l’accès aux données chiffrées.
Générez-en une et remplacez la ligne d’exemple dans .env :
tr -dc A-Za-z0-9 </dev/urandom | head -c 32; echoModifiez la ligne ZITADEL_MASTERKEY=MasterkeyNeedsToHave32Characters au lieu d’en ajouter une deuxième. Compose utilise la dernière définition d’une clé répétée. L’ajout fonctionne donc, mais un fichier contenant deux lignes masterkey risque d’induire en erreur la prochaine personne qui le consultera.
Réfléchissez maintenant à l’emplacement de cette clé. Le fichier Compose démarre le conteneur API comme ceci :
command: start-from-init --masterkey "${ZITADEL_MASTERKEY}"La masterkey se trouve donc dans la ligne de commande du conteneur. docker inspect l’affiche à toute personne pouvant accéder au socket Docker. Sur un VPS administré par une seule personne, ce compromis est acceptable. Le mode défini sur .env protège la clé sur le disque. Si ce compromis n’est pas acceptable, montez la clé en tant que fichier et utilisez plutôt --masterkeyFile /run/secrets/zitadel-masterkey. Sa valeur ne figurera ainsi pas dans les arguments du processus.
Copiez la masterkey dans votre gestionnaire de mots de passe avant le premier démarrage. Elle n’apparaît pas dans un dump de base de données. Un dump restauré avec une autre masterkey produit donc une instance incapable de lire ses propres secrets. Conservez-la ailleurs que dans l’archive contenant le dump. Ainsi, une seule sauvegarde volée ne contiendra pas à la fois les données chiffrées et la clé permettant de les déchiffrer.
Définir le domaine externe avant le premier démarrage
ZITADEL_DOMAIN dans .env alimente ZITADEL_EXTERNALDOMAIN dans le conteneur. C’est le nom que vos utilisateurs saisissent. Zitadel en déduit l’émetteur OIDC, l’URI de base de l’interface de connexion, les endpoints SAML et l’identifiant de connexion du premier administrateur. Ce paramètre n’est donc pas purement décoratif.
ZITADEL_DOMAIN=auth.example.com
ZITADEL_EXTERNALPORT=443
ZITADEL_EXTERNALSECURE=trueZitadel détermine l’instance à laquelle vous vous connectez à partir de l’en-tête Host. Si cet en-tête ne correspond pas à un domaine connu, toutes les requêtes renvoient la même réponse :
ID=QUERY-1kIjX Message=Instance not foundC’est l’erreur la plus fréquente avec Zitadel auto-hébergé. Elle signifie presque toujours l’une de ces deux choses. Soit ZITADEL_DOMAIN n’est pas le nom que vous utilisez dans votre navigateur, soit un proxy en amont réécrit Host avec l’adresse du serveur upstream. Elle apparaît également si vous utilisez l’adresse IP du serveur au lieu du nom de domaine.
Vous pouvez modifier ces valeurs ultérieurement. Zitadel doit relancer sa phase de configuration pour prendre la modification en compte, et chaque application déjà enregistrée conserve ses anciennes URI de redirection. Choisir le nom définitif dès maintenant coûte beaucoup moins cher que de le changer plus tard.
Terminaison TLS avec l’overlay Let's Encrypt
Pour un domaine public, ajoutez l’overlay Let's Encrypt de Zitadel. Il configure Traefik pour utiliser le challenge HTTP d’ACME (automatic certificate management environment) et remplace les ports publiés par 80 et 443. Aucun autre service sur le serveur ne doit donc utiliser l’un de ces ports.
curl -fsSLO https://raw.githubusercontent.com/zitadel/zitadel/main/deploy/compose/docker-compose.mode-letsencrypt.yml
echo 'LETSENCRYPT_EMAIL=ops@example.com' >> .envL’overlay définit également ZITADEL_EXTERNALPORT: 443 et ZITADEL_EXTERNALSECURE: true sur le conteneur API. C’est pourquoi l’URL publique et les URL que Zitadel génère pour lui-même correspondent. L’enregistrement A doit résoudre le domaine avant le démarrage, car le challenge HTTP échoue sans cet enregistrement.
Si vous terminez déjà le TLS sur nginx ou sur un load balancer, utilisez plutôt docker-compose.mode-external-tls.yml et définissez TRAEFIK_TRUSTED_IPS avec les plages d’adresses utilisées par votre proxy. Traefik ne prend en compte les en-têtes X-Forwarded-* que lorsqu’ils proviennent d’adresses présentes dans cette liste. Une valeur incorrecte entraîne donc l’abandon du protocole transmis, et Zitadel commence à générer des URL http:// pour un site HTTPS.
Un proxy en amont doit respecter deux exigences auxquelles Zitadel est strict. Il doit utiliser HTTP/2 pour communiquer avec le backend, car l’API utilise gRPC. Il doit également transmettre Host sans modification, ainsi que X-Forwarded-Proto: https. L’exemple nginx fourni par Zitadel montre la structure à utiliser :
server {
listen 443 ssl;
http2 on;
ssl_certificate /etc/certs/selfsigned.crt;
ssl_certificate_key /etc/certs/selfsigned.key;
location /ui/v2/login {
proxy_pass http://login-external-tls:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
}
location / {
grpc_pass grpc://zitadel-external-tls:8080;
grpc_set_header Host $host;
grpc_set_header X-Forwarded-Proto https;
}
}Les noms upstream utilisés ici correspondent aux conteneurs de l’environnement de test de Zitadel. Remplacez-les donc par les vôtres. Si vous servez Zitadel sur un port différent de 443, utilisez grpc_set_header Host $host:$server_port; afin que le port soit transmis avec l’en-tête. Le reste correspond à un virtual host classique. La lecture ligne par ligne d’une configuration de reverse proxy nginx présente les éléments qui ne sont pas spécifiques à Zitadel.
Le premier compte d’administration et le changement obligatoire du mot de passe
Le premier démarrage crée une instance, une organisation et un compte d’administration humain. Le nom de connexion est composé de zitadel-admin@, de zitadel. et de votre domaine externe. Avec ZITADEL_DOMAIN=auth.example.com, il est donc le suivant :
zitadel-admin@zitadel.auth.example.comLe mot de passe est Password1!, sauf si vous définissez le vôtre. La valeur par défaut fournie par Zitadel impose normalement un changement lors de la première connexion, mais le fichier compose fourni remplace cette valeur :
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORDCHANGEREQUIRED: falseCette ligne est codée en dur dans docker-compose.yml au lieu d’être lue depuis .env. Placez donc vos propres valeurs dans un petit fichier d’overlay. Appelez-le docker-compose.local.yml :
services:
zitadel-api:
environment:
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_EMAIL_ADDRESS: you@example.com
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD: "a-long-temporary-password"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORDCHANGEREQUIRED: "true"Compose charge automatiquement docker-compose.override.yml uniquement lorsque vous l’exécutez sans l’option -f. Or toutes les commandes du guide Zitadel utilisent -f, ce qui désactive ce comportement. Plutôt que de répéter une liste d’options qui s’allonge, définissez la liste des fichiers dans .env :
COMPOSE_FILE=docker-compose.yml:docker-compose.mode-letsencrypt.yml:docker-compose.local.ymlDémarrez maintenant le service :
docker compose pull
docker compose up -d --wait--wait maintient la commande jusqu’à ce que les healthchecks réussissent. Si le conteneur d’API n’atteint jamais cet état, Compose s’arrête avec dependency failed to start: container zitadel-compose-zitadel-api-1 is unhealthy, et docker compose logs zitadel-api en indique la cause. Lors d’un premier démarrage, la cause est généralement la longueur de la masterkey ou le DSN de la base de données.
Connectez-vous à https://auth.example.com/ui/console, changez le mot de passe, puis activez un second facteur pour ce compte avant de créer quoi que ce soit d’autre. Chaque valeur ZITADEL_FIRSTINSTANCE_* s’applique uniquement pendant la création de la première instance. Une fois l’instance créée, leur modification n’a plus aucun effet.
Pourquoi la réinitialisation du mot de passe ne fait rien tant que SMTP ne fonctionne pas
Un fournisseur d’identité qui ne peut pas envoyer d’e-mails est défaillant d’une manière qui peut rester invisible pendant des semaines. Zitadel envoie des e-mails pour les invitations d’utilisateurs, la vérification des adresses, les liens de réinitialisation du mot de passe, les codes à usage unique et les notifications de revendication de domaine. Si aucun fournisseur SMTP n’est configuré, la Console indique quand même que l’action est terminée, puis le message est transmis à un worker de notification qui n’a aucun serveur vers lequel l’envoyer. Les valeurs par défaut donnent à ce worker MaxAttempts: 3 et MaxTtl: 5m : il réessaie quelques fois pendant quelques minutes, puis s’arrête. La personne qui attend le lien n’en est pas informée.
Configurez-le dans la Console, dans les paramètres de l’instance, à l’emplacement https://auth.example.com/ui/console/settings. Le formulaire du fournisseur SMTP demande une adresse e-mail d’expéditeur, un nom d’expéditeur, l’hôte et le port, un utilisateur, un mot de passe SMTP et une option TLS. Utilisez le bouton de test de ce formulaire avant d’enregistrer, car il envoie un véritable message : celui-ci arrive ou n’arrive pas.
Un ensemble correspondant de variables d’environnement existe, ZITADEL_DEFAULTINSTANCE_SMTPCONFIGURATION_SMTP_HOST et ses variables associées. Elles s’appliquent lors de la création d’une instance. Sur une stack déjà en cours d’exécution, elles n’ont aucun effet. Pour une instance existante, utilisez donc la Console.
Deux points concernant l’envoi depuis un VPS, car c’est généralement là que le problème se produit. La plupart des fournisseurs bloquent le port sortant 25 sur les nouveaux comptes. Un envoi direct vers le serveur de messagerie du destinataire expire alors sans message d’erreur utile. Utilisez plutôt un relay authentifié sur le port 587. Publiez également des enregistrements SPF (sender policy framework) et DKIM (domainkeys identified mail) pour le domaine d’envoi. Sinon, le lien de réinitialisation arrive dans les spams, ce qui ressemble exactement, pour l’utilisateur, à un e-mail qui n’a jamais été envoyé.
Vérifiez le fonctionnement avant d’inviter qui que ce soit. Créez un utilisateur temporaire, demandez une réinitialisation du mot de passe et vérifiez que le message arrive. Si ce n’est pas le cas, docker compose logs -f zitadel-api indique l’échec SMTP. Le mot de passe SMTP est stocké chiffré dans la base de données. C’est une donnée supplémentaire que la masterkey protège pour vous.
Sauvegarder Postgres et la masterkey séparément
Tout ce que Zitadel connaît se trouve dans PostgreSQL. La masterkey permet de le déchiffrer. Sauvegardez ces deux éléments dans deux emplacements différents.
Commencez par créer le dump :
sudo install -d -m 700 /srv/zitadel-backups
docker compose exec -T postgres \
pg_dump -U postgres -Fc zitadel > "/srv/zitadel-backups/zitadel-$(date +%F).dump"-Fc correspond au format personnalisé. Il compresse les données à la création du dump, et pg_restore peut ensuite les lire de manière sélective. exec -T désactive le terminal. C’est nécessaire, car cette commande est exécutée par cron sans terminal associé.
Envoyez ensuite ce répertoire hors site avec restic, qui chiffre et déduplique les données :
export RESTIC_REPOSITORY="sftp:backup@backup.example.com:/srv/restic/zitadel"
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic init
restic backup /srv/zitadel-backups
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prunerestic init s’exécute une seule fois, le premier jour. Ajoutez le dump et les deux dernières commandes dans /usr/local/bin/zitadel-backup.sh, puis exécutez ce script chaque nuit :
0 3 * * * /usr/local/bin/zitadel-backup.shSauvegardez .env ainsi que tous les fichiers Compose que vous utilisez dans git. La masterkey fait exception à toutes ces règles. Stockez-la dans votre gestionnaire de mots de passe et dans un deuxième emplacement qui n’est pas ce repository restic. Une archive contenant à la fois la base de données et sa clé de déchiffrement ne constitue plus une sauvegarde d’un système chiffré.
Une sauvegarde que vous n’avez jamais restaurée reste une hypothèse. Restaurez-la dans une base de données temporaire sur le même serveur et vérifiez son contenu :
docker compose exec -T postgres createdb -U postgres zitadel_restore_test
docker compose exec -T postgres pg_restore -U postgres -d zitadel_restore_test \
< /srv/zitadel-backups/zitadel-2026-08-21.dump
docker compose exec -T postgres psql -U postgres -d zitadel_restore_test -c '\dt eventstore.*'
docker compose exec -T postgres dropdb -U postgres zitadel_restore_testLa présence d’une liste de tables dans le schéma eventstore signifie que le dump est valide. Si une erreur indique que le schéma n’existe pas, le dump ne l’est pas. Vous l’aurez découvert un jour où cela ne vous coûte rien. Le principe général pour sauvegarder et mettre à niveau une stack Compose s’applique ici presque sans modification. Garder la masterkey en dehors de la même archive est le seul aspect spécifique à Zitadel.
Mettre à niveau Zitadel sans perdre l’instance
Une mise à niveau consiste à changer la version dans .env, puis à exécuter deux commandes :
docker compose pull
docker compose up -d --waitComprenez ce que fait la seconde commande avant de l’exécuter sur une instance utilisée par des personnes pour se connecter. La commande du conteneur est start-from-init. Elle exécute les phases init et setup avant de commencer à traiter les requêtes. La phase setup correspond aux migrations de la base de données. Ainsi, un changement de version exécute automatiquement les migrations du schéma sur votre base de données en production au démarrage du conteneur, sans intervention, tandis que --wait attend qu’un healthcheck soit valide. C’est précisément pourquoi le test de restauration décrit plus haut n’est pas facultatif.
Effectuez un dump récent immédiatement avant la mise à niveau. Le dump de la nuit dernière ne convient pas.
Ne sautez pas une version majeure. Pour passer de v3 à v4, vous devez d’abord utiliser v3.4.1 ou une version ultérieure. v4 a supprimé les clés de signature OIDC historiques. Les tokens signés avec ces anciennes clés cessent donc d’être vérifiés dès que vous passez à v4. L’avis technique A-10017 de Zitadel décrit ce changement. La correction consiste à conserver la nouvelle v3 assez longtemps pour que les anciens tokens expirent avant la mise à niveau.
Surveillez la phase setup avec docker compose logs -f zitadel-api. Les migrations d’un eventstore volumineux peuvent prendre plusieurs minutes. Traefik n’achemine pas les requêtes vers l’API tant que son healthcheck n’est pas valide. Le site est donc indisponible pendant cette période. Planifiez cette interruption au lieu de la découvrir au moment de la mise à niveau.
Un rollback ne consiste pas à remettre l’ancien tag. Une fois les migrations exécutées, l’ancien binaire ne comprend plus le schéma qu’il trouve. Revenir en arrière signifie donc restaurer le dump. Dès que l’instance contient de vrais utilisateurs, passez à docker-compose.prodlike.yml. Cet overlay exécute init et setup comme des étapes distinctes de start. Vous pouvez ainsi déclencher et surveiller une migration, au lieu de la subir comme un effet secondaire du redémarrage d’un conteneur.
Vers quel endpoint pointer votre nouveau fournisseur d’identité
Dans la Console, créez un projet, puis une application à l’intérieur de celui-ci. Choisissez OIDC pour toute application moderne. Zitadel vous fournit un client ID, un client secret et un document de découverte à l’adresse https://auth.example.com/.well-known/openid-configuration. La plupart des logiciels auto-hébergés qui prennent en charge le single sign-on attendent exactement ces éléments.
De nombreux logiciels ne prennent pas en charge cette fonctionnalité, ou la réservent à une offre payante. Dans le premier cas, placez oauth2-proxy devant l’application pour permettre à Zitadel de protéger n’importe quel service HTTP. Dans le second, la taxe SSO des applications auto-hébergées mérite d’être lue avant de planifier une migration autour d’une fonctionnalité que vous n’avez pas payée.
FAQ
De combien de RAM et de CPU Zitadel a-t-il besoin en auto-hébergement ?
Le guide de production de Zitadel recommande environ 4 cœurs CPU et 8 Go de RAM pour un nœud unique avec une configuration réduite, et 16 Go par nœud lorsque la journalisation et les métriques sont activées. PostgreSQL est dimensionné séparément, à raison d’environ un cœur pour 100 requêtes par seconde et de 4 Go de RAM par cœur. Le quickstart Compose démarre avec moins de 2 Go, ce qui suffit pour l’essayer, mais reste inférieur aux recommandations du projet pour un système dont dépendent d’autres services.
Que se passe-t-il si je perds la masterkey de Zitadel ?
Toutes les données qu’elle chiffre restent chiffrées. Les secrets client, les identifiants des fournisseurs d’identité, le mot de passe SMTP et les seeds des mots de passe à usage unique ne peuvent pas être déchiffrés, et la clé ne peut pas être remplacée a posteriori. Un dump de la base de données ne suffit pas à restaurer une instance fonctionnelle, car il contient le texte chiffré, mais pas la clé. Stockez la masterkey dans un gestionnaire de mots de passe, à un emplacement distinct de la sauvegarde qui contient le dump. Si les deux sont perdus, il ne reste qu’à reconstruire l’instance depuis zéro.
Pourquoi les e-mails de réinitialisation du mot de passe Zitadel n’arrivent-ils jamais ?
Parce qu’aucun fournisseur SMTP n’est configuré, ou parce que celui qui est configuré ne peut pas distribuer les messages. Zitadel place chaque notification dans la file d’un worker et effectue trois tentatives par défaut. Dans les deux cas, la Console indique que l’opération a réussi, ce qui rend l’échec silencieux. Configurez le fournisseur SMTP dans les paramètres de l’instance et utilisez le bouton de test de ce formulaire. Il envoie un véritable message. Depuis un VPS, utilisez un relay authentifié sur le port 587, car la plupart des fournisseurs bloquent le port sortant 25. Publiez également les enregistrements SPF et DKIM du domaine d’envoi afin que les messages ne soient pas filtrés comme spam.
Puis-je modifier le domaine externe de Zitadel après l’installation ?
Oui, mais pas en modifiant uniquement .env. Modifiez ZITADEL_EXTERNALDOMAIN, ZITADEL_EXTERNALPORT et ZITADEL_EXTERNALSECURE, puis laissez Zitadel réexécuter sa phase de configuration pour prendre ce changement en compte. Les applications déjà enregistrées conservent leurs anciennes URI de redirection et doivent être mises à jour manuellement. Toute requête dont l’en-tête Host ne correspond pas à un domaine connu de Zitadel reçoit Instance not found. Choisir le nom définitif avant le premier démarrage évite tous ces problèmes.