Gérer les domaines, comptes email et alias à la main dans une base SQL fonctionne très bien. Du moins jusqu’au jour où l’on ajoute un domaine en urgence, que l’on oublie une requête, et que Postfix vous regarde avec le mépris silencieux d’un MTA contrarié.
PostfixAdmin règle ce problème proprement. Il fournit une interface web pour administrer les domaines virtuels, les boîtes mail, les alias et certains paramètres liés à Postfix. Il s’intègre avec Postfix, Dovecot ou Courier, et une base MySQL, MariaDB, PostgreSQL ou SQLite.
Dans ce guide, nous allons installer PostfixAdmin sur un serveur moderne avec Nginx, PHP-FPM et MariaDB. L’objectif n’est pas seulement de “faire marcher” l’interface. L’objectif est de l’installer proprement, avec des chemins maintenables, des permissions correctes, une configuration locale séparée et une procédure de mise à jour simple.
/more
Architecture cible
Voici l’architecture retenue :
Internet
↓ HTTPS
Nginx
↓ PHP-FPM
PostfixAdmin
↓ MariaDB
Base postfix
↓
Postfix + Dovecot
PostfixAdmin ne remplace ni Postfix ni Dovecot. Il administre les données utilisées par votre serveur mail. Postfix continue de recevoir, router et livrer les messages. Dovecot continue de gérer IMAP, POP3, LMTP et l’authentification des utilisateurs.
PostfixAdmin devient donc le panneau d’administration de vos domaines et comptes email. C’est plus confortable qu’une série de requêtes SQL tapées à la main, surtout lorsque le serveur héberge plusieurs domaines.
Ce que PostfixAdmin permet de gérer
- les domaines virtuels ;
- les boîtes mail ;
- les alias ;
- les quotas, si votre pile mail les utilise ;
- les administrateurs de domaine ;
- les messages d’absence, selon votre configuration ;
- certains paramètres DKIM dans les versions récentes ;
- les connexions utilisateur, avec TOTP et mots de passe applicatifs selon la version installée.
En revanche, PostfixAdmin ne configure pas magiquement toute votre pile mail. Il faut encore que Postfix et Dovecot utilisent la même base de données, les mêmes schémas et les bons fichiers de requêtes SQL.
Pré-requis
Ce guide part du principe que vous avez déjà :
- un serveur Linux administrable en SSH ;
- Nginx installé ;
- PHP-FPM installé ;
- MariaDB ou MySQL installé ;
- Postfix installé ;
- Dovecot installé si vous gérez IMAP, POP3 ou LMTP ;
- un certificat TLS valide pour le sous-domaine PostfixAdmin ;
- un accès root ou sudo.
Dans les exemples, j’utilise les valeurs suivantes :
pfa.example.com
/srv/postfixadmin
/var/vmail
postfix
postfixadmin
php8.3-fpmLangage du code : JavaScript (javascript)
Remplacez évidemment example.com, les chemins et les versions PHP par ceux de votre serveur.
Installer les paquets nécessaires
Installez les dépendances de base :
sudo apt update
sudo apt install \
curl \
unzip \
tar \
mariadb-client \
mariadb-server \
nginx \
php8.3-fpm \
php8.3-cli \
php8.3-common \
php8.3-curl \
php8.3-imap \
php8.3-intl \
php8.3-mbstring \
php8.3-mysql \
php8.3-readline \
php8.3-sqlite3 \
php8.3-xml \
php8.3-zipLangage du code : CSS (css)
Si votre serveur utilise PHP 8.4, adaptez simplement les paquets et le socket PHP-FPM. Évitez en revanche de rester sur une vieille version de PHP pour une interface d’administration exposée en HTTPS. Une interface mail périmée, c’est une invitation avec buffet.
Vérifiez la version de PHP :
php -v
Vérifiez aussi le socket PHP-FPM disponible :
ls -lah /run/php/
Vous devriez voir un socket du type :
/run/php/php8.3-fpm.sock
Créer le sous-domaine PostfixAdmin
Je conseille d’utiliser un sous-domaine dédié. C’est plus clair, plus simple à protéger, et plus facile à isoler dans Nginx.
Dans votre DNS, créez un enregistrement :
Type : A
Nom : pfa
IPv4 : 203.0.113.10Langage du code : CSS (css)
Vous obtenez donc :
pfa.example.comLangage du code : CSS (css)
Si vous utilisez Cloudflare, le proxy orange peut fonctionner pour cette interface web. Toutefois, gardez en tête que PostfixAdmin est une interface d’administration. Ajoutez une restriction IP, une authentification forte ou une protection complémentaire si l’interface n’a pas besoin d’être publique.
Créer la base MariaDB pour PostfixAdmin
Connectez-vous à MariaDB :
sudo mariadb
Créez la base et l’utilisateur applicatif. Utilisez évidemment un mot de passe unique.
CREATE DATABASE postfix
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
CREATE USER 'postfixadmin'@'localhost'
IDENTIFIED BY 'CHANGE_ME_WITH_A_LONG_RANDOM_PASSWORD';
GRANT ALL PRIVILEGES ON postfix.* TO 'postfixadmin'@'localhost';
FLUSH PRIVILEGES;Langage du code : JavaScript (javascript)
Quittez MariaDB :
EXIT;Langage du code : PHP (php)
Testez la connexion avec l’utilisateur créé :
mariadb -u postfixadmin -p postfix
Si la connexion fonctionne, quittez la session :
EXIT;Langage du code : PHP (php)
Dans une installation plus stricte, vous pouvez aussi créer un utilisateur SQL séparé en lecture seule pour Postfix et Dovecot. PostfixAdmin garde alors les droits d’écriture, tandis que Postfix et Dovecot ne font que lire les domaines, alias, boîtes et mots de passe.
sudo mariadb
CREATE USER 'postfix_reader'@'localhost'
IDENTIFIED BY 'CHANGE_ME_WITH_ANOTHER_LONG_RANDOM_PASSWORD';
GRANT SELECT ON postfix.* TO 'postfix_reader'@'localhost';
FLUSH PRIVILEGES;
EXIT;Langage du code : PHP (php)
Ce n’est pas obligatoire pour démarrer, mais c’est plus propre sur un serveur exposé.
Télécharger la dernière version stable de PostfixAdmin
Installez PostfixAdmin dans /srv/postfixadmin avec une structure versionnée. Ainsi, les mises à jour deviennent plus simples, car chaque version vit dans son propre répertoire.
sudo install -d -o root -g root -m 0755 /srv/postfixadmin/releases
Récupérez le dernier tag publié sur GitHub :
Besoin d'un coup de main ?
Ce bug qui traîne depuis des semaines, ce plugin qui casse votre mise en page, cette fonctionnalité que personne n'arrive à implémenter proprement — c'est exactement ce que je règle au quotidien depuis 20 ans.
Parlons de votre problème →LATEST_TAG="$(curl -fsSL https://api.github.com/repos/postfixadmin/postfixadmin/releases/latest | grep '"tag_name":' | cut -d '"' -f4)"
echo "$LATEST_TAG"Langage du code : PHP (php)
Téléchargez et extrayez l’archive :
cd /tmp
curl -fsSL \
-o postfixadmin.tar.gz \
"https://github.com/postfixadmin/postfixadmin/archive/refs/tags/${LATEST_TAG}.tar.gz"
sudo install -d -o root -g root -m 0755 "/srv/postfixadmin/releases/${LATEST_TAG}"
sudo tar -xzf postfixadmin.tar.gz \
-C "/srv/postfixadmin/releases/${LATEST_TAG}" \
--strip-components=1Langage du code : JavaScript (javascript)
Créez un lien symbolique current vers la version active :
sudo ln -sfn "/srv/postfixadmin/releases/${LATEST_TAG}" /srv/postfixadmin/currentLangage du code : JavaScript (javascript)
Vérifiez la structure :
ls -lah /srv/postfixadmin/
ls -lah /srv/postfixadmin/current/
Installer les dépendances Composer
Depuis PostfixAdmin 4.x, l’installation des dépendances passe par le script install.sh. Il installe Composer localement si nécessaire, puis télécharge les dépendances PHP.
cd /srv/postfixadmin/current
sudo /bin/bash install.sh
Le script doit créer ou utiliser le répertoire templates_c, nécessaire au cache Smarty. Nous allons ensuite fixer les permissions proprement.
Configurer PostfixAdmin avec config.local.php
Ne modifiez pas config.inc.php directement. Ce fichier appartient à l’application et sera remplacé lors des mises à jour. Placez vos réglages locaux dans config.local.php.
sudo nano /srv/postfixadmin/current/config.local.php
Ajoutez une configuration minimale :
<?php
$CONF['configured'] = true;
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfixadmin';
$CONF['database_password'] = 'CHANGE_ME_WITH_A_LONG_RANDOM_PASSWORD';
$CONF['database_name'] = 'postfix';
$CONF['encrypt'] = 'dovecot:SHA512';
$CONF['default_aliases'] = array(
'abuse' => 'abuse@example.com',
'hostmaster' => 'hostmaster@example.com',
'postmaster' => 'postmaster@example.com',
'webmaster' => 'webmaster@example.com',
);
$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'NO';
$CONF['quota'] = 'YES';
$CONF['used_quotas'] = 'NO';
$CONF['fetchmail'] = 'NO';
$CONF['footer_text'] = 'Return to admin';
$CONF['footer_link'] = 'https://pfa.example.com/';Langage du code : HTML, XML (xml)
Adaptez les alias par défaut à votre domaine. Si vous gérez plusieurs domaines, vous pourrez ajuster ces réglages ensuite depuis l’interface ou votre configuration.
La ligne $CONF['encrypt'] = 'dovecot:SHA512'; indique à PostfixAdmin de générer des mots de passe compatibles avec Dovecot. Vérifiez que votre configuration Dovecot utilise bien un schéma cohérent avec ce choix.
Générer le mot de passe setup_password
PostfixAdmin demande un setup_password pour initialiser ou mettre à jour l’installation depuis setup.php. Générez un hash PHP :
php -r "echo password_hash('CHANGE_ME_SETUP_PASSWORD', PASSWORD_DEFAULT) . PHP_EOL;"Langage du code : JavaScript (javascript)
Copiez le hash généré, puis ajoutez-le dans config.local.php :
$CONF['setup_password'] = '$2y$10$REPLACE_WITH_THE_GENERATED_HASH';Langage du code : PHP (php)
Vous devrez saisir le mot de passe original, pas le hash, dans l’interface setup.php.
Appliquer les permissions correctes
PostfixAdmin n’a pas besoin d’écrire dans tous ses fichiers. Le serveur web doit surtout pouvoir lire l’application et écrire dans templates_c.
sudo chown -R root:root /srv/postfixadmin/releases
sudo find /srv/postfixadmin/releases -type d -exec chmod 0755 {} \;
sudo find /srv/postfixadmin/releases -type f -exec chmod 0644 {} \;
sudo chown root:www-data /srv/postfixadmin/current/config.local.php
sudo chmod 0640 /srv/postfixadmin/current/config.local.php
sudo install -d -o www-data -g www-data -m 0750 /srv/postfixadmin/current/templates_c
Si install.sh a déjà créé templates_c, corrigez simplement son propriétaire :
sudo chown -R www-data:www-data /srv/postfixadmin/current/templates_c
sudo chmod 0750 /srv/postfixadmin/current/templates_c
Configurer Nginx pour PostfixAdmin
Créez un vhost dédié :
sudo nano /etc/nginx/sites-available/pfa.example.com.conf
Voici une configuration propre pour Nginx et PHP-FPM :
server {
listen 80;
listen [::]:80;
server_name pfa.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name pfa.example.com;
root /srv/postfixadmin/current/public;
index index.php;
ssl_certificate /etc/letsencrypt/live/pfa.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pfa.example.com/privkey.pem;
access_log /var/log/nginx/pfa.example.com.access.log;
error_log /var/log/nginx/pfa.example.com.error.log warn;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "same-origin" always;
add_header X-Robots-Tag "noindex, nofollow, noarchive" always;
client_max_body_size 10m;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /setup.php {
allow 203.0.113.50;
deny all;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param HTTPS on;
fastcgi_hide_header X-Powered-By;
}
location ~ \.php$ {
try_files $uri =404;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param HTTPS on;
fastcgi_hide_header X-Powered-By;
}
location ~* \.(?:css|js|gif|ico|jpg|jpeg|png|svg|webp|woff|woff2)$ {
access_log off;
expires 7d;
try_files $uri =404;
}
location ~ /\.(?!well-known) {
deny all;
}
}Langage du code : PHP (php)
Remplacez pfa.example.com, les chemins de certificats, le socket PHP-FPM et l’adresse IP autorisée pour setup.php.
La restriction IP sur setup.php est volontaire. Cette page sert à initialiser ou mettre à jour la base. Elle n’a aucune raison d’être accessible à tout Internet.
Activez le vhost :
sudo ln -s /etc/nginx/sites-available/pfa.example.com.conf /etc/nginx/sites-enabled/pfa.example.com.conf
Testez et rechargez Nginx :
sudo nginx -t
sudo systemctl reload nginx
Installer le certificat TLS
Si vous utilisez Certbot :
sudo certbot certonly --nginx -d pfa.example.comLangage du code : CSS (css)
Rechargez ensuite Nginx :
sudo nginx -t
sudo systemctl reload nginx
Si vous utilisez acme.sh, installez les certificats dans un chemin stable, puis rechargez Nginx après chaque renouvellement :
acme.sh --install-cert -d pfa.example.com \
--key-file /etc/letsencrypt/live/pfa.example.com/privkey.pem \
--fullchain-file /etc/letsencrypt/live/pfa.example.com/fullchain.pem \
--reloadcmd "systemctl reload nginx"Langage du code : JavaScript (javascript)
Lancer l’assistant setup.php
Ouvrez l’assistant dans votre navigateur :
https://pfa.example.com/setup.phpLangage du code : JavaScript (javascript)
Saisissez le mot de passe setup_password en clair, celui que vous avez utilisé avant de générer le hash. PostfixAdmin vérifie alors la configuration, crée ou met à jour les tables SQL, puis propose de créer le premier superadmin.
Créez votre compte superadmin avec une adresse email réelle, par exemple :
admin@example.comLangage du code : CSS (css)
Ensuite, connectez-vous à l’interface :
https://pfa.example.com/login.phpLangage du code : JavaScript (javascript)
Une fois l’installation terminée, vous pouvez renforcer encore l’accès à setup.php. Par exemple, vous pouvez le bloquer complètement dans Nginx et le réactiver seulement lors des mises à jour.
location = /setup.php {
deny all;
}
Gardez toutefois en tête que certaines mises à jour de PostfixAdmin peuvent nécessiter de relancer setup.php pour appliquer les migrations de base de données.
Créer un domaine et une première boîte mail
Depuis l’interface PostfixAdmin, commencez par créer un domaine :
- allez dans Domain List ;
- ajoutez
example.com; - définissez le nombre maximal d’alias ;
- définissez le nombre maximal de boîtes ;
- activez le domaine.
Créez ensuite une boîte mail :
- adresse :
contact@example.com; - mot de passe fort ;
- quota adapté ;
- statut actif.
Ajoutez enfin quelques alias utiles :
postmaster@example.com → contact@example.com
abuse@example.com → contact@example.com
webmaster@example.com → contact@example.comLangage du code : CSS (css)
Ces alias standards sont utiles pour la délivrabilité, les signalements et les contacts techniques. Ce n’est pas glamour, mais le mail n’a jamais prétendu être une fête foraine.
Brancher Postfix sur les tables PostfixAdmin
Postfix doit maintenant lire les domaines, alias et boîtes mail créés par PostfixAdmin. Les noms de tables et colonnes dépendent du schéma PostfixAdmin, mais une configuration classique utilise les fichiers SQL suivants :
/etc/postfix/sql/mysql_virtual_domains_maps.cf/etc/postfix/sql/mysql_virtual_alias_maps.cf/etc/postfix/sql/mysql_virtual_mailbox_maps.cf/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf
Créez le répertoire :
sudo install -d -o root -g postfix -m 0750 /etc/postfix/sql
Créez la requête des domaines :
sudo nano /etc/postfix/sql/mysql_virtual_domains_maps.cf
user = postfix_reader
password = CHANGE_ME_WITH_ANOTHER_LONG_RANDOM_PASSWORD
hosts = 127.0.0.1
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'Langage du code : JavaScript (javascript)
Créez la requête des alias :
sudo nano /etc/postfix/sql/mysql_virtual_alias_maps.cf
user = postfix_reader
password = CHANGE_ME_WITH_ANOTHER_LONG_RANDOM_PASSWORD
hosts = 127.0.0.1
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'Langage du code : PHP (php)
Créez la requête des boîtes mail :
sudo nano /etc/postfix/sql/mysql_virtual_mailbox_maps.cf
user = postfix_reader
password = CHANGE_ME_WITH_ANOTHER_LONG_RANDOM_PASSWORD
hosts = 127.0.0.1
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'Langage du code : JavaScript (javascript)
Appliquez les permissions :
sudo chown root:postfix /etc/postfix/sql/mysql_*.cf
sudo chmod 0640 /etc/postfix/sql/mysql_*.cf
Testez les requêtes avec postmap :
sudo postmap -q example.com mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf
sudo postmap -q contact@example.com mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf
sudo postmap -q postmaster@example.com mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cfLangage du code : JavaScript (javascript)
Si ces commandes ne retournent rien, ne redémarrez pas Postfix au hasard. Vérifiez d’abord le contenu des tables dans MariaDB, les mots de passe SQL et les noms de colonnes.
Ajoutez ensuite les maps dans /etc/postfix/main.cf :
virtual_mailbox_domains = mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf
virtual_alias_maps = mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf
virtual_mailbox_base = /var/vmail
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000Langage du code : JavaScript (javascript)
Rechargez Postfix :
sudo postfix check
sudo systemctl reload postfix
Créer l’utilisateur système vmail
Si ce n’est pas déjà fait, créez l’utilisateur qui possédera les boîtes mail physiques :
sudo groupadd -g 5000 vmail
sudo useradd -g vmail -u 5000 vmail -d /var/vmail -m -s /usr/sbin/nologinLangage du code : JavaScript (javascript)
Vérifiez :
id vmail
ls -lah /var/vmailLangage du code : JavaScript (javascript)
Le répertoire /var/vmail accueillera les boîtes mail si votre configuration Postfix/Dovecot suit cette convention.
Brancher Dovecot sur les utilisateurs PostfixAdmin
Dovecot doit lire les utilisateurs et mots de passe dans la même base. Le détail exact dépend de votre installation, mais la logique reste la même : Dovecot interroge la table mailbox de PostfixAdmin.
Un fichier SQL Dovecot typique ressemble à ceci :
sudo nano /etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname=postfix user=postfix_reader password=CHANGE_ME_WITH_ANOTHER_LONG_RANDOM_PASSWORD
default_pass_scheme = SHA512-CRYPT
password_query = \
SELECT username AS user, password \
FROM mailbox \
WHERE username = '%u' AND active = '1'
user_query = \
SELECT maildir AS home, 5000 AS uid, 5000 AS gid \
FROM mailbox \
WHERE username = '%u' AND active = '1'Langage du code : PHP (php)
Protégez le fichier :
sudo chown root:dovecot /etc/dovecot/dovecot-sql.conf.ext
sudo chmod 0640 /etc/dovecot/dovecot-sql.conf.ext
Rechargez Dovecot :
sudo doveconf -n
sudo systemctl reload dovecot
Testez l’authentification d’un compte :
doveadm auth test contact@example.com 'PASSWORD_IN_CLEAR_TEXT'Langage du code : CSS (css)
Si ce test échoue, regardez les logs Dovecot avant de toucher à Postfix. Le transport SMTP et l’authentification IMAP sont liés, mais ils ne tombent pas toujours pour la même raison.
Sécuriser l’accès à PostfixAdmin
PostfixAdmin administre votre serveur mail. Traitez-le donc comme une interface sensible.
- forcez HTTPS ;
- bloquez l’indexation avec
X-Robots-Tag; - restreignez
setup.php; - activez TOTP si votre version le propose ;
- utilisez des mots de passe uniques ;
- limitez l’accès par IP si possible ;
- surveillez les logs Nginx ;
- gardez PostfixAdmin à jour.
Vous pouvez ajouter une restriction IP globale dans Nginx si vous administrez toujours depuis les mêmes adresses :
allow 203.0.113.50;
deny all;Langage du code : CSS (css)
Placez ces directives dans le bloc server ou dans certaines locations sensibles. Si votre IP change souvent, préférez une protection d’accès plus souple, comme Cloudflare Access ou une authentification HTTP en amont.
Mettre à jour PostfixAdmin proprement
L’installation versionnée simplifie énormément les mises à jour. Avant tout, sauvegardez la base :
sudo mariadb-dump postfix > "/root/postfixadmin-postfix-$(date +%F-%H%M).sql"Langage du code : JavaScript (javascript)
Téléchargez la nouvelle version :
NEW_TAG="$(curl -fsSL https://api.github.com/repos/postfixadmin/postfixadmin/releases/latest | grep '"tag_name":' | cut -d '"' -f4)"
sudo install -d -o root -g root -m 0755 "/srv/postfixadmin/releases/${NEW_TAG}"
cd /tmp
curl -fsSL \
-o postfixadmin-update.tar.gz \
"https://github.com/postfixadmin/postfixadmin/archive/refs/tags/${NEW_TAG}.tar.gz"
sudo tar -xzf postfixadmin-update.tar.gz \
-C "/srv/postfixadmin/releases/${NEW_TAG}" \
--strip-components=1Langage du code : PHP (php)
Copiez votre configuration locale depuis la version active :
sudo cp -a /srv/postfixadmin/current/config.local.php "/srv/postfixadmin/releases/${NEW_TAG}/config.local.php"Langage du code : JavaScript (javascript)
Installez les dépendances :
cd "/srv/postfixadmin/releases/${NEW_TAG}"
sudo /bin/bash install.shLangage du code : JavaScript (javascript)
Corrigez les permissions :
sudo chown -R root:root "/srv/postfixadmin/releases/${NEW_TAG}"
sudo find "/srv/postfixadmin/releases/${NEW_TAG}" -type d -exec chmod 0755 {} \;
sudo find "/srv/postfixadmin/releases/${NEW_TAG}" -type f -exec chmod 0644 {} \;
sudo chown root:www-data "/srv/postfixadmin/releases/${NEW_TAG}/config.local.php"
sudo chmod 0640 "/srv/postfixadmin/releases/${NEW_TAG}/config.local.php"
sudo install -d -o www-data -g www-data -m 0750 "/srv/postfixadmin/releases/${NEW_TAG}/templates_c"Langage du code : JavaScript (javascript)
Basculez le lien symbolique :
sudo ln -sfn "/srv/postfixadmin/releases/${NEW_TAG}" /srv/postfixadmin/currentLangage du code : JavaScript (javascript)
Rechargez PHP-FPM et Nginx :
sudo systemctl reload php8.3-fpm
sudo nginx -t
sudo systemctl reload nginxLangage du code : CSS (css)
Ouvrez ensuite setup.php pour appliquer les migrations éventuelles :
https://pfa.example.com/setup.phpLangage du code : JavaScript (javascript)
Si quelque chose casse, revenez à l’ancienne version :
ls -lah /srv/postfixadmin/releases/
sudo ln -sfn /srv/postfixadmin/releases/OLD_TAG /srv/postfixadmin/current
sudo systemctl reload php8.3-fpm
sudo systemctl reload nginx
Dépannage
Erreur 502 Bad Gateway
Vérifiez le socket PHP-FPM dans Nginx :
ls -lah /run/php/
sudo systemctl status php8.3-fpm --no-pager
sudo tail -f /var/log/nginx/pfa.example.com.error.logLangage du code : JavaScript (javascript)
Le socket configuré dans fastcgi_pass doit correspondre au socket réellement présent sur le serveur.
Page blanche ou erreur PHP
Regardez les logs PHP-FPM et Nginx :
sudo journalctl -u php8.3-fpm -n 100 --no-pager
sudo tail -f /var/log/nginx/pfa.example.com.error.logLangage du code : JavaScript (javascript)
Vérifiez aussi que les extensions PHP nécessaires sont installées, notamment mysqli, mbstring, imap, xml et curl.
PostfixAdmin ne peut pas écrire dans templates_c
Corrigez le propriétaire du répertoire de cache :
sudo install -d -o www-data -g www-data -m 0750 /srv/postfixadmin/current/templates_c
sudo chown -R www-data:www-data /srv/postfixadmin/current/templates_c
setup.php renvoie 403
La configuration Nginx proposée limite l’accès à setup.php par IP. Remplacez l’adresse autorisée par votre IP publique actuelle :
curl -4 ifconfig.meLangage du code : CSS (css)
Puis modifiez le bloc Nginx correspondant :
location = /setup.php {
allow YOUR_PUBLIC_IP;
deny all;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param HTTPS on;
fastcgi_hide_header X-Powered-By;
}Langage du code : PHP (php)
Rechargez Nginx après modification :
sudo nginx -t
sudo systemctl reload nginx
Les comptes existent dans PostfixAdmin mais Postfix ne les voit pas
Testez les maps SQL avec postmap. C’est le diagnostic le plus rapide :
sudo postmap -q example.com mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf
sudo postmap -q contact@example.com mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf
sudo postmap -q postmaster@example.com mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cfLangage du code : JavaScript (javascript)
Si postmap ne retourne rien, Postfix ne retournera rien non plus. Vérifiez le nom de la base, l’utilisateur SQL, les permissions SQL et le contenu réel des tables.
Checklist finale
- Le sous-domaine PostfixAdmin pointe vers le serveur.
- Nginx sert uniquement le répertoire
public. - HTTPS fonctionne avec un certificat valide.
config.local.phpcontient la configuration locale.config.inc.phpn’a pas été modifié.- Le répertoire
templates_cappartient àwww-data. setup.phpest restreint par IP ou bloqué après installation.- La base MariaDB contient les tables PostfixAdmin.
- Le superadmin peut se connecter à
login.php. - Postfix lit les domaines, alias et boîtes avec
postmap. - Dovecot valide les comptes avec
doveadm auth test.
Besoin d’un serveur mail ou web vraiment propre ?
PostfixAdmin est pratique, mais un serveur mail complet reste une belle mécanique : Postfix, Dovecot, SPF, DKIM, DMARC, TLS, DNS, logs et délivrabilité doivent avancer ensemble.
- installation et sécurisation de serveurs mail Postfix/Dovecot ;
- configuration Nginx, PHP-FPM, MariaDB et certificats TLS ;
- diagnostic de logs SMTP, SASL, DKIM, DMARC et délivrabilité ;
- maintenance de serveurs WordPress, WooCommerce et infrastructures web.
Vous voulez éviter les nuits blanches avec mail.log ouvert en plein écran ? Contactez-moi et regardons votre configuration ensemble.
Pour aller plus loin
- Postfix sécurisé, avec des utilisateurs virtuels
- Serveur dédié : ajouter SPF, Sender-ID et DKIM
- Serveur mail : ajouter l’authentification DMARC
- Corriger les erreurs SASL, stats-writer et SSL dans Dovecot
- Postfix : corriger l’erreur SASL _sasl_plugin_load failed pour le plugin SQL
Besoin d’un serveur mail professionnel, sécurisé et bien configuré ?
Créer un serveur mail fiable demande plus qu’un simple Postfix qui démarre. Il faut gérer les domaines, les boîtes, les alias, l’authentification, le chiffrement, la délivrabilité et les enregistrements DNS. Sinon, les emails partent… puis disparaissent dans le Triangle des Bermudes du spam.
Je peux installer, configurer ou auditer votre serveur mail sur mesure, avec une base saine et documentée.
- installation de Postfix, Dovecot, PostfixAdmin et MariaDB ;
- création de domaines, comptes email, alias et quotas ;
- configuration SPF, DKIM, DMARC, TLS et reverse DNS ;
- durcissement de la configuration serveur et limitation des accès sensibles ;
- diagnostic de délivrabilité, logs SMTP, erreurs SASL et rejets antispam ;
- maintenance, migration ou remise au propre d’une infrastructure mail existante.
Vous voulez un serveur mail propre, maintenable et réellement utilisable au quotidien ? Contactez-moi et parlons de votre configuration.
FAQ
PostfixAdmin remplace-t-il Postfix ?
Non. PostfixAdmin est une interface d’administration. Postfix reste le serveur SMTP. PostfixAdmin écrit dans la base SQL, puis Postfix lit cette base pour connaître les domaines, alias et boîtes mail.
PostfixAdmin remplace-t-il Dovecot ?
Non. Dovecot gère IMAP, POP3, LMTP et souvent l’authentification. PostfixAdmin peut créer les comptes et mots de passe, mais Dovecot doit être configuré pour les lire dans la base SQL.
Faut-il modifier config.inc.php ?
Non. Utilisez config.local.php. Ce fichier surcharge la configuration par défaut et reste plus simple à conserver lors des mises à jour.
Peut-on utiliser SQLite avec PostfixAdmin ?
Oui, PostfixAdmin peut utiliser SQLite. Toutefois, pour un serveur mail avec Postfix et Dovecot, MariaDB ou PostgreSQL restent souvent plus pratiques, surtout si plusieurs services interrogent la base.
Pourquoi servir uniquement le répertoire public ?
Parce que le répertoire public contient le point d’entrée web prévu. Nginx ne doit pas exposer directement les fichiers internes, la configuration locale, les scripts ou les dépendances de l’application.
Faut-il laisser setup.php accessible ?
Non, pas publiquement. Restreignez-le par IP pendant l’installation ou les mises à jour, puis bloquez-le si vous n’en avez plus besoin. Cette page peut déclencher des opérations sensibles sur la base.
Conclusion
PostfixAdmin reste une excellente interface pour gérer un serveur mail Postfix avec domaines virtuels. La bonne approche consiste à l’installer dans un chemin versionné, à servir uniquement son répertoire public, à conserver la configuration dans config.local.php, et à relier proprement Postfix et Dovecot à la base SQL.
Une fois cette base posée, l’administration des domaines, boîtes et alias devient beaucoup plus simple. Et surtout, vous évitez de modifier vos utilisateurs mail à coups de requêtes SQL écrites un vendredi soir. Personne ne mérite ça.
Sources
- PostfixAdmin — dépôt GitHub officiel
- PostfixAdmin — guide d’installation officiel
- PostfixAdmin — versions publiées
- Nginx — documentation du module FastCGI
- Dovecot — documentation officielle
- Postfix — documentation des tables de recherche
Besoin d'un coup de main ?
Ce bug qui traîne depuis des semaines, ce plugin qui casse votre mise en page, cette fonctionnalité que personne n'arrive à implémenter proprement — c'est exactement ce que je règle au quotidien depuis 20 ans.
Parlons de votre problème →


