~/blog/fr/self-hosted-email-postfix-dovecot
Faire tourner votre propre serveur mail : Postfix, Dovecot et DKIM

L’auto-hébergement d’email a une réputation, et elle est en grande partie méritée : c’est le seul service où bien régler le logiciel est la moitié facile. La moitié difficile consiste à convaincre les serveurs mail de tout le monde que vous n’êtes pas un spammeur.
Je fais tourner le mien sur un petit VPS. Voici la pile complète, et les éléments qui décident réellement si votre courrier arrive.
Les composants
Quatre pièces mobiles, et il vaut la peine de savoir laquelle vous déboguez avant de commencer :
- Postfix — le MTA. Accepte le mail depuis l’internet sur le port 25, envoie votre courrier sortant, et remet tout ce qui est local à l’agent de livraison.
- Dovecot — le MDA et serveur IMAP. Range le mail dans Maildir, le sert à votre client en IMAP, et fait aussi office de fournisseur SASL pour que Postfix puisse authentifier la submission.
- OpenDKIM — signe le courrier sortant avec une clé dans votre DNS, pour que le destinataire puisse prouver que c’était bien vous.
- Roundcube — webmail, si vous voulez un navigateur dans la boucle.
Il vous faut aussi des choses qui ne sont pas du logiciel : le port 25 en sortie (beaucoup de fournisseurs le bloquent, et certains le débloquent sur demande), un enregistrement reverse DNS que vous contrôlez, et un domaine.
Avant d’installer quoi que ce soit
Cet enregistrement PTR n’est pas optionnel. Si l’IP de votre serveur résout vers quelque chose comme vps-1234.hosting-provider.net, vous pouvez avoir un SPF et un DKIM impeccables et vous serez quand même filtré — un PTR générique d’hébergeur est le signal de spam le plus fort qui existe. Configurez-le sur mail.example.org pour qu’il corresponde à votre nom HELO, et faites-le avant de commencer à envoyer.
Postfix
apt install postfix postfix-pcre dovecot-core dovecot-imapd opendkim opendkim-tools
Les réglages qui comptent, extraits d’un main.cf qui fonctionne :
myhostname = mail.example.org
mydomain = example.org
myorigin = $mydomain
mydestination = $myhostname, $mydomain, localhost.$mydomain, localhost
inet_protocols = ipv4
home_mailbox = Maildir/
# Rejeter les tentatives de relais, mais laisser passer les utilisateurs authentifiés
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
# TLS
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.org/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.org/privkey.pem
smtpd_tls_security_level = may
# Passer le tout à OpenDKIM
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
smtpd_relay_restrictions est la ligne qui vous évite de devenir un open relay. Ratez-la et vous serez trouvé et abusé en quelques jours — un open relay est le moyen le plus rapide de perdre définitivement la réputation de votre IP, et cela arrive avant même que vous n’ayez envoyé un seul message légitime. Lisez-la de gauche à droite : relayer pour la machine locale, relayer pour les clients authentifiés, et refuser tout autre destinataire hors de vos propres domaines. defer_unauth_destination refuse avec un 4xx temporaire ; reject_unauth_destination est la variante 5xx définitive. Rien d’autre n’est relayé.
smtpd_tls_security_level = may est du TLS opportuniste. encrypt est plus strict et refusera les connexions des expéditeurs qui ne savent pas faire de TLS — ce qui, en pratique, signifie perdre le courrier d’expéditeurs mal configurés sur l’internet, donc la plupart des gens qui font tourner un petit serveur utilisent may et laissent les règles de sortie faire le travail d’application.
Dovecot
Dovecot sert l’IMAP en TLS (993) et fournit le socket SASL que Postfix utilise à la submission (587) :
protocols = imap pop3
ssl = required
ssl_min_protocol = TLSv1.2
ssl_server_cert_file = /etc/letsencrypt/live/mail.example.org/fullchain.pem
ssl_server_key_file = /etc/letsencrypt/live/mail.example.org/privkey.pem
mail_driver = maildir
mail_path = %{home}/Maildir
mail_privileged_group = mail
ssl = required plutôt que yes : il refuse le plaintext au lieu de simplement annoncer STARTTLS. Pour les connexions IMAP, cela compte — un client qui retombe sur des mots de passe en clair parce qu’il peut est exactement le client qu’on ne veut pas accommoder.
Ici, les utilisateurs mail sont des comptes système authentifiés via PAM : créer une boîte, c’est créer un utilisateur Linux, sans shell de connexion :
adduser --shell /usr/sbin/nologin mailuser
(Avec des utilisateurs virtuels dans un passwd-file, doveadm pw -s SHA512-CRYPT génère le hash à y stocker.) Pour un compte existant :
usermod -s /usr/sbin/nologin mailuser
Un compte mail qui peut se connecter en SSH transforme un mot de passe fuité en compromission totale. Les comptes mail ne devraient jamais avoir de shell.
OpenDKIM
opendkim-genkey -b 2048 -d example.org -s mail -D /etc/opendkim/keys/example.org
Cela génère mail.private et un mail.txt contenant la moitié publique. Pointez OpenDKIM vers eux :
Domain example.org
Selector mail
KeyFile /etc/opendkim/keys/example.org/mail.private
Socket inet:8891@localhost
Canonicalization relaxed/simple
relaxed/simple est le choix courant : l’en-tête relaxed tolère les petites réécritures d’en-têtes qui surviennent en transit, et le corps simple est strict, donc un corps modifié n’importe où est détectable. Signer avec une canonisation d’en-tête simple est un excellent moyen de voir vos signatures valides rejetées — chaque saut de transfert réécrit les en-têtes.
Les enregistrements DNS décident de tout
Cinq enregistrements. Quatre d’entre eux sont la raison pour laquelle votre mail arrive ou n’arrive pas.
| Enregistrement | Valeur |
|---|---|
MX |
10 mail.example.org. |
mail.example.org A |
l’IP de votre serveur |
_dmarc TXT |
v=DMARC1; p=quarantine; pct=100 |
mail._domainkey TXT |
v=DKIM1; h=sha256; k=rsa; p=<public key from mail.txt> |
root TXT (SPF) |
v=spf1 ip4:<your server IP> -all |
Deux détails sur lesquels s’arrêter. Dans SPF, -all signifie hard fail — tout serveur absent de votre liste n’est explicitement pas autorisé à envoyer en votre nom. C’est ce que vous voulez une fois que vous avez confiance dans votre liste, et c’est pourquoi un enregistrement SPF non maintenu provoque une perte silencieuse de courrier. Et DMARC p=quarantine demande aux destinataires de mettre au rebut le courrier qui échoue à la fois à SPF et à DKIM, ce qui n’a de sens qu’une fois les deux premiers enregistrements corrects.
Commencez par p=none, surveillez les rapports agrégés pendant une semaine, puis resserrez. Passer directement à p=reject sur un domaine qui a d’autres expéditeurs — une plateforme de newsletter, un CRM, votre propre laptop — se met silencieusement à jeter du courrier légitime, et rien dans les logs ne vous le dira.
Roundcube
Roundcube est une application PHP ; avec PHP-FPM et un vhost, c’est une installation de dix minutes, et il devrait avoir son propre sous-domaine avec son propre certificat. L’important, c’est la config. Dans Roundcube 1.6, imap_host vaut ssl://mail.example.org:993 et smtp_host vaut tls://mail.example.org:587 (les versions plus anciennes les appelaient default_host et smtp_server, avec un smtp_port à part). Donnez-lui une connexion IMAP en TLS et ne le laissez jamais retomber en plaintext.
Vérifier que cela fonctionne réellement
Ne faites pas confiance à « le mail est parti ».
dig +short MX example.org
dig +short TXT example.org
dig +short TXT mail._domainkey.example.org
dig +short TXT _dmarc.example.org
dig +short -x <your server IP> # must return mail.example.org
openssl s_client -connect mail.example.org:993 -servername mail.example.org </dev/null 2>/dev/null | openssl x509 -noout -dates
Envoyez ensuite un vrai message à une adresse Gmail et regardez Authentication-Results dans les en-têtes avec lesquels il revient. Les trois spf=pass, dkim=pass, dmarc=pass réunis sont la seule chose qui mérite d’être appelée un succès.
Pièges
- Pas de PTR, ou un PTR d’hébergeur. Configurez-le en premier. Rien d’autre ne compense.
- Un open relay. Vérifiez
smtpd_relay_restrictions, puis vérifiez depuis l’extérieur :telnet mail.example.org 25et essayez de relayer vers un domaine sans rapport. Cela doit être refusé. - Sélecteur non concordant. Le nom de l’enregistrement DNS doit être
<selector>._domainkey.<domain>et doit correspondre auSelectord’OpenDKIM. Une signature introuvable échoue silencieusement — le mail part, il n’arrive simplement pas. - Clé trop petite. 2048 bits RSA au minimum ; les clés de 1024 bits sont considérées comme suspectes.
- Des comptes avec un shell.
nologin, toujours. - Port 25 en sortie bloqué par votre fournisseur. Les symptômes ressemblent à une file pleine de courrier différé. Vérifiez
mailqavant de déboguer quoi que ce soit d’autre. - Les réglages SSL par défaut de Dovecot qui changent d’une version à l’autre. Relisez la config après les mises à niveau majeures au lieu de faire confiance à votre ancien fichier — Dovecot 2.4 a renommé plusieurs directives, donc une config inchangée n’est pas forcément la même config.
Est-ce que ça vaut le coup ?
Pour le prix d’un petit VPS, oui — avec une réserve. Vous passerez un après-midi sur le DNS et une soirée sur la délivrabilité, et vous apprendrez plus sur le fonctionnement réel de l’email qu’une décennie à utiliser le relais SMTP de quelqu’un d’autre ne vous l’aurait appris. Ce que vous obtenez, c’est un serveur mail que personne ne peut rate-limiter, suspendre ou lire.
S’il doit fonctionner pour demain, utilisez un relais. Si vous voulez le comprendre, hébergez-le.