Déploiement de Zitadel sur Linux

Logo Zitadel
Source: dépôt Github de Zitadel

J'étais à la recherche d'un SSO assez complet quand je suis tombé sur Zitadel, j'ai donc eu envie de tenter l'expérience.
Je ne suis pas doué pour les présentations donc pour faire court c'est un service d'IAM (Identity and Access Management) qui a à première vue toutes les fonctionnalité qu'on pourrait attendre d'un SSO mais en mettant l'accent sur la partie IAM et multi-tenant. De plus comme la majorité des solutions que j'utilise il est open-source.

Malheureusement après quelques recherches on voit que son déploiement n'est pas très documenté sur machine Linux pour une utilisation supérieur à du simple test mais ne nécessitant pas un cluster pour la gestion de millions d'utilisateurs.


Passons à la partie amusante en voyant comment déployer cette solution sur une machine Linux.

Pour cette article j'utilise une VM Ubuntu 22.04 avec 4vCPU, 8Go de RAM et 80 Go de disque avec un utilisateur qui a toutes les permissions avec sudo.

Nous aurons besoin de mettre en place une base de données PostgreSQL puis un reverse-proxy pour simplifier la gestion du SSL, j'ai choisi d'utiliser Caddy qui gère déjà mes domaines sur mon infrastructure cependant il est possible d'utiliser Nginx ou encore de passer par Cloudflare, les autres solutions sont documentées ici.
Pour la base de données Zitadel recommande l'utilisation de Cockroach en production mais à nouveau dans cette exemple nous sommes sur une petite production où la mise en place d'un cluster de ce type serait surdimensionné.

Installation de PostgreSQL

Installation

Nous aurons besoin d'une installation basique de PostgreSQL en ajoutant les dépôts officiel via le script présent dans la distribution Ubuntu :

sudo apt install -y postgresql-common

sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh

Installation du dépôt et des paquets PostgreSQL

Configuration

Nous devons ensuite créer un utilisateur et une base de donnée pour Zitadel :

sudo -u postgres psql
CREATE USER zitadel WITH PASSWORD '<mot de passe>';
CREATE DATABASE zitadel;
GRANT CONNECT, CREATE ON DATABASE zitadel TO zitadel;

Installation de Zitadel

L'installation de Zitadel est une opération manuelle.

Voici un résumé des étapes que nous allons réaliser :

  1. Récupérer le binaire de Zitadel
  2. Créer un utilisateur
  3. Créer les répertoires
  4. Définir les permissions sur les répertoires
  5. Créer le service

Commençons par la récupération du binaire à partir de la dernière version publiée sur Github :

LATEST=$(curl -i https://github.com/zitadel/zitadel/releases/latest | grep location: | cut -d '/' -f 8 | tr -d '\r'); wget -c https://github.com/zitadel/zitadel/releases/download/$LATEST/zitadel-linux-amd64.tar.gz -O - | tar -xz && sudo mv zitadel-linux-amd64/zitadel /usr/local/bin

Ici en une ligne nous récupérons la dernière version disponible, nous téléchargeons cette version, la décompressons puis déplaçons le binaire.
Sur la documentation officielle vous trouverez une méthode qui prend également en compte l'architecture de la machine.

Nous créons un utilisateur pour notre outil :

sudo useradd -r -U -M -d /var/lib/zitadel/ -s /usr/sbin/nologin zitadel

Nous utilisons plusieurs arguments:

  • -r permet d'indiquer quíl s'agit d'un utilisateur système
  • -U pour créer un groupe avec le même nom que l'utilisateur
  • -M pour ne pas créer de répertoire HOME
  • -d pour définir le répertoire à utiliser comme dossier HOME
  • -s pour définir le Shell de connexion de l'utilisateur (ici notre utilisateur n'ayant pas besoin de se connecter au système de façon interactive nous pouvons utiliser /usr/sbin/nologin)

Ensuite il faut créer les dossiers qui seront utilisés par Zitadel :

sudo mkdir -p /var/lib/zitadel /etc/zitadel
tr -dc A-Za-z0-9 </dev/urandom | head -c 32 | sudo tee /etc/zitadel/zitadel-masterkey
sudo touch /etc/zitadel/config.yaml /etc/default/zitadel
sudo chown -R zitadel:zitadel /var/lib/zitadel
sudo chown -R root:zitadel /etc/zitadel
sudo chown root:root /etc/default/zitadel
sudo chmod 640 /etc/zitadel/config.yaml /etc/default/zitadel /etc/zitadel/zitadel-masterkey

