Cybersécurité

Installer Zitadel sur Coolify : tutoriel 2026

11 min de lecture

Tutoriel pour déployer Zitadel via Coolify en 2026 (informations vérifiées en avril 2026, susceptibles d’évoluer).

Voir notre guide Zitadel.

Prérequis

  • Coolify v4 fonctionnel
  • VPS 4 Go RAM minimum (Zitadel + CockroachDB embedded)
  • Domaine (ex: auth.exemple.sn)
  • 30 minutes

Étape 1 — Service Docker Compose

services:
  zitadel:
    image: ghcr.io/zitadel/zitadel:latest
    command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled'
    environment:
      ZITADEL_DATABASE_POSTGRES_HOST: db
      ZITADEL_DATABASE_POSTGRES_PORT: 5432
      ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
      ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel
      ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: zitadel
      ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
      ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
      ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres
      ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
      ZITADEL_EXTERNALSECURE: 'true'
      ZITADEL_EXTERNALDOMAIN: auth.exemple.sn
      ZITADEL_EXTERNALPORT: 443
      ZITADEL_TLS_ENABLED: 'false'
    depends_on:
      - db
    labels:
      - "coolify.expose=true"
      - "coolify.domain=https://auth.exemple.sn"

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: zitadel
    volumes:
      - zitadel-db:/var/lib/postgresql/data

volumes:
  zitadel-db:

Étape 2 — Premier accès

  1. Logs container Zitadel : récupérer les credentials initial admin
  2. Ouvrir https://auth.exemple.sn/ui/console
  3. Login avec zitadel-admin@zitadel.localhost et le mot de passe des logs
  4. Changer immédiatement le mot de passe
  5. Activer 2FA / passkey sur ce compte

Étape 3 — Custom domain et email

  • Settings → Domains : ajouter votre domaine custom
  • Settings → SMTP Settings : Brevo ou autre pour les emails de vérification
  • Configurer logo et thème de votre organisation

Étape 4 — Reverse proxy

Coolify configure auto Traefik. Vérifier que le proxy gère bien gRPC (Zitadel utilise HTTP/2 et gRPC pour son admin console).

Pour creuser ce sujet

Hostinger pour vos premiers déploiements

Le panel hPanel reste l’un des plus accessibles du marché pour les débutants en self-hosting.

Découvrir hPanel →

Lien d affiliation. Si vous achetez via ce lien, le blog reçoit une petite commission sans surcoût pour vous.

Etape 1 : Pourquoi Zitadel et pourquoi Coolify

Zitadel est une plateforme d’identite open source ecrite en Go, alternative serieuse a Keycloak avec une interface plus moderne et une consommation memoire reduite (300 a 500 Mo en charge moyenne contre 1 Go pour Keycloak). En 2026, la version stable Zitadel est la 2.66, distribuee comme image Docker officielle ghcr.io/zitadel/zitadel.

Coolify est une plateforme self-hosted type Heroku qui simplifie le deploiement Docker via interface web. La version 4 (sortie courant 2024) gere natilvement Postgres comme service partage et des reverse proxy avec TLS automatique via Traefik. Combine, Zitadel sur Coolify donne un SSO d’entreprise deployable en 30 minutes par un developpeur a Dakar, Cotonou ou Douala — sans connaissance Kubernetes.

Etape 2 : Provisionner le serveur Coolify

Coolify a besoin d’un VPS Ubuntu 24.04 avec au moins 4 Go de RAM et 40 Go de disque. Pour heberger Coolify + Zitadel + 2 ou 3 autres applications, comptez 8 Go de RAM. Hetzner CX32 (8,40 EUR par mois soit environ 5500 FCFA) ou Contabo Cloud VPS S sont les choix economiques en 2026.

curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash

Le script installe Docker, le reseau Traefik et Coolify lui-meme en 5 a 10 minutes. A la fin, il affiche l’URL de premier acces au format http://IP:8000 et le token initial. Connectez-vous, creez le compte admin, puis configurez votre domaine principal dans Settings.

