← Retour aux articles
26 October 2026 15 min de lecture Self-HostingGoogle WorkspaceStalwartAuthentikJMAPSouveraineté

Sortir de Google Workspace : mail, agendas, visio et bureautique sur un serveur dédié, un seul SSO

Le MX a quitté Google le 24 octobre. Stalwart en JMAP seul, Authentik partout, Jitsi, OpenCloud + Collabora, un relais SMTP interne, et une vue en lecture seule de la prod via le MCP Maintenant.

Ce qui tourne aujourd’hui

Le 24 octobre 2026, l’enregistrement MX de mon domaine a cessé de pointer vers Google. Depuis, le mail arrive sur un serveur dédié, dans Stalwart, et je le lis dans Bulwark, un webmail installé comme application sur le bureau et sur Android. Les agendas et les contacts sont dans Stalwart aussi, qui fait Calendrier et Contact sans rien ajouter. La page de prise de rendez-vous que les prospects utilisent n’est plus un lien Google Calendar. La visio n’est plus Meet. Les documents s’ouvrent dans Collabora, depuis OpenCloud. Et chacun de ces services demande le même compte, le même mot de passe, la même double authentification : Authentik.

Google WorkspaceSur le serveur
GmailStalwart (serveur) + Bulwark (webmail, JMAP)
Agenda, ContactsCalDAV / CardDAV intégrés à Stalwart
Lien de prise de rendez-vousTymeslot
MeetJitsi Meet
Drive, Docs, SheetsOpenCloud + Collabora Online
Comptes, SSO, 2FAAuthentik

Plus rien ne justifie de garder l’abonnement Workspace. La suite est technique : les choix, les bugs, et ce qui manque encore. Pas de théorie sur la souveraineté, le sujet a sa page sur ce site.

Un serveur dédié, et son dimensionnement

Tout tourne sur un serveur dédié chez Scaleway, un EM-A410X-SSD : un Xeon six cœurs, 64 Go de RAM, deux SSD d’un téraoctet, pour un peu moins de 70 € par mois. En face, pour une équipe d’une dizaine de personnes, Google Workspace coûte dans les 120 € par mois. Pour une équipe de cent, c’est 1 200 €, et le serveur coûte toujours 70 €. La facture Google suit le nombre de comptes, celle du serveur suit la taille de la machine, par paliers. Cent boîtes mail et cent comptes SSO tiennent sans problème sur ce Xeon. Ce qui finit par coincer, c’est le disque et le nombre de visios simultanées, et ce jour-là on prend la taille au-dessus, ou une machine secondaire dédié, pas dix fois le prix. L’écart n’est pas la raison du déménagement, et il faut y ajouter le maintien en condition opérationnelle, qui n’est gratuit que si c’est ton métier. Avec ce coût-là, être indépendant peut revenir plus cher que Google. Ce n’est pas une économie qu’on achète : c’est que le courrier, les agendas et les documents restent chez soi, sur une machine dont on a les clés, et qu’on peut les emporter ailleurs demain. Proton, Infomaniak et les autres hébergeurs plus respectueux sont une réponse intermédiaire : même facture par siège, à peu près au tarif de Google, et chez Proton ni CalDAV pour l’agenda ni IMAP sans son Bridge. C’est un meilleur locataire, pas une sortie du modèle.

Ce qui compte, c’est que la taille de la machine décide de ce qu’on peut y mettre, pas l’inverse. Un VPS à 2 Go de RAM porte Traefik, le SSO et le mail. Il ne porte pas Jitsi, Collabora et une base vectorielle pour les photos en plus. Au moment où j’écris, la machine fait tourner 58 conteneurs, dont une bonne partie n’a rien à voir avec l’exit Google (les sites, les produits, leurs bases). Ça consomme moins de 7 Go de RAM et la moitié du disque. La marge est là parce que le serveur a été choisi pour ça.

