Installer mailcow sur un VPS accepté par Gmail
Vérifiez le port SMTP 25 avant l’installation de mailcow : s’il est bloqué, les messages restent en file d’attente. Configurez aussi le PTR contre l’erreur Gmail 550 5.7.25.
Ce que vous allez mettre en place
Un serveur de messagerie complet sur une machine que vous possédez : SMTP pour envoyer et recevoir, IMAP pour synchroniser votre téléphone et votre ordinateur portable, un client de webmail et un filtre antispam qui évalue chaque message dans les deux sens. mailcow-dockerized regroupe Postfix, Dovecot, Rspamd, le webmail SOGo, MariaDB, Redis et un client ACME dans une seule stack Docker Compose. Le logiciel n’est donc pas la partie la plus difficile. Vous pouvez avoir un serveur fonctionnel en une demi-heure.
La difficulté se trouve dans tout ce qui l’entoure. La messagerie est le seul service pour lequel le reste d’Internet se méfie activement d’un serveur récent. L’écart entre « ça fonctionne » et « Gmail supprime silencieusement tous les messages » dépend de quatre enregistrements DNS et d’un paramètre de réputation IP que vous ne contrôlez peut-être pas complètement. Lisez les prérequis ci-dessous avant de louer quoi que ce soit. Après cette lecture, si vous décidez que la construction d’une réputation ne vaut pas l’effort, c’est une réponse légitime. Notre récapitulatif de ce qui vaut réellement la peine d’être auto-hébergé en 2026 classe la messagerie dans la catégorie « uniquement si vous en avez réellement l’intention », précisément pour ces raisons.
Les prérequis constituent le projet
Si vous en oubliez un seul, vous enverrez des e-mails qui n’arriveront jamais. Voici les points classés grossièrement selon la fréquence à laquelle ils font échouer les déploiements :
Le port sortant 25 doit être ouvert. Votre serveur remet les e-mails à Gmail et Microsoft via le port TCP 25. De nombreux fournisseurs de VPS et de cloud bloquent par défaut le port 25 sortant pour lutter contre le spam. Ce blocage est silencieux : aucune erreur n’apparaît au démarrage, tout semble fonctionner et les e-mails restent simplement indéfiniment dans la file d’attente. Testez ce point avant d’installer quoi que ce soit. S’il est bloqué, la seule solution consiste à ouvrir un ticket auprès de votre fournisseur pour lui demander de le débloquer. Certains acceptent de le faire pour les comptes suffisamment anciens, d’autres refusent systématiquement.
Une adresse IP propre, avec une réputation exploitable. Les adresses IP de VPS recyclées figurent souvent déjà sur des blocklists à cause du spam envoyé par un précédent locataire. Vérifiez la vôtre avec un service comme la recherche Spamhaus ou mxtoolbox avant de vous engager. Une adresse IP listée entraîne des rejets que vous ne pourrez pas résoudre par la configuration.
La gestion du DNS et un enregistrement PTR correct. Vous devez pouvoir ajouter des enregistrements à la zone de votre domaine. Vous devez également disposer d’un reverse DNS (PTR) pour l’adresse IP du serveur, qui pointe vers le hostname de messagerie. Le PTR est presque toujours géré en dehors de votre panneau DNS. Il dépend du propriétaire de l’adresse IP. Vous le configurez donc dans le panneau de contrôle de votre fournisseur de VPS ou par ticket.
6 GiB de RAM et 2 vCPU constituent un minimum confortable. Le minimum indiqué par mailcow est de 6 GiB de RAM et 1 GiB de swap pour une installation privée. Une configuration de 8 GiB est recommandée dès que plusieurs utilisateurs s’en servent. En dessous d’environ 2.5 GiB, generate_config.sh propose de désactiver l’antivirus ClamAV afin que le kernel ne commence pas à arrêter les conteneurs. Prévoyez 20 GB de SSD pour commencer.
Un nom DNS, pas une simple adresse IP. Choisissez un hostname comme mail.example.com. Ce nom devient votre MAILCOW_HOSTNAME, le sujet de votre certificat TLS, la cible de votre PTR et votre bannière SMTP. Utilisez-le partout de manière cohérente.
Étape 1, vérifiez que le port sortant 25 est ouvert
Commencez par cette étape. Si elle échoue, tout le reste est inutile. Depuis le VPS fraîchement installé, essayez d’ouvrir une session SMTP avec un véritable serveur de messagerie :
sudo apt update && sudo apt install -y netcat-openbsd
nc -vz -w 5 gmail-smtp-in.l.google.com 25Si le test réussit, le résultat est immédiat :
Connection to gmail-smtp-in.l.google.com (142.250.x.x) 25 port [tcp/smtp] succeeded!Un port bloqué attend pendant les cinq secondes complètes, puis échoue :
nc: connect to gmail-smtp-in.l.google.com port 25 (tcp) timed out: Operation now in progressCe délai d’attente indique le blocage. Il s’agit d’un filtre réseau appliqué par le fournisseur, pas de votre pare-feu. Aucune modification locale ne peut donc le corriger. Ouvrez un ticket avec le message suivant : « Please enable outbound TCP port 25 for my VPS at <IP>; I am running a legitimate mail server. » N’installez pas mailcow tant que ce test ne renvoie pas « succeeded ». Le port entrant 25, utilisé par les autres serveurs pour vous joindre, suit un chemin distinct et est généralement ouvert. C’est le trafic sortant que les fournisseurs limitent.
Étape 2, Créez maintenant les enregistrements DNS
Les modifications DNS prennent du temps à se propager. Publiez donc tout ce que vous pouvez avant l’installation. Supposons que votre domaine soit example.com, que votre hôte de messagerie soit mail.example.com et que l’adresse IP soit 10.0.0.10. Dans votre zone, créez :
mail.example.com. A 10.0.0.10
mail.example.com. AAAA 2001:db8::10 ; only if you have IPv6
example.com. MX 10 mail.example.com.
example.com. TXT "v=spf1 mx -all"
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:postmaster@example.com"L’enregistrement SPF indique que seul votre MX peut envoyer des messages pour ce domaine et que les autres doivent être rejetés. Commencez avec DMARC à p=none pour consulter les rapports sans rejeter vos propres messages. Passez ensuite à p=quarantine, puis à p=reject, lorsque l’alignement est confirmé. Deux enregistrements manquent encore volontairement : DKIM, que mailcow génère à votre place à l’étape 6, et PTR, que vous configurez maintenant dans le panneau de votre fournisseur.
Définissez le PTR (DNS inverse) de 10.0.0.10 sur mail.example.com, c’est-à-dire la valeur exacte de MAILCOW_HOSTNAME. C’est l’enregistrement que la plupart des utilisateurs oublient, et les grands fournisseurs le contrôlent pour refuser les messages. Si votre panneau ne comporte aucun champ rDNS, ouvrez un ticket.
Étape 3 : installer Docker
mailcow nécessite Docker Engine avec le plugin Compose v2. Utilisez le script d’installation officiel de Docker plutôt que le package docker.io d’Ubuntu, qui ne fournit aucun plugin Compose :
curl -fsSL https://get.docker.com | sudo sh
sudo docker compose versionVous devriez voir une ligne Docker Compose version v2.x. Si docker compose version affiche docker: 'compose' is not a docker command, Docker Engine est installé, mais pas le plugin Compose. Installez le plugin depuis le dépôt de Docker, exécutez de nouveau le script ci-dessus ou consultez notre guide de base sur Docker Compose, qui installe les deux composants depuis le dépôt apt de Docker.
Étape 4 : cloner mailcow et générer la configuration
cd /opt
sudo git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
umask
sudo ./generate_config.shVérifiez que umask affiche d’abord 0022. mailcow refuse de se construire avec un masque de fichiers inhabituel, et un shell root ouvert sur Ubuntu 24.04 fournit déjà 0022. Le script demande ensuite la seule information importante : le nom d’hôte pleinement qualifié. Saisissez mail.example.com. Cette valeur doit correspondre exactement à votre enregistrement A et à votre enregistrement PTR. Le script écrit mailcow.conf, l’unique fichier d’environnement lu par toute la stack. Ouvrez-le si vous devez modifier les ports web (HTTP_PORT, HTTPS_PORT) ou désactiver ClamAV sur une petite machine :
MAILCOW_HOSTNAME=mail.example.com
HTTP_PORT=80
HTTPS_PORT=443
SKIP_CLAMD=n # set to y to drop the virus scanner on a <2.5 GiB boxSKIP_FTS=y est l’autre paramètre à ajuster sur une machine équipée de peu de RAM : la recherche en texte intégral est le deuxième consommateur de mémoire cité dans la documentation de mailcow, et la désactiver vous prive uniquement de la recherche dans le corps des messages du webmail.
Conservez HTTP_PORT=80 et HTTPS_PORT=443, sauf si un autre service de l’hôte les utilise déjà. Le client ACME intégré à mailcow doit pouvoir atteindre le port 80 depuis Internet pour obtenir le certificat. C’est pourquoi vous ne devez pas exécuter une configuration nginx-plus-Certbot distincte sur la même machine : mailcow délivre et renouvelle lui-même ses certificats TLS en interne, et un second service qui occupe les ports 80/443 provoque un conflit. Cela vaut aussi pour tout autre service qui nécessite une interface web publique. Une configuration comme Halcyon qui transforme une bibliothèque Jellyfin en vidéoclub des années 90, et qui attend son propre reverse proxy sur 443, doit donc être déployée sur un autre hôte. L’exception concerne les services qui ne demandent jamais de port web public : un relais RustDesk auto-hébergé écoute uniquement sur sa propre plage de ports 21115 à 21119. Il peut donc partager la machine, à condition de disposer d’une marge suffisante en bande passante.
Étape 5, démarrer la stack et se connecter
sudo docker compose pull
sudo docker compose up -d
sudo docker compose psLe pull récupère environ deux douzaines d’images ; comptez quelques minutes. Lorsque docker compose ps affiche que tous les conteneurs sont running (ou healthy), ouvrez https://mail.example.com dans un navigateur. Les identifiants administrateur par défaut sont le nom d’utilisateur admin et le mot de passe moohoo. Changez immédiatement ce mot de passe dans l’interface d’administration, sous Access → Administrators. Si le navigateur signale NET::ERR_CERT_AUTHORITY_INVALID, le certificat ACME n’a pas encore été délivré. Consultez la section sur l’échec ACME avant de conclure à un problème ; un certificat autosigné temporaire est normal pendant la première ou les deux premières minutes.
Étape 6, ajouter un domaine, une boîte aux lettres et publier DKIM
Dans l’interface d’administration, ouvrez la page Mail Setup (Configuration → Mail Setup). Dans l’onglet Domains, cliquez sur Add domain et saisissez example.com. Ensuite, dans la section Mailboxes, cliquez sur Add mailbox pour créer you@example.com avec un mot de passe. La boîte aux lettres est alors déjà fonctionnelle et accessible via IMAP.
Configurez maintenant la clé DKIM. Accédez à Configuration → ARC/DKIM keys. mailcow a peut-être déjà généré une clé lorsque vous avez ajouté le domaine. Si ce n’est pas le cas, générez-en une à cet endroit, sélectionnez le domaine, conservez le sélecteur dkim, choisissez 2048-bit, puis cliquez sur Add. Copiez la longue valeur TXT affichée et publiez-la ainsi :
dkim._domainkey.example.com. TXT "v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqh...long-key...QAB"La page Domains de mailcow comporte un bouton DNS. Il répertorie tous les enregistrements attendus et indique, avec une coche verte ou une croix rouge, ce qui est effectivement publié. Utilisez cette liste comme checklist et vérifiez que chaque ligne est verte avant de tester la délivrabilité. Une ligne DKIM rouge après la publication indique généralement que la clé a été découpée incorrectement entre plusieurs fragments TXT. Une clé de 2048-bit dépasse la limite de 255 caractères d’une chaîne TXT unique. Collez-la donc comme une seule valeur logique et laissez votre hébergeur DNS la découper en fragments.
Étape 7 : testez la délivrabilité et visez 10/10
Accédez à mail-tester.com, copiez l’adresse aléatoire affichée, puis envoyez-lui un message depuis votre nouvelle boîte aux lettres. Connectez-vous à la messagerie web SOGo à l’adresse https://mail.example.com/SOGo et envoyez le message depuis cette interface. Cliquez ensuite sur « Then check your score ».
Visez 10/10. Voici les déductions les plus fréquentes et leurs causes :
- SPF non aligné : votre enregistrement
MX/SPF est absent ou l’adresse IP d’envoi n’est pas couverte. Vérifiez à nouveau l’enregistrement TXT SPF. - La signature DKIM n’est pas vérifiée : l’enregistrement TXT
dkim._domainkeyest absent, sa propagation n’est pas terminée ou son contenu est incorrect. C’est l’erreur la plus fréquente. - PTR absent / PTR incohérent : le reverse DNS ne résout pas vers
mail.example.com. Corrigez ce paramètre auprès du fournisseur. - Adresse IP présente sur une blocklist : la réputation antérieure de votre adresse IP est en cause. Demandez son retrait de la liste ou demandez une adresse IP avec une meilleure réputation.
N’envoyez pas de vrais e-mails vers Gmail ou Outlook tant que le score n’est pas de 10/10. Un score faible associé à une nouvelle adresse IP peut entraîner le signalement de votre domaine dès le premier jour.
Étape 8, Connecter un véritable client de messagerie
Configurez Thunderbird, Apple Mail ou votre téléphone avec ces paramètres. Le serveur est mail.example.com dans tous les cas :
- IMAP : port 993, SSL/TLS (ou 143 avec STARTTLS)
- Envoi SMTP : port 465, SSL/TLS (ou 587 avec STARTTLS)
- Nom d’utilisateur : l’adresse complète,
you@example.com - Mot de passe : le mot de passe de la boîte aux lettres que vous avez défini
N’envoyez jamais les messages d’un client sur le port 25. Ce port est réservé aux échanges entre serveurs. mailcow n’y propose pas d’envoi authentifié, et les clients qui l’utilisent sont refusés. Si un client affiche Relay access denied, il essaie d’envoyer les messages sur le port 25 ou sans authentification. Configurez-le sur le port 465 ou 587 avec les identifiants de votre boîte aux lettres.
Étape 9 : sauvegardez ce qui compte vraiment
mailcow fournit un script de sauvegarde qui capture l’état de chaque volume persistant. Exécutez-le vers un disque externe ou un emplacement distant monté :
sudo MAILCOW_BACKUP_LOCATION=/opt/mailcow-backups \
./helper-scripts/backup_and_restore.sh backup allall capture six éléments. La perte de l’un d’eux entraîne une perte de données : vmail (les boîtes aux lettres elles-mêmes), crypt (les clés qui déchiffrent vmail, inutiles sans celui-ci), mysql (MariaDB, qui contient les domaines, les utilisateurs, les alias et les paramètres), redis (l’état de la file d’attente et du cache), rspamd (les données apprises sur les spams et les messages légitimes) et postfix (la file d’attente des messages). Le script s’exécute dans un conteneur auxiliaire qui écrit des archives compressées. Les sauvegardes restent ainsi cohérentes, même lorsque la stack est en fonctionnement. Automatisez-le avec une tâche cron quotidienne et ajoutez --delete-days 14 pour supprimer les anciens jeux de sauvegardes. Une tâche cron qui ne fonctionne plus échoue silencieusement. Envoyez donc le code de sortie du script vers un système de notification que vous consultez réellement ; un serveur ntfy auto-hébergé accepte une commande curl sur une seule ligne dans la même entrée cron et vous signale l’échec sur votre téléphone la nuit où il survient. La restauration utilise le même script avec restore. Cette option affiche les snapshots et vous permet de choisir les éléments à restaurer. Une sauvegarde dont vous n’avez jamais testé la restauration n’est qu’un espoir, pas une sauvegarde. Effectuez un test à blanc sur un VPS de test.
Étape 10 : mettre à jour selon un calendrier
mailcow se met à jour avec son propre script. Celui-ci récupère le nouveau code, effectue les migrations de mailcow.conf, télécharge les images à l’avance et redémarre les conteneurs dans l’ordre :
cd /opt/mailcow-dockerized
sudo ./update.sh --check # reports whether an update exists, changes nothing
sudo ./update.sh # applies itEffectuez d’abord une sauvegarde (étape 9), car il est difficile d’annuler une migration de schéma. Les mises à jour sont fréquentes et incluent des correctifs de sécurité pour les daemons exposés à Internet. Ne laissez donc pas un serveur de messagerie accumuler plusieurs mois de retard. Si une mise à jour laisse un conteneur en état unhealthy, sudo docker compose logs --tail=50 <service>-mailcow indique le daemon qui n’a pas redémarré correctement.
Une note sur le durcissement
mailcow exécute son propre service netfilter (netfilter-mailcow), qui bannit les adresses IP martelant les ports de messagerie et de webmail. La messagerie est donc protégée par défaut. Cela ne protège pas SSH sur l’hôte lui-même : le service reste exposé et continue de subir des attaques par force brute. Complétez cette configuration avec Fail2ban qui surveille le journal d’authentification SSH et une connexion reposant uniquement sur des clés. Protégez l’interface d’administration mailcow avec un mot de passe robuste et, dans l’idéal, ne l’exposez pas sur Internet ou placez-la derrière un VPN.
Modes d’échec, avec les chaînes exactes
Les messages restent en file d’attente et ne sont jamais remis. Exécutez sudo docker compose exec postfix-mailcow postqueue -p ou consultez la file d’attente des e-mails dans l’interface d’administration. Les entrées restent différées avec :
status=deferred (connect to gmail-smtp-in.l.google.com[142.250.x.x]:25: Connection timed out)Cela signifie que votre fournisseur bloque le port sortant 25 (étape 1). Aucune modification de configuration ne peut résoudre ce problème. Ouvrez un ticket. Il ne s’agit ni du DNS ni de TLS. L’indice est le mot timed out pour un MX distant sur le port 25.
Gmail classe tous les messages comme spam ou les rejette. Ouvrez le message dans Gmail, sélectionnez « Afficher l’original », puis consultez les résultats d’authentification. dkim=fail ou dkim=none signifie que votre enregistrement TXT dkim._domainkey est absent, incorrect ou pas encore propagé. Republiez exactement ce qu’affiche la page ARC/DKIM et attendez l’expiration du TTL. spf=fail signifie que les enregistrements SPF/MX ne couvrent pas votre adresse IP. L’alignement est essentiel : un seul contrôle en échec suffit pour que le message arrive dans les spams.
Rejet par les grands fournisseurs lors de la connexion. Les messages de rejet ou les journaux Postfix contiennent le rejet PTR de Gmail :
550-5.7.25 [10.0.0.10] The IP address sending this message does not have a PTR
550-5.7.25 record setup, or the corresponding forward DNS entry does not match
550 5.7.25 the sending IP. As a policy, Gmail does not accept messages from IPs
550 5.7.25 with missing PTR records.Le code 550 5.7.25 indique l’absence d’un reverse DNS ou une incohérence. Définissez le PTR de votre adresse IP sur mail.example.com chez le fournisseur (étape 2). L’enregistrement direct (A) et l’enregistrement inverse (PTR) doivent correspondre. Ils doivent tous deux désigner le même hôte que celui que mailcow présente aux autres serveurs.
Le navigateur affiche un avertissement de certificat qui ne disparaît jamais. Le conteneur acme-mailcow n’a pas réussi à obtenir un certificat valide. Consultez son journal :
sudo docker compose logs acme-mailcow | tail -n 40Une ligne telle que Cannot validate any hostnames, skipping Let's Encrypt for 1 hour. ou un échec du challenge signifie que le port 80 n’est pas accessible depuis Internet ou que l’enregistrement A ne pointe pas vers ce serveur. Vérifiez que mail.example.com se résout vers ce serveur, ouvrez les ports 80 et 443 dans le firewall de l’hôte et assurez-vous qu’aucun autre service n’écoute sur ces ports. Après avoir corrigé la cause, redémarrez le client avec sudo docker compose restart acme-mailcow au lieu d’attendre la fin du délai de reprise d’une heure.
FAQ
L’auto-hébergement de la messagerie en vaut-il vraiment la peine ?
Si vous voulez conserver la maîtrise de vos données, disposer d’alias illimités et garder un contrôle total, oui : mailcow vous fournit une stack professionnelle au prix d’un VPS. Mais la délivrabilité demande une attention constante : la réputation de l’IP, l’alignement DNS et la surveillance des blocklists ne sont jamais complètement réglés. Pour une adresse professionnelle critique, lorsque le fait qu’un seul message passe une journée dans le dossier spam de quelqu’un vous coûte cher, un fournisseur managé est le choix le plus pragmatique. Auto-hébergez votre messagerie si vous privilégiez le contrôle à la simplicité et si vous êtes réellement prêt à l’administrer. Si votre objectif réel est de garder vos données hors des serveurs d’un tiers plutôt que d’héberger spécifiquement votre messagerie, commencez par un service sur lequel personne d’autre n’a de droit de décision : une photothèque n’a aucun problème de délivrabilité, et notre comparatif de PhotoPrism et Immich détaille les seuils de RAM et les commandes de sauvegarde pour ce type d’installation sur un VPS comparable.
Comment savoir si le port sortant 25 est bloqué ?
Exécutez nc -vz -w 5 gmail-smtp-in.l.google.com 25 depuis le serveur. Le message « succeeded! » signifie que le port est ouvert ; un timed out après le délai d’attente signifie que votre fournisseur le bloque. C’est la raison la plus fréquente pour laquelle un serveur auto-hébergé peut recevoir des messages sans jamais pouvoir en envoyer, et le seul correctif consiste à demander à votre fournisseur d’ouvrir le port : aucune modification locale ne permet de contourner ce blocage.
Pourquoi mes messages arrivent-ils toujours dans le dossier spam de Gmail ?
Il s’agit presque toujours d’une chaîne d’authentification défaillante. Dans Gmail, utilisez « Show original » et recherchez spf=pass, dkim=pass et dmarc=pass. Un dkim=fail indique un enregistrement TXT dkim._domainkey absent ou incorrect ; une incohérence de PTR ou une nouvelle IP sans historique d’envoi nuit également à la délivrabilité. Commencez par obtenir 10/10 sur mail-tester.com, puis augmentez progressivement le volume d’envoi, de quelques messages par jour à un volume supérieur, au lieu d’envoyer un grand nombre de messages dès le premier jour.
Que dois-je sauvegarder exactement ?
Exécutez backup_and_restore.sh backup all et conservez l’ensemble hors du serveur. Cette commande sauvegarde vmail (les boîtes aux lettres), crypt (les clés qui permettent de les déchiffrer), la base de données MariaDB (domaines, utilisateurs, alias, paramètres), Redis, les données apprises par Rspamd et la file d’attente Postfix. Le volume crypt est souvent oublié. Sans lui, la sauvegarde vmail contient un texte chiffré illisible. Testez au moins une fois la restauration sur un serveur de test.
Puis-je exécuter mailcow sur un VPS de 2 GB ?
Pas dans de bonnes conditions. generate_config.sh propose de désactiver ClamAV en dessous d’environ 2.5 GiB, mais Rspamd, ClamAV, Dovecot et MariaDB se disputent malgré tout la mémoire. Vous subirez donc du swap et des arrêts pour dépassement de mémoire dès qu’il y aura une charge réelle. Considérez 6 GiB et 1 GiB de swap comme le minimum pour une installation stable destinée à un seul utilisateur, puis passez à 8 GiB dès que plus de deux personnes environ en dépendent.