Etape 3 : Configurer le DNS du sous-domaine Zitadel

Avant de deployer Zitadel, creez un enregistrement DNS A qui pointe auth.exemple.sn vers l’IP publique du serveur Coolify. Si votre registrar est Namecheap, OVH ou un registrar local senegalais, le TTL par defaut de 3600 secondes est acceptable — diminuez a 300 si vous testez et changez de cible souvent.

auth.exemple.sn.  3600  IN  A  203.0.113.42

Verifiez la propagation avec dig auth.exemple.sn +short. Tant que la commande ne retourne pas la bonne IP, n’allez pas plus loin — Traefik echouera a obtenir le certificat Let’s Encrypt si le DNS ne resout pas correctement, et vous perdrez 30 minutes a chercher l’erreur ailleurs.

Etape 4 : Creer la base Postgres dediee dans Coolify

Zitadel necessite Postgres 17 ou superieur (depuis la version 2.62). Dans Coolify, allez dans Resources puis New Resource puis Database puis PostgreSQL et choisissez la version 17. Donnez un nom comme « zitadel-db », laissez Coolify generer le mot de passe.

Notez le password genere — vous l’utiliserez dans la configuration Zitadel a l’etape suivante. Coolify expose la base sur le reseau Docker interne uniquement par defaut, ce qui est la bonne pratique. Aucun port n’est ouvert sur internet, seul Zitadel pourra s’y connecter via le hostname interne genere par Coolify.

Etape 5 : Deployer Zitadel via Docker Compose dans Coolify

Dans Coolify, creez un nouveau service « Zitadel » en mode Docker Compose. Collez la configuration ci-dessous, en adaptant les variables ZITADEL_DATABASE_POSTGRES_* aux credentials de la base creee a l’etape 4.

services:
  zitadel:
    image: ghcr.io/zitadel/zitadel:v2.66.0
    command: 'start-from-init --masterkey "MasterKeyNeedsToHave32Characters" --tlsMode external'
    environment:
      ZITADEL_DATABASE_POSTGRES_HOST: zitadel-db
      ZITADEL_DATABASE_POSTGRES_PORT: 5432
      ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
      ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel
      ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: CHANGE_ME
      ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
      ZITADEL_EXTERNALDOMAIN: auth.exemple.sn
      ZITADEL_EXTERNALPORT: 443
      ZITADEL_EXTERNALSECURE: true
    labels:
      - traefik.enable=true
      - traefik.http.routers.zitadel.rule=Host(`auth.exemple.sn`)
      - traefik.http.routers.zitadel.tls.certresolver=letsencrypt

Generez la masterkey via openssl rand -hex 16 — exactement 32 caracteres. Cette cle chiffre les secrets en base, sa perte rend les donnees illisibles. Sauvegardez-la dans un gestionnaire de secrets immediatement.

Etape 6 : Lancer le deploiement et surveiller les logs

Cliquez Deploy dans Coolify. Le premier demarrage prend 60 a 120 secondes : Zitadel cree son schema dans Postgres, genere les cles internes, lance le serveur. Surveillez les logs en temps reel via l’onglet Logs de Coolify.

Vous devez voir une ligne « server is listening on » suivie du port. Si vous voyez « database connection failed », vos credentials Postgres sont mauvais. Si vous voyez « TLS handshake error », le DNS ne propage pas encore ou Traefik n’a pas encore obtenu le certificat — attendez 2 minutes et rafraichissez https://auth.exemple.sn.

Etape 7 : Premier acces et creation de l’organisation

Ouvrez https://auth.exemple.sn dans le navigateur. Vous arrivez sur la page de login Zitadel. Le premier admin est cree automatiquement avec l’email zitadel-admin@zitadel.auth.exemple.sn et un mot de passe initial visible dans les logs au premier demarrage (cherchez « initial password »).

Connectez-vous, changez immediatement le mot de passe pour quelque chose de fort (16+ caracteres), activez la 2FA via TOTP avec une app comme Aegis ou Bitwarden, puis renommez l’organisation par defaut au nom de votre entreprise.