L’infrastructure de base est celle que je décris dans mon guide d’auto-hébergement : Debian, Docker Compose, Traefik avec des certificats Let’s Encrypt obtenus par challenge DNS, CrowdSec, un pare-feu. Depuis, j’ai poussé ces scripts jusqu’à l’identité et jusqu’au mail, et toute la méthode est automatisée et documentée : un script qui prend une Debian vierge et sort un serveur durci avec le SSO, un installeur par application, un installeur pour la pile mail, un runbook de durcissement pour une machine déjà en production, et une VM de test pour valider chaque brique avant de la pousser. Ces scripts sont nés pour l’installation d’un client, où ils ont été éprouvés en premier. Ma propre migration a pris trois jours, et l’ensemble représente une quinzaine de jours de travail.

Un seul fournisseur d’identité

Il n’y a qu’un fournisseur d’identité, Authentik. Avant, j’avais un annuaire LDAP d’un côté et un portail d’authentification de l’autre, deux outils à maintenir pour une seule question : qui a le droit d’entrer. Authentik fait les deux, et surtout il parle OIDC, forward-auth et LDAP avec le même annuaire derrière.

Chaque application reçoit son propre fournisseur OIDC, avec son propre émetteur. Celles qui savent parler OIDC (OpenCloud, Tymeslot, le serveur Matrix, le gestionnaire de mots de passe) s’y connectent directement. Celles qui ne savent pas (l’analytique web, les outils d’administration) passent par le forward-auth de Traefik : la requête est interceptée, Authentik vérifie la session, et seulement ensuite l’application voit passer l’utilisateur.

Les groupes sont hiérarchiques : users, managers, admins. Un administrateur est membre de tout ce qui est ouvert aux utilisateurs, mais un outil réservé aux admins impose la double authentification, et un outil du quotidien ouvert aux users ne force personne à enrôler un TOTP. Le réglage se fait au moment de l’installation ou après coup, par application, sans toucher à l’interface d’Authentik.

Tout ça est déclaratif. Authentik lit des fichiers YAML (ses « blueprints »), et chaque installeur en génère un par application : le fournisseur, l’application, les groupes autorisés. Désinstaller une application, c’est réécrire le même fichier avec state: absent et le réappliquer. Aucun clic dans l’interface, et un serveur reconstruit depuis zéro retrouve exactement la même configuration.

Le mail en JMAP, et rien d’autre

C’est le choix le plus radical de la pile. Stalwart, le serveur de mail, n’expose que trois choses : le port 25 pour recevoir, JMAP pour les clients, et CalDAV/CardDAV. Pas d’IMAP. Pas de SMTP authentifié pour l’envoi. Pas de ManageSieve.

JMAP, c’est le protocole qui aurait dû remplacer IMAP il y a dix ans : du JSON sur HTTPS, une seule connexion pour le mail, les contacts et les agendas, une synchronisation par état plutôt que par balayage de dossiers. Le client, Bulwark, est un pur client JMAP : il ne connaît que l’adresse du serveur, le navigateur appelle Stalwart directement, et il s’installe comme application web sur le bureau et sur Android. Une application mobile existe aussi, qu’on apparie avec un QR code depuis le webmail.

Pourquoi fermer IMAP ? Parce que le mot de passe du compte ne sert plus à rien côté mail. Stalwart est branché sur Authentik par OIDC : Bulwark fait une authentification par code avec PKCE contre Authentik et présente le jeton obtenu à Stalwart. Un mot de passe envoyé dans une session IMAP serait refusé. Les clients qui ne savent faire que du HTTP Basic (un agenda sur le téléphone, un script) utilisent un mot de passe d’application que l’utilisateur crée lui-même dans Stalwart. Le compte Authentik, avec sa double authentification, n’est jamais exposé à un protocole qui ne la comprend pas.

La migration n’a rien eu de spécial. Stalwart a tourné à côté de Gmail pendant cinq jours. L’historique a été copié avec imapsync, pendant que le MX pointait encore chez Google. Le 24 octobre, j’ai changé l’enregistrement MX, et les enregistrements SPF, DKIM et DMARC que l’installeur affiche à la fin. Stalwart génère ses clés DKIM tout seul au moment où on lui déclare le domaine.