La deuxième commande permettra de générer la clé de sécurité pour le chiffrement des données dans Zitadel.

Nous pouvons ensuite créer le service qui permettra de lancer notre outil :

[Unit]
Description=Zitadel

[Service]
RestartSec=2s
Type=simple
User=zitadel
Group=zitadel
EnvironmentFile=/etc/default/zitadel
WorkingDirectory=/var/lib/zitadel
ExecStart=/usr/local/bin/zitadel start --config /etc/zitadel/config.yaml --masterkeyFile ${MASTERKEYFILE} --tlsMode ${TLSMODE}
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target

/etc/systemd/system/zitadel.service

Comme certains paramètres en arguments nous allons définir les valeurs associées :

USER=zitadel
GROUP=zitadel
HOME=/var/lib/zitadel
TLSMODE=external
MASTERKEYFILE=/etc/zitadel/zitadel-masterkey

/etc/default/zitadel

Il faut ensuite recharger le daemon systemd pour appliquer la configuration du service :

sudo systemctl daemon-reload

Configuration de Zitadel

La première configuration consiste à définir les ports d'écoute et la connexion à la base de donnée. Nous allons donc éditer le fichier /etc/zitadel/config.yaml:

Port: 8080
ExternalPort: 443
ExternalDomain: <votre domaine>
ExternalSecure: true
TLS:
  Enabled: false
Database:
  postgres:
    Host: localhost
    Port: 5432
    Database: zitadel
    User:
      Username: zitadel
      Password: <mot de passe>
      SSL:
        Mode: disable

/etc/zitadel/config.yaml

Vous trouverez toutes les options de configuration dans la documentation.

Nous pouvons maintenant lancer l'initialisation de Zitadel via la commande appropriée :

sudo -u zitadel -g zitadel zitadel init --config /etc/zitadel/config.yaml zitadel
sudo -u zitadel -g zitadel zitadel setup --config /etc/zitadel/config.yaml --tlsMode external --masterkeyFile /etc/zitadel/zitadel-masterkey --init-projections

Comme nous avons déjà créer la base de donnée et l'utilisateur associé (afin de ne pas fournir de compte avec des droits élevés sur la base). La première commande permet de vérifier la configuration et de créer le schéma dans la base de données, la deuxième effectue les migrations nécessaire pour peupler cette dernière.

Cette étape va également configurer le compte administrateur avec les informations suivantes :

  • Utilisateur: zitadel-admin@<hostname VM>.<domaine Zitadel>
  • Mot de passe: Password1!

Vous pouvez également utiliser PostgreSQL pour récupérer le nom d'utilisateur :

sudo -u postgres psql -d zitadel -c '\x' -c 'SELECT user_name FROM auth.users2;'

Installation du reverse proxy

Comme indiqué plus haut nous allons installer et configurer Caddy qui sera notre reverse proxy. Comme nous avons définir le mode TLS comme external il sera en charge d'ajouter cette couche.

Un des avantages de Caddy est la génération de certificats automatiquement avec Let's Encrypt.

Il est disponible depuis les dépôts Ubuntu :

sudo apt install Caddy

Nous pouvons ensuite le configurer avec notre domaine pour transmettre les requêtes à Zitadel en grpc. Cette configuration se fait via le fichier /etc/caddy/Caddyfile qu'il faut créer s'il n'existe pas.

zitadel.thystips.net {
	reverse_proxy h2c://127.0.0.1:8080
}

/etc/caddy/Caddyfile

Cette configuration est suffisante pour mettre en place le reverse proxy dont nous avons besoin. Caddy utilisera le challenge HTTP01 pour demander un certificat à Let's Encrypt.

Si cette solution n'est pas adapté pour vous je vous invite à lire la documentation de Caddy sur les autres possibilité de configuration du TLS.

Démarrage de la solution

Maintenant nous pouvons lancer les deux services nécessaire pour que notre solution soit accessible :

sudo systemctl enable --now zitadel.service caddy.service

L'interface d'administration est maintenant accessible via : https://<votre domaine>/ui/console, dans mon cas il s'agit donc de https://zitadel.thystips.net.

Une fois connecté vous serrez amené à changer le mot de passe de l'utilisateur et si vous le souhaitez à définir un second facteur d'authentification pour sécurisé votre compte.

Après avoir jouer avec pendant quelques heures on remarque que l'intégration LDAP n'est pas encore très aboutie au moment où je rédige cet article.
Je reste à l’affût de plusieurs issues et discussions à ce sujet sur Github :

Peut-être que je ferais un autre article pour parler un peu de mon retour d'expérience en détail et faire une présentation de la configuration de l'outil.