Etape 8 : Creer un projet et son client OIDC

Dans la console Zitadel, allez dans Projects puis Create new project. Donnez un nom (par exemple « Application Web Interne »). Cliquez sur le projet, puis Applications puis Create new application, type Web. Choisissez le flux Authorization Code avec PKCE — le standard moderne.

Configurez les redirect URIs vers votre application : par exemple https://app.exemple.sn/auth/callback. Activez « Development Mode » pendant la phase de test pour autoriser http://localhost dans les redirects, mais desactivez-le en production sous peine d’attaque par redirection ouverte.

Etape 9 : Integrer Zitadel dans une application Node Express

Dans votre application Express, installez openid-client. Le code minimal pour rediriger vers Zitadel et recevoir le callback tient en 30 lignes, et le pattern PKCE protege contre les attaques d’interception du code.

import { Issuer, generators } from 'openid-client';
const issuer = await Issuer.discover('https://auth.exemple.sn');
const client = new issuer.Client({
  client_id: 'CLIENT_ID_ZITADEL',
  redirect_uris: ['https://app.exemple.sn/auth/callback'],
  response_types: ['code'],
});

Pour le callback, verifiez le state, echangez le code contre un id_token, validez la signature et stockez l’utilisateur en session. Ne stockez JAMAIS l’access_token en localStorage cote front — utilisez un cookie HTTPOnly avec SameSite=Lax.

Etape 10 : Activer la connexion via Google ou Microsoft

Pour permettre aux utilisateurs de se connecter avec leur compte Google Workspace ou Microsoft 365, ajoutez un Identity Provider externe dans Zitadel. Allez dans Identity Providers puis Create. Pour Google, vous devez creer un projet sur Google Cloud Console et obtenir un Client ID + Client Secret OAuth 2.0.

Configurez le redirect URI cote Google : https://auth.exemple.sn/ui/login/login/externalidp/callback. Une fois sauvegarde, le bouton « Continuer avec Google » apparait sur la page de login Zitadel. C’est particulierement apprecie par les PME au Senegal et en Cote d’Ivoire qui utilisent deja Google Workspace pour leur messagerie. Voyez aussi notre tutoriel NocoDB pour ajouter Zitadel comme couche SSO devant et notre guide Grafana Discord pour superviser le tout.

Etape 11 : Mettre en place les politiques de mot de passe

Par defaut, Zitadel accepte des mots de passe trop courts. Dans Settings de votre organisation, ouvrez Login Policy et durcissez : longueur minimale 12 caracteres, exiger maj+min+chiffre+special, lockout apres 5 tentatives, force du renouvellement tous les 180 jours pour les comptes admin uniquement (pas pour les utilisateurs finaux — la rotation forcee genere des mots de passe plus faibles).

Activez aussi la verification email obligatoire — les comptes non verifies ne peuvent pas se connecter. Et le check des mots de passe contre la base Have I Been Pwned via l’option Password Compromise Check, qui rejette les mots de passe deja exposes dans des leaks publics.

Etape 12 : Imposer la 2FA pour les administrateurs

La 2FA n’est pas optionnelle pour les comptes a privileges. Dans Login Policy, activez « Force MFA » pour le role IAM_OWNER et IAM_ORG_OWNER. Les admins devront configurer une cle de securite FIDO2 (YubiKey, Titan, ou Passkey iOS/Android) ou TOTP au prochain login.

# Force MFA via API
curl -X PUT https://auth.exemple.sn/admin/v1/policies/login \
  -H "Authorization: Bearer $PAT" \
  -d '{"forceMfa": true, "secondFactors": ["SECOND_FACTOR_TYPE_OTP", "SECOND_FACTOR_TYPE_U2F"]}'

Les utilisateurs finaux peuvent rester sur 2FA optionnelle au depart — la rendre obligatoire d’un coup pour 200 personnes provoque une vague de tickets support. Procedez par etapes : email d’annonce, fenetre de 30 jours pour configurer, puis activation forcee.

Etape 13 : Sauvegarder Zitadel