Trois choses ont cassé :

  • Le conteneur ne doit pas porter le nom du serveur de mail. Docker enregistre le hostname d’un conteneur comme nom DNS sur chaque réseau qu’il rejoint. Avec hostname: mail.<domaine>, tous les conteneurs du réseau web résolvaient le nom public du serveur mail vers Stalwart lui-même, qui n’écoute ni sur 80 ni sur 443. Bulwark ne pouvait plus vérifier sa session, son cookie n’était jamais écrit, et l’appairage mobile répondait « not authenticated ». Le nom SMTP se déclare dans la configuration, pas sur le conteneur.
  • L’annuaire OIDC reste en panne si Authentik répond trop tard. Au démarrage, Stalwart interroge Authentik ; si la réponse n’arrive pas dans les trente secondes, l’annuaire est marqué en échec et chaque connexion renvoie une erreur 500 jusqu’au prochain redémarrage, alors que le courrier entrant continue d’arriver. Le healthcheck du conteneur fait donc une fausse connexion Basic et tue le processus quand il obtient un 500 alors qu’Authentik répond : Docker redémarre Stalwart, et tout rentre dans l’ordre.
  • La configuration d’authentification ne s’applique pas en mode recovery. Stalwart 0.16 se configure par un plan déclaratif appliqué pendant qu’il tourne en mode recovery. Mais c’est seulement au premier démarrage normal qu’il crée ses rôles intégrés et les attache aux comptes. Écrire la configuration d’authentification depuis le plan de recovery laisse tous les comptes sans aucun droit : connexion acceptée, puis refus sur la première action. Il faut un premier démarrage normal, puis appliquer le second plan.

Trois jours perdus sur ces trois bugs, et aucun n’est documenté.

Agendas, contacts, prise de rendez-vous

Les agendas et les contacts vivent dans Stalwart, qui fait CalDAV et CardDAV nativement. Les exports de Google (.ics et .vcf) se réimportent depuis Bulwark. Sur le téléphone, le client CalDAV reçoit un mot de passe d’application, le même mécanisme que pour les scripts.

Le lien de réservation de Google Calendar est une fonction que les prospects utilisent, et il fallait un remplaçant avant de couper. Tymeslot (Elixir, AGPL) fait exactement ça : une page publique, les créneaux calculés à partir d’un agenda CalDAV, et une confirmation par mail. Il se connecte à Authentik comme fournisseur OAuth générique. Le premier compte créé devient administrateur de l’application, donc son accès est réservé au groupe admins. L’agenda, c’est celui de Stalwart, avec un mot de passe d’application ; la visio, c’est Jitsi.

Deux réglages à connaître. Tymeslot sait parler à Jitsi avec un identifiant et un secret d’application : je ne les lui donne pas, parce qu’avec, il insère un jeton signé dans le lien envoyé au prospect, et sur mon Jitsi tout porteur de jeton est modérateur. Sans secret, le prospect clique sur un lien nu et attend que l’hôte, authentifié, ouvre la salle. Et Tymeslot envoie ses mails par le relais SMTP interne sans vérifier son certificat : le relais offre STARTTLS avec un certificat autosigné dont la clé privée est publique, vérifier n’authentifie rien, et Tymeslot refuserait d’envoyer.

La visio derrière Traefik, UDP compris

Jitsi Meet n’a pas d’OIDC. Il tourne en mode JWT, avec un petit adaptateur qui fabrique le jeton après une connexion Authentik. L’hôte clique sur « se connecter », passe par Authentik, revient modérateur. Les invités n’ont pas de compte : ils entrent dans une salle d’attente jusqu’à ce qu’un hôte arrive (comme dans Teams en fait…).

Le flux média passe par Traefik, lui aussi. Traefik sait router l’UDP, et l’installeur lui ajoute un point d’entrée UDP sur le port 10000 qui mène au pont vidéo. Aucun conteneur ne publie de port directement, c’est la règle sur toute la machine. Attention au pare-feu : Docker contourne UFW pour les ports qu’il publie, et il faut une règle route explicite pour qu’un port publié soit atteignable, sinon le service est injoignable depuis l’extérieur, sans aucune erreur nulle part.

