Postfix Dovecot MySQL sur Ubuntu 22.04
Introduction
Ce guide vous accompagnera pas à pas dans la configuration d’un serveur de messagerie complet et sûr, en utilisant Postfix (SMTP), Dovecot (IMAP/POP3), MariaDB (base de données des utilisateurs) et Rspamd (antispam). Le serveur utilisera exclusivement des connexions chiffrées avec des certificats Let’s Encrypt.
À la fin, vous disposerez d’un serveur de messagerie professionnel avec :
- Domaines et utilisateurs virtuels gérés via base de données
- Chiffrement TLS obligatoire pour toutes les connexions
- Filtres antispam avancés
- Protection contre les attaques par force brute
- Prise en charge des filtres Sieve côté serveur
1. Prérequis et préparation du système
Exigences de base
Pour ce guide, vous aurez besoin de :
- Un VPS avec IP statique (je conseille Hetzner pour la fiabilité et les prix)
- Ubuntu 22.04 LTS installé
- Un domaine enregistré avec accès à la configuration DNS
- Au moins 2 Go de RAM (4 Go conseillés)
Configuration DNS
Avant de commencer, configurez correctement les enregistrements DNS de votre domaine :
# Enregistrement A pour le serveur mail
mail.exemple.com A [IP_VPS]
# Enregistrement MX pour le domaine
exemple.com MX 10 mail.exemple.com
# Enregistrement PTR (reverse DNS) — à configurer dans le panneau du fournisseur VPS
[IP_VPS] PTR mail.exemple.com
# Enregistrement SPF pour autoriser le serveur à envoyer du courrier
exemple.com TXT "v=spf1 mx -all"
Important : l’enregistrement PTR doit correspondre au nom d’hôte du serveur. Vérifiez avec :
hostname -f
# Doit retourner : mail.exemple.com
Installation des paquets
Mettons à jour le système et installons tous les composants nécessaires :
apt update && apt upgrade -y
apt install -y \
mariadb-server \
postfix postfix-pcre postfix-mysql \
dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd \
dovecot-mysql dovecot-sieve dovecot-managesieved \
rspamd redis-server \
certbot \
pwgen \
fail2ban \
ufw
Pendant l’installation de Postfix, sélectionnez « Internet Site » et saisissez votre domaine (exemple.com).
2. Certificats SSL/TLS avec Let’s Encrypt
Générons tout de suite les certificats SSL qui protégeront toutes les communications :
# On arrête temporairement les services qui utilisent le port 80
systemctl stop apache2 nginx
# On génère le certificat avec une clé RSA 4096 bits
certbot certonly --standalone --rsa-key-size 4096 -d mail.exemple.com
# On configure le renouvellement automatique avec redémarrage des services
cat > /etc/letsencrypt/cli.ini << EOF
post-hook = systemctl restart postfix dovecot
EOF
3. Configuration de la base de données MariaDB
Sécurisation de la base
Tout d’abord, sécurisons MariaDB :
mysql_secure_installation
# Répondez :
# - Set root password? [Y]
# - Remove anonymous users? [Y]
# - Disallow root login remotely? [Y]
# - Remove test database? [Y]
# - Reload privilege tables? [Y]
Création de la base et de l’utilisateur
Générons un mot de passe sécurisé pour l’utilisateur de la base :
# Génère un mot de passe de 30 caractères
pwgen -s1 30
# Exemple de sortie : rEfsoI2KSejLEHmDNvAYnVEHr8o1ig
Créons maintenant la base et les tables :
mysql -u root -p
-- Création base et utilisateur
CREATE DATABASE mailserver;
CREATE USER 'mailuser'@'localhost' IDENTIFIED BY 'rEfsoI2KSejLEHmDNvAYnVEHr8o1ig';
GRANT ALL PRIVILEGES ON mailserver.* TO 'mailuser'@'localhost';
FLUSH PRIVILEGES;
USE mailserver;
-- Table domaines
CREATE TABLE IF NOT EXISTS `virtual_domains` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Table utilisateurs
CREATE TABLE IF NOT EXISTS `virtual_users` (
`id` int(11) NOT NULL auto_increment,
`domain_id` int(11) NOT NULL,
`email` varchar(100) NOT NULL,
`password` varchar(150) NOT NULL,
`quota` bigint(20) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Table alias
CREATE TABLE IF NOT EXISTS `virtual_aliases` (
`id` int(11) NOT NULL auto_increment,
`domain_id` int(11) NOT NULL,
`source` varchar(100) NOT NULL,
`destination` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
EXIT;
Ajout de domaines et d’utilisateurs
Pour ajouter un domaine et un utilisateur, générons d’abord un mot de passe chiffré :
# Génère le mot de passe utilisateur
pwgen -s1 20
# Exemple : xK9mNp2Lq8Rt5Yw3Zb7
# Chiffre le mot de passe en SHA256
doveadm pw -s SHA256-CRYPT
# Saisissez le mot de passe quand demandé
# Exemple de sortie : {SHA256-CRYPT}$5$xvxyx8xOf5MSGsK.$zEBRszEg...
Ajoutons maintenant le domaine et l’utilisateur à la base :
mysql -u root -p mailserver
-- Ajoute le domaine
INSERT INTO virtual_domains (name) VALUES ('exemple.com');
-- Ajoute l’utilisateur (utilise le hash généré ci-dessus)
INSERT INTO virtual_users (domain_id, email, password)
VALUES (1, 'info@exemple.com', '{SHA256-CRYPT}$5$xvxyx8xOf5MSGsK.$zEBRszEg...');
-- Ajoute un alias
INSERT INTO virtual_aliases (domain_id, source, destination)
VALUES (1, 'postmaster@exemple.com', 'info@exemple.com');
EXIT;
4. Configuration de Postfix
Fichiers de mapping MySQL
Créons les fichiers qui permettent à Postfix d’interroger la base :
# Fichier : /etc/postfix/mysql-virtual-mailbox-domains.cf
cat > /etc/postfix/mysql-virtual-mailbox-domains.cf << EOF
user = mailuser
password = rEfsoI2KSejLEHmDNvAYnVEHr8o1ig
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'
EOF
# Fichier : /etc/postfix/mysql-virtual-mailbox-maps.cf
cat > /etc/postfix/mysql-virtual-mailbox-maps.cf << EOF
user = mailuser
password = rEfsoI2KSejLEHmDNvAYnVEHr8o1ig
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'
EOF
# Fichier : /etc/postfix/mysql-virtual-alias-maps.cf
cat > /etc/postfix/mysql-virtual-alias-maps.cf << EOF
user = mailuser
password = rEfsoI2KSejLEHmDNvAYnVEHr8o1ig
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'
EOF
# On met les bonnes permissions
chmod 640 /etc/postfix/mysql-*.cf
chown root:postfix /etc/postfix/mysql-*.cf
Configuration main.cf
Configurons Postfix en modifiant le fichier principal :
# Sauvegarde du fichier d’origine
cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
# Configuration de base
postconf -e "myhostname = mail.exemple.com"
postconf -e "mydomain = exemple.com"
postconf -e "myorigin = \$mydomain"
postconf -e "mydestination = localhost"
postconf -e "mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128"
# Domaines et boîtes virtuelles
postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf"
postconf -e "virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf"
postconf -e "virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf"
# Authentification SASL via Dovecot
postconf -e "smtpd_sasl_type = dovecot"
postconf -e "smtpd_sasl_path = private/auth"
postconf -e "smtpd_sasl_auth_enable = yes"
postconf -e "broken_sasl_auth_clients = yes"
# TLS/SSL
postconf -e "smtpd_tls_cert_file = /etc/letsencrypt/live/mail.exemple.com/fullchain.pem"
postconf -e "smtpd_tls_key_file = /etc/letsencrypt/live/mail.exemple.com/privkey.pem"
postconf -e "smtpd_tls_security_level = may"
postconf -e "smtpd_tls_auth_only = yes"
postconf -e "smtp_tls_security_level = may"
postconf -e "smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1"
postconf -e "smtpd_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1"
postconf -e "smtpd_tls_mandatory_ciphers = high"
postconf -e "tls_high_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305"
# Restrictions
postconf -e "smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination"
postconf -e "smtpd_relay_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination"
# Limites
postconf -e "message_size_limit = 52428800"
postconf -e "mailbox_size_limit = 0"
Configuration master.cf
Activons le port submission (587) pour l’envoi authentifié :
# On modifie /etc/postfix/master.cf
# On décommente et modifie les lignes suivantes :
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_tls_auth_only=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
5. Configuration de Dovecot
Création de l’utilisateur et du répertoire mail
# Création utilisateur et groupe pour les boîtes virtuelles
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/vmail -m
chown -R vmail:vmail /var/vmail
Configuration de l’authentification
Modifions /etc/dovecot/conf.d/10-auth.conf :
# Mécanismes d’authentification
auth_mechanisms = plain login
# Désactive l’authentification en clair sans TLS
disable_plaintext_auth = yes
# Commenter la ligne auth-system et décommenter auth-sql
#!include auth-system.conf.ext
!include auth-sql.conf.ext
Configuration SQL
Créons /etc/dovecot/dovecot-sql.conf.ext :
driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=rEfsoI2KSejLEHmDNvAYnVEHr8o1ig
default_pass_scheme = SHA256-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u'
user_query = SELECT email as user,
'vmail' as uid, 'vmail' as gid,
'/var/vmail/%d/%n' as home,
'*:storage=1G' as quota_rule
FROM virtual_users WHERE email='%u'
iterate_query = SELECT email AS user FROM virtual_users
Configuration Mail Location
Modifions /etc/dovecot/conf.d/10-mail.conf :
mail_location = maildir:~/Maildir
mail_uid = vmail
mail_gid = vmail
first_valid_uid = 5000
last_valid_uid = 5000
Configuration SSL
Modifions /etc/dovecot/conf.d/10-ssl.conf :
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.exemple.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.exemple.com/privkey.pem
Configuration Master Services
Modifions /etc/dovecot/conf.d/10-master.conf :
service imap-login {
inet_listener imap {
port = 143
}
inet_listener imaps {
port = 993
ssl = yes
}
}
service pop3-login {
inet_listener pop3 {
port = 0 # Désactivé
}
inet_listener pop3s {
port = 0 # Désactivé
}
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
unix_listener auth-userdb {
mode = 0600
user = vmail
}
}
service auth-worker {
user = vmail
}
Activation de Sieve
Modifions /etc/dovecot/conf.d/20-lmtp.conf :
protocol lmtp {
mail_plugins = $mail_plugins sieve
}
Et /etc/dovecot/conf.d/90-sieve.conf :
plugin {
sieve = file:~/sieve;active=~/.dovecot.sieve
sieve_global_path = /var/vmail/sieve/default.sieve
sieve_dir = ~/sieve
sieve_max_script_size = 1M
}
6. Configuration de Rspamd (antispam)
Rspamd est un système antispam avancé qui protégera le serveur contre le spam et les malwares.
Configuration de base
# On configure rspamd pour qu’il s’intègre à Postfix
cat > /etc/rspamd/local.d/worker-controller.inc << EOF
password = "\$2\$zy8npwwgqbpgo5ujnug6of3zy3rgpbmj\$k6mmm9xe3jugxr1bii4o5gxjfhqjjh4pg3iyhka4rq3479bjqzny";
enable_password = "\$2\$zy8npwwgqbpgo5ujnug6of3zy3rgpbmj\$k6mmm9xe3jugxr1bii4o5gxjfhqjjh4pg3iyhka4rq3479bjqzny";
EOF
# Configuration milter
cat > /etc/rspamd/local.d/worker-proxy.inc << EOF
bind_socket = "127.0.0.1:11332";
milter = yes;
timeout = 120s;
upstream "local" {
default = yes;
self_scan = yes;
}
EOF
# On ajoute rspamd à Postfix
postconf -e "smtpd_milters = inet:127.0.0.1:11332"
postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"
postconf -e "milter_default_action = accept"
# On redémarre rspamd
systemctl restart rspamd
Signature DKIM
# On génère la clé DKIM
mkdir -p /var/lib/rspamd/dkim/
rspamadm dkim_keygen -b 2048 -s mail -k /var/lib/rspamd/dkim/mail.key > /var/lib/rspamd/dkim/mail.txt
chown -R _rspamd:_rspamd /var/lib/rspamd/dkim
# On configure DKIM
cat > /etc/rspamd/local.d/dkim_signing.conf << EOF
selector = "mail";
path = "/var/lib/rspamd/dkim/\$selector.key";
allow_username_mismatch = true;
EOF
# L’enregistrement DNS DKIM à ajouter se trouve dans :
cat /var/lib/rspamd/dkim/mail.txt
7. Configuration de Fail2ban
Protégeons le serveur contre les attaques par force brute :
# Création d’un jail pour Postfix
cat > /etc/fail2ban/jail.d/postfix.conf << EOF
[postfix-sasl]
enabled = true
filter = postfix-sasl
action = iptables-multiport[name=postfix-sasl, port="25,587,465", protocol=tcp]
logpath = /var/log/mail.log
maxretry = 3
bantime = 3600
EOF
# Jail pour Dovecot
cat > /etc/fail2ban/jail.d/dovecot.conf << EOF
[dovecot]
enabled = true
filter = dovecot
action = iptables-multiport[name=dovecot, port="143,993,110,995", protocol=tcp]
logpath = /var/log/mail.log
maxretry = 3
bantime = 3600
EOF
# Redémarrage de fail2ban
systemctl restart fail2ban
8. Configuration du pare-feu
# Configuration d’UFW
ufw allow 22/tcp # SSH
ufw allow 25/tcp # SMTP
ufw allow 587/tcp # Submission
ufw allow 143/tcp # IMAP
ufw allow 993/tcp # IMAPS
ufw allow 80/tcp # HTTP (pour Let’s Encrypt)
ufw allow 443/tcp # HTTPS
# Activation du pare-feu
ufw enable
9. Tests et vérification
Test de la base
# Test de mapping Postfix
postmap -q exemple.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
# Sortie attendue : 1
postmap -q info@exemple.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
# Sortie attendue : 1
postmap -q postmaster@exemple.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf
# Sortie attendue : info@exemple.com
Test des services
# Vérification configuration Postfix
postfix check
# Vérification configuration Dovecot
dovecot -n
# Test connexion SMTP
telnet localhost 25
EHLO test
# Doit afficher STARTTLS et AUTH
# Test IMAP
telnet localhost 143
a1 LOGIN info@exemple.com password
# Doit s’authentifier correctement
Test SSL/TLS
# Test certificat SMTP
openssl s_client -connect mail.exemple.com:587 -starttls smtp
# Test certificat IMAP
openssl s_client -connect mail.exemple.com:993
10. Configuration des clients de messagerie
Pour configurer un client mail (Thunderbird, Outlook, etc.), utilisez ces paramètres :
- Serveur IMAP : mail.exemple.com, Port 993, SSL/TLS
- Serveur SMTP : mail.exemple.com, Port 587, STARTTLS
- Nom d’utilisateur : adresse email complète (info@exemple.com)
- Mot de passe : le mot de passe de l’utilisateur
- Authentification : Mot de passe normal
11. Maintenance et monitoring
Fichiers de logs
Les logs principaux à surveiller :
# Log mail général
tail -f /var/log/mail.log
# Log d’erreurs
tail -f /var/log/mail.err
# Log rspamd
tail -f /var/log/rspamd/rspamd.log
# Statistiques rspamd
rspamc stat
Sauvegarde
# Script de sauvegarde de la base
#!/bin/bash
mysqldump mailserver > /backup/mailserver-$(date +%Y%m%d).sql
# Sauvegarde des boîtes
rsync -av /var/vmail/ /backup/vmail/
# Sauvegarde des configurations
tar czf /backup/mail-config-$(date +%Y%m%d).tar.gz \
/etc/postfix /etc/dovecot /etc/rspamd
Mises à jour
# Mise à jour sûre du système
apt update
apt upgrade -y
systemctl restart postfix dovecot rspamd
Résolution des problèmes courants
Erreur « Relay access denied »
Vérifiez que l’utilisateur est bien authentifié et que le domaine est correctement configuré dans la base.
Certificats qui ne fonctionnent pas
Vérifiez les permissions et les chemins des certificats. Dovecot nécessite le caractère < avant le chemin.
Mail classé en spam
Assurez-vous d’avoir correctement configuré SPF, DKIM et DMARC. Vérifiez aussi l’enregistrement PTR.
Conclusion
Vous disposez maintenant d’un serveur mail complet et sûr. N’oubliez pas de :
- Surveiller régulièrement les logs
- Maintenir le système à jour
- Faire des sauvegardes régulières
- Tester périodiquement la délivrabilité
- Renouveler les certificats SSL avant leur expiration
Pour une sécurité supplémentaire, envisagez la mise en place complète des enregistrements DNS SPF, DKIM et DMARC pour améliorer la réputation de votre serveur.