La base Postgres de Zitadel contient l’identite de tous vos utilisateurs. Sa perte est catastrophique — chaque utilisateur devra se reinscrire et reconfigurer 2FA. Mettez en place un dump quotidien automatise avec retention 30 jours, chiffre avec age, push sur S3 ou Backblaze B2.

0 3 * * * docker exec coolify-zitadel-db pg_dump -U zitadel zitadel \
  | age -r age1abc... > /backup/zitadel-$(date +\%F).sql.age

Sauvegardez aussi la masterkey separement, dans un gestionnaire type 1Password ou Bitwarden — sans elle, le dump Postgres restaure ne pourra pas dechiffrer les secrets stockes (cles privees OIDC, cles API). Testez la procedure de restauration complete une fois par trimestre sur un VPS de staging.

Etape 14 : Mettre a jour Zitadel sans interruption

Zitadel publie une release mineure environ toutes les 4 semaines. Avant chaque mise a jour, lisez les release notes a la recherche d’une « breaking change » — il y en a parfois sur des changements de schema Postgres qui necessitent une fenetre de maintenance. Mettez a jour la version dans la config Coolify, sauvegardez, puis redeployez.

# 1) backup
docker exec coolify-zitadel-db pg_dump ... > pre-upgrade.sql
# 2) edit image: ghcr.io/zitadel/zitadel:v2.67.0
# 3) Coolify Redeploy

Zitadel applique automatiquement les migrations au demarrage. Surveillez les logs pendant 2 a 3 minutes — la duree de migration depend du nombre d’utilisateurs et d’evenements en base. Pour 1000 utilisateurs et 50000 evenements, comptez 30 secondes. Si vous voyez « migration failed », restaurez le backup et ouvrez un issue sur GitHub Zitadel.

Etape 15 : Surveiller les logs d’audit

Zitadel ecrit un evenement pour chaque action significative : login reussi, login echoue, changement de mot de passe, creation d’utilisateur. Ces evenements sont accessibles via l’API et stockes dans la table events de Postgres. Streamez-les vers Loki pour les analyser dans Grafana.

SELECT created_at, event_type, editor_user, payload
FROM eventstore.events
WHERE created_at > now() - interval '1 hour'
ORDER BY created_at DESC LIMIT 100;

Configurez une alerte Grafana qui fire si plus de 50 logins echoues sur 5 minutes — c’est typiquement le signe d’une attaque par brute force qui necessite une investigation immediate. Bloquez l’IP via fail2ban ou la WAF en amont si l’attaque persiste.

Etape 16 : Migrer depuis un Keycloak existant

Si vous remplacez un Keycloak par Zitadel, migrez les utilisateurs via export JSON puis import API. Keycloak permet d’exporter realm + utilisateurs via kcadm.sh export. Cote Zitadel, l’API admin importe par batch de 1000 utilisateurs avec l’endpoint /admin/v1/users/_import. Comptez 1 a 2 minutes par tranche de 1000.

kcadm.sh get users -r my-realm > users.json
# transformer puis POST vers Zitadel /v1/users/_import

Les mots de passe Keycloak (hashes PBKDF2) ne peuvent pas etre directement importes dans Zitadel qui utilise bcrypt — les utilisateurs devront definir un nouveau mot de passe au premier login. Communiquez clairement par email avant la migration pour eviter une vague de tickets support le jour J.

Etape 17 : Documenter pour l’equipe et les auditeurs

Au-dela du code et de la config, documentez : la procedure de creation d’utilisateur, la procedure de revocation, la matrice des roles et permissions, le processus de revue trimestrielle des comptes inactifs. Ces documents sont attendus lors de tout audit ISO 27001, SOC 2, ou audit BCEAO pour les fintechs ouest-africaines. Sans documentation, le meilleur Zitadel du monde echouera l’audit. Avec une documentation a jour de 5 a 10 pages stockee dans le repo infra a cote du docker-compose.yml, l’auditeur valide en 30 minutes au lieu d’imposer un plan d’action correctif de 3 mois.

Partager