Les images Jitsi comptent sur un binaire setuid que l’option no-new-privileges désactive, et tous les conteneurs s’arrêtent au démarrage. La solution : système de fichiers en lecture seule, et des tmpfs montés aux bons endroits pour l’utilisateur du conteneur. Validé à trois participants, dont un flux qui passe par le pont (à deux, WebRTC reste en pair-à-pair).

Pas de serveur TURN pour l’instant : un participant dont le réseau bloque l’UDP ne se connecte pas. A voir si j’ai souvent le cas j’ajouterai TURN (il est prêt dans ma pile).

Fichiers et bureautique

OpenCloud remplace Drive, avantageusement. Il parle OIDC nativement, y compris pour ses clients de bureau et mobiles, chacun enregistré comme une application à part dans Authentik. Collabora Online remplace Docs et Sheets : le serveur WOPI est celui d’OpenCloud lui-même, servi sur le même nom, et Collabora n’est qu’un moteur d’édition derrière.

Un compromis : Collabora veut des capacités système que no-new-privileges lui refuse, et le profil seccomp de Docker lui refuse les espaces de noms. Les recettes officielles lui donnent SYS_ADMIN et désactivent seccomp et AppArmor. Je préfère lui dire de ne pas utiliser ces capacités ; chaque document est alors édité dans un sandbox Landlock plutôt que dans un chroot. Ça ouvre les documents, et ça laisse le reste de la politique de sécurité intacte.

Un relais SMTP pour toutes les applications

Chaque application de la machine veut envoyer des mails : Authentik pour les réinitialisations, Tymeslot pour les confirmations, le gestionnaire de mots de passe pour les invitations, Stalwart lui-même pour le courrier sortant. Plutôt que de donner à chacune un compte chez un fournisseur, un seul relais Postfix tourne sur un réseau Docker dédié, et toutes y pointent avec la même configuration : smtp-relay, port 25, pas d’authentification. Seuls les conteneurs du serveur peuvent l’atteindre. Le relais, lui, s’authentifie auprès d’un fournisseur d’envoi transactionnel, qui vérifie les domaines expéditeurs.

Je ne filtre pas les domaines expéditeurs sur le relais, volontairement. Le fournisseur amont le fait déjà, et un filtre local rejetterait chaque domaine de mail supplémentaire et chaque rebond. Un seul point de configuration SMTP sur la machine, une seule clé à faire tourner, et une application qui veut envoyer du mail n’a besoin d’aucun secret.

Sauvegardes et durcissement

Chaque application porte son propre service de sauvegarde, inactif par défaut : restic vers un stockage S3, un dépôt par application, de sorte qu’on restaure une application sans toucher aux autres. Le service fait son pg_dump en client réseau sur le réseau interne de l’application, puis envoie les données et le fichier .env, qui contient la clé de chiffrement. La restauration refuse de s’exécuter si cette clé manque dans l’instantané. Aucun de ces conteneurs ne voit le socket Docker. Chaque sauvegarde envoie un battement de cœur à Maintenant, qui alerte si elle ne se présente pas.

Stalwart est l’exception : sa base RocksDB n’a pas de copie à chaud sûre, donc une tâche cron de l’hôte l’arrête, le sauvegarde et le redémarre. Quelques secondes de coupure par nuit, pendant lesquelles les serveurs expéditeurs réessaient, comme SMTP le prévoit. Le cycle sauvegarde, effacement des données, restauration a été joué sur la VM avant la mise en production.

Pour le durcissement, la méthode est la même que pour le reste. D’abord une analyse de l’état réel de la machine en production, faite depuis ce que le MCP de Maintenant expose, le dépôt en face pour comparer ce que les scripts sont censés produire et ce qui tourne vraiment. Le résultat est une liste d’écarts. Puis chaque écart est comblé, sur la VM d’abord, avec un runbook écrit pour une machine déjà en production, et une seconde session SSH ouverte avant chaque changement de pare-feu. À l’arrivée : SSH sur un port non standard, clé uniquement, root interdit, un seul utilisateur autorisé. Mises à jour de sécurité automatiques, Docker exclu, parce qu’une mise à jour de Docker redémarre tous les conteneurs. Le socket Docker n’est monté que par un proxy qui n’accepte que les lectures, et c’est lui que Traefik et Maintenant interrogent. Les réseaux sont segmentés : un conteneur sans route Traefik ne voit pas le réseau public. HSTS sur chaque routeur. Et un script qui vérifie tout ça d’un coup, pour la prochaine machine.

La méthode : une VM avant la prod, et la prod en lecture seule

Une bonne partie du code, je l’ai produite avec Claude Code, du script de bootstrap aux installeurs d’applications. Ce que ça change et ce que ça coûte, je l’ai raconté ailleurs. Ici, deux habitudes ont fait la différence.

La première, c’est la VM. Un script qui durcit SSH, reconfigure le pare-feu, installe Docker et redémarre la machine ne se teste pas dans un conteneur. Il se teste dans une Debian sous QEMU/KVM, pilotée avec virsh : un vrai domaine, un challenge DNS, l’environnement de staging de Let’s Encrypt. Chaque brique est installée de bout en bout sur la VM, cassée, restaurée, avant d’être installée sur le serveur. Les trois bugs de Stalwart ci-dessus ont été trouvés là, pas en production.

La seconde, c’est une vue en lecture seule de la production. Maintenant, mon outil de supervision, expose un serveur MCP : la liste des conteneurs et leur état, leurs journaux, les certificats et leur échéance, les battements de cœur des sauvegardes, les alertes, les ressources de la machine. Branché sur l’assistant, il remplace le copier-coller de journaux : l’état réel de la production est comparé à ce que les scripts sont censés produire, et je pars de ce constat pour corriger. L’inventaire au début du runbook de durcissement et les chiffres de dimensionnement plus haut viennent de là. Rien dans ce MCP ne redémarre, ne modifie, ne supprime. L’action reste de mon côté, sur la VM d’abord.

Ce qui ne marche pas encore

  • Pas d’IMAP, donc pas de Thunderbird ni d’Apple Mail. C’est un choix, pas un oubli, mais il exclut tout client classique. Si ton équipe tient à Outlook, il faudra ajouter ouvrir le mail avec un mot de passe direct…
  • L’application mobile Bulwark n’a le SSO que par le webmail. Donnée une adresse mail, elle trouve Stalwart et tombe sur son serveur OAuth interne, qui ne connaît pas Authentik. Il faut lui donner l’adresse du webmail, ou scanner le QR code.
  • Une adresse inconnue reçoit un 550 tant que son propriétaire ne s’est pas connecté une fois. L’annuaire OIDC ne résout pas les destinataires ; le compte local est créé à la première connexion. Il faut faire ouvrir le webmail aux nouveaux avant de leur annoncer leur adresse.
  • Pas de TURN : la visio échoue pour qui est derrière un réseau qui bloque l’UDP; turn n’est pas compliqué en soit, je ne suis juste pas certain qu’il soient nécessaire, a voir avec le temps.
  • La synchronisation de fichiers hors OpenCloud (un gestionnaire de tâches, par exemple) via WebDAV n’est pas validée de bout en bout.
  • Le tableau blanc (Excalidraw) est auto-hébergé, mais sa collaboration en direct et ses liens de partage passent par les serveurs de l’éditeur : les adresses sont compilées dans l’application.

Ce que j’en retiens

  1. Un seul fournisseur d’identité, et tout le reste s’y plie. Chaque application a été choisie d’abord pour sa capacité à déléguer l’authentification. Celles qui ne savaient pas ont été mises derrière Traefik ou écartées.
  2. Fermer un protocole est une décision, pas une régression. Sans IMAP, le mot de passe du compte ne circule nulle part, et la double authentification vaut partout. Le prix, ce sont les clients classiques.
  3. La VM avant la prod, et la prod en lecture seule pour l’assistant. Les trois bugs de Stalwart ont coûté trois jours sur la VM. En production, ils auraient coûté du courrier.

Si cette démarche t’intéresse pour ton équipe, c’est exactement le périmètre de mon offre de remplacement SaaS par l’auto-hébergement : audit, choix des briques, migration, formation.

Besoin d'aide sur ce sujet ?

Réserver un créneau