Post

🟱 đŸ“© OVH Stalwart Mail Server yannig.net

🟱 đŸ“© OVH Stalwart Mail Server yannig.net

Stalwart Mail Server est une solution open source conçue pour simplifier l’auto-hĂ©bergement des serveurs de mail, en mettant l’accent sur la sĂ©curitĂ© et la confidentialitĂ©. Écrit en Rust, il offre une alternative moderne aux logiciels de serveurs de mail existants, souvent complexes et obsolĂštes.

Stalwart Mail Server

Exigences :

  • VPS avec un port 25 ouvert : OVH vps-1780de45 yannig.net
    • IPV6: 2001:41d0:305:2100::c1c
      • IPV4: 51.38.37.240
  • Un nom de domaine enregistrĂ© : yannig.net
  • Domaine mail: mail.yannig.net

OVH vps-1780de45

DNS OVH yannig.net

Avant modifications

1
2
3
4
5
6
7
8
9
$TTL 3600
@	IN SOA dns14.ovh.net. tech.ovh.net. (2076760362 86400 3600 3600000 60)
        IN NS     dns14.ovh.net.
        IN NS     ns14.ovh.net.
        IN MX     1 mx1.mail.ovh.net.
        IN MX     5 mx2.mail.ovh.net.
        IN MX     100 mx3.mail.ovh.net.
        IN A     51.38.37.240
        IN TXT     "v=spf1 include:mx.ovh.com -all"

Configuration DNS OVH basique domaine yannig.net

1
2
3
4
5
6
7
$TTL 3600
@	IN SOA dns14.ovh.net. tech.ovh.net. (2076760577 86400 3600 3600000 60)
        IN NS     dns14.ovh.net.
        IN NS     ns14.ovh.net.
        IN A     51.38.37.240
        IN AAAA     2001:41d0:305:2100::c1c
        IN TXT     "v=spf1 include:mx.ovh.com -all"

Reverse DNS

Network → Adresses IP publiques


Outils

1
sudo apt install dnsutils

Vérification

1
2
dig -x 51.38.37.240 +short            # → yannig.net.
dig -x 2001:41d0:305:2100::c1c +short       # → yannig.net.

SMTP Port 25

VĂ©rifier que le fournisseur d’accĂšs internet ne bloque pas le trafic SMTP port TCP 25

Depuis un poste externe :

1
sudo nmap -sS -p25 51.38.37.240
1
2
3
4
5
6
7
8
Starting Nmap 7.99 ( https://nmap.org ) at 2026-04-22 14:30 +0200
Nmap scan report for yannig.net (51.38.37.240)
Host is up (0.013s latency).

PORT   STATE SERVICE
25/tcp open  smtp

Nmap done: 1 IP address (1 host up) scanned in 0.16 seconds

ACME.sh

CrĂ©ation des certificats SSL Let’s encrypt via Acme

1
2
3
4
5
6
# Git
git clone https://github.com/acmesh-official/acme.sh.git
cd ./acme.sh
# Installation sans crontab --force
./acme.sh --install --force

Se reconnecter pour prise en charge

Les clé OVH

1
2
export OVH_AK="wxxxxxxxxxxxxxxxx"
export OVH_AS="yxxxxxxxxxxxxxxxxxxxxxxx"

Créer les certificats

1
acme.sh --dns dns_ovh --server letsencrypt --issue --keylength ec-384 -d 'yannig.net' -d '*.yannig.net'

Ouvrir le lien gĂ©nĂ©rĂ© pour valider l’authentification OVH
puis relancer la commande

1
acme.sh --dns dns_ovh --server letsencrypt --issue --keylength ec-384 -d 'yannig.net' -d '*.yannig.net'

Les certificats

1
2
3
4
[mar. 21 avril 2026 16:10:41 CEST] Your cert is in: /home/yann/.acme.sh/yannig.net_ecc/yannig.net.cer
[mar. 21 avril 2026 16:10:41 CEST] Your cert key is in: /home/yann/.acme.sh/yannig.net_ecc/yannig.net.key
[mar. 21 avril 2026 16:10:41 CEST] The intermediate CA cert is in: /home/yann/.acme.sh/yannig.net_ecc/ca.cer
[mar. 21 avril 2026 16:10:41 CEST] And the full-chain cert is in: /home/yann/.acme.sh/yannig.net_ecc/fullchain.cer

Installation des certificats

Droits dossier

1
2
sudo chown $USER:stalwart /etc/ssl/private/ 
sudo chmod 750 /etc/ssl/private/

Si vous utilisez acme.sh pour gérer vos certificats, vous pouvez simplement exécuter

1
2
3
4
acme.sh --ecc --install-cert -d 'yannig.net' \
  --key-file       /etc/ssl/private/privkey.pem  \
  --fullchain-file /etc/ssl/private/fullchain.pem \
  --reloadcmd      "sudo systemctl restart stalwart"

Mise Ă  jour des certificats

Le VPS n’a pas crontab installĂ©, on va utiliser systemd timer

Le fichier de service

1
sudo nano /etc/systemd/system/update-certificat.service

contenu

1
2
3
4
[Unit]
Description="Update certificat"
[Service]
ExecStart="/home/yann/.acme.sh"/acme.sh --cron --home "/home/yann/.acme.sh"

Le fichier minuteur

1
sudo nano /etc/systemd/system/update-certificat.timer

Exécution service tous les jours (lundi au dimanche) à 1h20

1
2
3
4
5
6
7
[Unit]
Description="Renouvellement certificat si date validité atteinte"
[Timer]
OnCalendar=Mon..Sun *-*-* 1:20:00
Unit=update-certificat.service
[Install]
WantedBy=multi-user.target

Activer le minuteur

1
sudo systemctl enable update-certificat.timer --now

Vérification

1
systemctl list-timers

Résultat

1
2
NEXT                            LEFT LAST                               PASSED UNIT                         ACTIVATES                     
Wed 2026-04-22 01:20:00 CEST      9h -                                       - update-certificat.timer      update-certificat.service

Tester la mise Ă  jour des certificats

On va forcer (--force) la procédure et voir le résultat

1
"/home/yann/.acme.sh"/acme.sh --force --cron --home "/home/yann/.acme.sh"

Résultat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[mer. 22 avril 2026 15:29:27 CEST] ===Starting cron===
[mer. 22 avril 2026 15:29:27 CEST] Renewing: 'yannig.net'
[mer. 22 avril 2026 15:29:27 CEST] Renewing using Le_API=https://acme-v02.api.letsencrypt.org/directory
[mer. 22 avril 2026 15:29:28 CEST] Using CA: https://acme-v02.api.letsencrypt.org/directory
[mer. 22 avril 2026 15:29:28 CEST] Multi domain='DNS:yannig.net,DNS:*.yannig.net'
[mer. 22 avril 2026 15:29:31 CEST] Getting webroot for domain='yannig.net'
[mer. 22 avril 2026 15:29:31 CEST] Getting webroot for domain='*.yannig.net'
[mer. 22 avril 2026 15:29:32 CEST] yannig.net is already verified, skipping dns-01.
[mer. 22 avril 2026 15:29:32 CEST] *.yannig.net is already verified, skipping dns-01.
[mer. 22 avril 2026 15:29:32 CEST] Verification finished, beginning signing.
[mer. 22 avril 2026 15:29:32 CEST] Let's finalize the order.
[mer. 22 avril 2026 15:29:32 CEST] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/3261565761/503263123221'
[mer. 22 avril 2026 15:29:34 CEST] Downloading cert.
[mer. 22 avril 2026 15:29:34 CEST] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/06f1d2dce6d6abf103b51aeacd877777dced'
[mer. 22 avril 2026 15:29:34 CEST] Cert success.
-----BEGIN CERTIFICATE-----
MIIDqzCCAzKgAwIBAgISBvHS3ObWq/EDtRrqzYd3d9ztMAoGCCqGSM49BAMDMDIx
................................................................
wlGN9+2d/jpHlXCDhVKto+dTRvSOSWpI4LLnyujefQ==
-----END CERTIFICATE-----
[mer. 22 avril 2026 15:29:34 CEST] Your cert is in: /home/yann/.acme.sh/yannig.net_ecc/yannig.net.cer
[mer. 22 avril 2026 15:29:34 CEST] Your cert key is in: /home/yann/.acme.sh/yannig.net_ecc/yannig.net.key
[mer. 22 avril 2026 15:29:34 CEST] The intermediate CA cert is in: /home/yann/.acme.sh/yannig.net_ecc/ca.cer
[mer. 22 avril 2026 15:29:34 CEST] And the full-chain cert is in: /home/yann/.acme.sh/yannig.net_ecc/fullchain.cer
[mer. 22 avril 2026 15:29:35 CEST] Installing key to: /etc/ssl/private/privkey.pem
[mer. 22 avril 2026 15:29:35 CEST] Installing full chain to: /etc/ssl/private/fullchain.pem
[mer. 22 avril 2026 15:29:35 CEST] Running reload cmd: sudo systemctl restart stalwart
[mer. 22 avril 2026 15:29:36 CEST] Reload successful
[mer. 22 avril 2026 15:29:36 CEST] ===End cron===

Les certificats ont été mis à jour et installés dans le dossier /etc/ssl/private/ puis le service stalwart est redémarré.

Parefeu

Ports essentiels Ă  maintenir ouverts :

  • Port 25 (SMTP) : Pour la rĂ©ception d’e-mails d’autres serveurs de messagerie.
  • Port 465 (SMTPS) : RecommandĂ© pour l’envoi sĂ©curisĂ© d’e-mails sortants des clients utilisateurs avec TLS implicite. À privilĂ©gier par rapport au port 587.‱
  • Port 993 (IMAPS) : Pour l’accĂšs sĂ©curisĂ© aux e-mails via les clients IMAP avec TLS implicite.
  • Port 443 (HTTPS) : Pour l’administration web, JMAP, l’API REST, OAuth, le provisionnement de certificats TLS (ACME) et d’autres services web sĂ©curisĂ©s.

Ports non essentiels à désactiver si non utilisés :

  • Port 587 (SMTP Submission) : Si tous vos clients utilisent le port 465, ce port peut ĂȘtre dĂ©sactivĂ©.
  • Port 143 (IMAP4) : Le port IMAP standard sans chiffrement. Il devrait gĂ©nĂ©ralement ĂȘtre dĂ©sactivĂ© au profit du port 993 (IMAPS).
  • Port 4190 (ManageSieve) : À garder ouvert uniquement si vos utilisateurs gĂšrent activement des scripts Sieve.
  • Port 110 (POP3) et Port 995 (POP3S) : POP3 est largement obsolĂšte au profit d’IMAP. DĂ©sactivez-les sauf en cas de besoin spĂ©cifique.
  • Port 8080 (HTTP) : Principalement fourni pour la configuration initiale. Il est fortement recommandĂ© de dĂ©sactiver ce port aprĂšs la configuration pour prĂ©venir les accĂšs non authentifiĂ©s et non chiffrĂ©s.

Installation Debian / Ubuntu

1
sudo apt install ufw

Les rĂšgles Ă  ajouter pour le serveur de messagerie

1
2
sudo ufw allow 53240 # ssh
sudo ufw allow 443

Activer le parefeu

1
sudo ufw enable
1
2
3
4
# Ouvrir les ports 25,465 et 993 pour le serveur messagerie
sudo ufw allow 25
sudo ufw allow 465
sudo ufw allow 993

Parefeu final

1
2
3
4
5
6
7
8
9
10
11
12
55240/tcp                  ALLOW       Anywhere                  
443                        ALLOW       Anywhere                  
25                         ALLOW       Anywhere                  
993                        ALLOW       Anywhere                  
465                        ALLOW       Anywhere                  
587/tcp                    ALLOW       Anywhere                  
55240/tcp (v6)             ALLOW       Anywhere (v6)             
443 (v6)                   ALLOW       Anywhere (v6)             
25 (v6)                    ALLOW       Anywhere (v6)             
993 (v6)                   ALLOW       Anywhere (v6)             
465 (v6)                   ALLOW       Anywhere (v6)             
587/tcp (v6)               ALLOW       Anywhere (v6)             

Applications Stalwart

Stalwart Web UI

Stalwart est livrĂ© avec un script d’installation qui tĂ©lĂ©charge la derniĂšre version, crĂ©e un compte de service dĂ©diĂ©, installe le binaire sous les chemins Unix standard, Ă©crit une unitĂ© de service et dĂ©marre le dĂ©mon. L’accĂšs root sur la machine cible et la connectivitĂ© HTTPS sortante sont nĂ©cessaires pour les Ă©tapes ci-dessous.

Ouvrez un terminal sur l’hĂŽte cible et rĂ©cupĂ©rez le script d’installation en mode utilisateur (PAS root):

1
curl --proto '=https' --tlsv1.2 -sSf https://get.stalw.art/install.sh -o install.sh

Exécutez le script comme root:

1
sudo sh install.sh

Aucun argument n’est requis. Le script suit la norme de hiĂ©rarchie du systĂšme de fichiers et place le binaire sous /usr/local/bin/stalwart, le fichier de configuration sous /etc/stalwart/config.json, variables d’environnement sous /etc/stalwart/stalwart.env, donnĂ©es d’application sous /var/lib/stalwart/et de journaux fichiers sous /var/log/stalwart/.

Un dĂ©diĂ© stalwartUn compte de service est créé s’il n’existe pas dĂ©jĂ . Le script Ă©crit alors l’unitĂ© de service appropriĂ©e (systemd, SysV init.d, ou launchden fonction du systĂšme d’exploitation), active le service au dĂ©marrage et le dĂ©marre immĂ©diatement.

En utilisant les identifiants fournis, connectez-vous Ă  votre Stalwart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
⏳ Downloading stalwart for x86_64-unknown-linux-gnu...
Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure
Warning: Not enforcing TLS v1.2, this is potentially less secure
📝 Writing env file at /etc/stalwart/stalwart.env...
🔐 Setting permissions...
🚀 Starting service...
Created symlink '/etc/systemd/system/multi-user.target.wants/stalwart.service' → '/etc/systemd/system/stalwart.service'.

🎉 Installation complete!

Stalwart is running in bootstrap mode. A temporary administrator
password was generated at startup and printed to the service logs.

👉 To find the password, inspect the service logs:
     journalctl -u stalwart -n 200 | grep -A8 'bootstrap mode'

   Or set STALWART_RECOVERY_ADMIN=admin:<password> in
   /etc/stalwart/stalwart.env and restart the service to pin a credential.

   Finish setup at: http://yannig.net:8080/admin

Les fichiers log

1
2
sudo mkdir /var/log/stalwart
sudo chown stalwart:stalwart /var/log/stalwart

Stalwart Web UI - Mises Ă  jour

Afficher version : stalwart -V
La derniĂšre version https://github.com/stalwartlabs/stalwart/releases

Stalwart suit le versioning sĂ©mantique (semver), qui utilise un numĂ©ro de version dans le format MAJOR.MINOR.PATCH (par exemple, 0.16.3). Ce systĂšme indique la nature et l’impact de chaque rejet:

  • Les versions de patch (le dernier numĂ©ro) n’incluent que de petites corrections rĂ©trocompatibles. Mise Ă  niveau entre les versions de patch, telles que Ă  partir de 0.16.5 Ă  0.16.13, est sĂ»r et ne nĂ©cessite pas de lire les notes de libĂ©ration au prĂ©alable.
  • Les versions mineures (le numĂ©ro moyen) peuvent introduire de nouvelles fonctionnalitĂ©s ou des ajustements qui pourraient nĂ©cessiter des modifications de configuration ou des migrations. Il est essentiel de lire attentivement les notes de publication avant la mise Ă  niveau pour comprendre ce qui a pu changer.
  • Les versions principales (le premier numĂ©ro) peuvent inclure des changements de rupture, en particulier avant la version 1.0.0, et nĂ©cessitent toujours un examen et une planification avant la mise Ă  niveau.

[0.16.13] - 2026-07-12
Si vous mettez Ă  jour depuis v0.16.x, remplacez le binaire (ou exĂ©cutez docker pull). Si vous mettez Ă  niveau depuis v0.15.x et les versions antĂ©rieures, veuillez lire la documentation de mise Ă  niveau pour plus d’informations sur comment mettre Ă  niveau depuis les versions prĂ©cĂ©dentes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Version release
Version="v0.16.13"
mkdir -p ~/temp
cd ~/temp
# Téléchargement et décompression derniÚre version linux
wget https://github.com/stalwartlabs/stalwart/releases/download/$Version/stalwart-x86_64-unknown-linux-gnu.tar.gz
tar xzvf stalwart-x86_64-unknown-linux-gnu.tar.gz
# Rendre exécutable le binaire stalwart
chmod +x stalwart
# ArrĂȘt service stalwart
sudo systemctl stop stalwart
# Copier le binaire stalwart dans /usr/local/bin/
sudo cp stalwart /usr/local/bin/stalwart 
# Départ service stalwart
sudo systemctl start stalwart
# Afficher version stalwart
stalwart -V 
# Effacer ~/temp/stalwart*
rm ~/temp/stalwart*
cd ..

stalwart-cli

stalwart-cli est un petit outil de ligne de commande axĂ© sur les schĂ©mas pour l’administration d’un serveur de messagerie et de collaboration Stalwart. Il s’adresse exclusivement Ă  l’API JMAP et fonctionne sur les objets de gestion/configuration (ceux dont les noms de type JMAP sont prĂ©fixĂ©s avec x:) exposĂ© par le biais de la urn:stalwart:jmapcapacitĂ©.

L’outil est pilotĂ© par schĂ©ma: d’abord, il tĂ©lĂ©charge (et cache) un schĂ©ma JSON Ă  partir du serveur qui dĂ©crit chaque objet, ses champs, les formulaires utilisĂ©s pour le rendre et les listes utilisĂ©es pour rendre des requĂȘtes. Tout le comportement de commande, la validation et la sortie lisible par l’homme sont dĂ©rivĂ©s de ce schĂ©ma, de sorte que le mĂȘme binaire fonctionne contre tout dĂ©ploiement compatible de Stalwart sans recompilation.

Capacités

TĂąche Commande Titre
Inspectez les objets et les énums que le serveur expose describe Explorer le schéma
Lire un seul objet par id (ou un singleton) get Aller chercher un seul objet
Liste ou filtre des objets d’un type donnĂ© query Recherche et liste
CrĂ©er un ou plusieurs objets create CrĂ©ation d’objets
Modifier un objet existant (ou singleton) update Mise Ă  jour des objets
Détruire un ou plusieurs objets delete Enlever des objets
Appliquer un plan en gros Ă  partir d’un fichier JSON apply OpĂ©rations en vrac dĂ©claratives
Exporter l’état du serveur en direct comme plan d’application snapshot Exportation de l’état du serveur

Installation Linux (installateur shell)

Les binaires prĂ©-construits sont produits pour macOS (Intel et Apple Silicon), Linux (x86_64 et aarch64, glibc et musl), et Windows (x86_64 et aarch64). Choisissez l’installateur qui correspond Ă  la plate-forme.

1
2
curl --proto '=https' --tlsv1.2 -LsSf \
  https://github.com/stalwartlabs/cli/releases/latest/download/stalwart-cli-installer.sh | sh

Résultat commande

1
2
3
4
5
6
7
8
9
downloading stalwart-cli 1.0.8 x86_64-unknown-linux-gnu
installing to /home/yann/.cargo/bin
  stalwart-cli
everything's installed!

To add $HOME/.cargo/bin to your PATH, either restart your shell or run:

    source $HOME/.cargo/env (sh, bash, zsh)
    source $HOME/.cargo/env.fish (fish)

Exécuter

1
source $HOME/.cargo/env

Version: stalwart-cli --version → stalwart-cli 1.0.8

Clé API

Settings → Credentials → API Keys

Connexion serveur

Chaque invocation a besoin d’une URL de serveur et d’un identifiant. Les mĂȘmes drapeaux sont globaux et peuvent apparaĂźtre avant ou aprĂšs la sous-commande.

Drapeau| Variable environnement| But ——-|—————————-|————– –url | STALWART_URL| Le point de terminaison du serveur Stalwart (requis). --user | STALWART_USER| Nom d'utilisateur de base-auth. --password | STALWART_PASSWORD| Mot de passe de base-auth. ProvoquĂ© de maniĂšre interactive si absent et stdin est un ATS. --api-key | STALWART_TOKEN| Jeton de porteur. Mutuellement exclusif avec --user. --insecure/ -k| (aucun) |VĂ©rifier le certificat TLS (matchs curl -k). --no-color| (aucun)| DĂ©sactivez la sortie couleur ANSI. Le NO_COLORLa variable d'environnement dĂ©sactive Ă©galement les couleurs.

Une invocation typique contre un serveur de développement local:

1
stalwart-cli --url http://localhost:8080 --user admin --password admin describe

Équivalent avec les variables d’environnement (recommandĂ©es pour les scripts et l’IC):

1
2
3
4
export STALWART_URL=https://yannig.net
export STALWART_USER=admin
export STALWART_PASSWORD='changeme'
stalwart-cli describe

Pour une utilisation sans surveillance, préférez un jeton API:

1
2
3
export STALWART_URL=https://yannig.net
export STALWART_TOKEN='eyJhbGciOi...'
stalwart-cli describe

MX yannig.net

Administration

Le serveur n’a pas de carte graphique, on utilise le proxy ssh depuis un poste linux ayant les accùs

1
ssh -L 9500:localhost:8080 -p 55240 -i ~/.ssh/vps-1780de45 yann@51.38.37.240

Ouvrir le lien http://localhost:9500/admin sur le poste appelant

Les fichiers log "info"

Les fichiers log "debug"

DNS OVH Auto

Mise Ă  jour automatique des enregistrements DNS OVH

Settings -> Network -> DNS -> DNS Providers OVH

Relancer stalwart

Relever les information de connexion et redémarrer le service stalwart

1
sudo systemctl restart stalwart

TLS Certificats Manuels

Connexion sur le lien https://yannig.net/admin

Les certificats ne sont pas au bon endroits, il faut forcer la connexion

Se rendre dans settings

On copie le certificat /home/yann/.acme.sh/yannig.net_ecc/fullchain.cer et la clé /home/yann/.acme.sh/yannig.net_ecc/yannig.net.key

Lecture certificats par stalwart

on doit utiliser les ACLs

1
2
sudo apt install acl # si non installé
sudo setfacl -R -m u:stalwart:rX /etc/ssl/private/privkey.pem /etc/ssl/private/fullchain.pem

Vérification: sudo getfacl /etc/ssl/private/*.pem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
getfacl : suppression du premier « / » des noms de chemins absolus
# file: etc/ssl/private/fullchain.pem
# owner: yann
# group: yann
user::rw-
user:stalwart:r--
group::rw-
mask::rw-
other::r--

# file: etc/ssl/private/privkey.pem
# owner: yann
# group: yann
user::rw-
user:stalwart:r--
group::---
mask::r--
other::---

“Settings” → “TLS” → “Certificates”

VĂ©rifications Management → Domains
Domain yannig.net

Zonefile

Management → Domains → yannig.net

  • Les options
    • DKIM public keys
    • TLSA records
    • SPF records
    • MX records
    • DMARC policy
    • SRV records
    • MTA-STS policy record
    • TLS reporting record
    • CAA records
    • Autoconfig records
    • Legacy Autoconfig records
    • Microsoft Autodiscover records

Submission port 587

L’accĂšs smtp via le port 587 est ajoutĂ© pour une utilisation dans le serveur de notification ntfy

Préalable:
Ouvrir le port 587 sur le parefeu UFW

1
sudo ufw allow 587

Stalwart, ajouter un listener:
“Settings → Network → Listeners” et “+ Create listener”


Cliquer sur “Save”

Redémarrer le service

1
sudo systemctl restart stalwart

Account


Configurez les préférences de votre compte, notamment les paramÚtres régionaux, le fuseau horaire, le cryptage au repos et une description personnelle

Utilisateur yann

Compte de messagerie

Nous ajoutons un compte email.

Allez Ă  Management > Directory > Accounts

ATTENTION Username est le nom sans extension , yann et NON yann@yannig.net



Calendrier et contacts

AccĂšs Settings â€ș Calendar & Contacts

Ne pas oublier de cliquer sur “Save”


Ne pas oublier de cliquer sur “Save”

Thunderbird

Stalwart n’a pas d’email web, donc nous devons utiliser un client de messagerie externe.

Aller dans ParamĂštre des comptes et ajouter






Test messagerie

Maintenant que nous avons connecté notre Stalwart à Thunderbird, laissez-nous tester notre e-mail.

Allez au testeur de courrier https://www.mail-tester.com/.
Je vais envoyer un e-mail de test.

⚠ Il faut saisir un sujet et du contenu

Importer un agenda






Importer un carnet d’adresse





yick.eu

Certificats TLS

On a une création de certificats existante pour le domaine yannig.net, regénérer les certificats en ajoutant le domaine yick.eu

Les clé OVH

1
2
export OVH_AK="wxxxxxxxxxxxxxxxx"
export OVH_AS="yxxxxxxxxxxxxxxxxxxxxxxx"

Générer les certificats des domaines

1
acme.sh --dns dns_ovh --server letsencrypt --issue --keylength ec-384 -d 'yannig.net' -d '*.yannig.net' -d 'yick.eu' -d 'cinay.eu'

Les certificats

1
2
3
4
[jeu. 23 avril 2026 16:40:34 CEST] Your cert is in: /home/yann/.acme.sh/yannig.net_ecc/yannig.net.cer
[jeu. 23 avril 2026 16:40:34 CEST] Your cert key is in: /home/yann/.acme.sh/yannig.net_ecc/yannig.net.key
[jeu. 23 avril 2026 16:40:34 CEST] The intermediate CA cert is in: /home/yann/.acme.sh/yannig.net_ecc/ca.cer
[jeu. 23 avril 2026 16:40:34 CEST] And the full-chain cert is in: /home/yann/.acme.sh/yannig.net_ecc/fullchain.cer

Installer les certificats et redémarrer le service stalwart

1
2
3
4
acme.sh --ecc --install-cert -d 'yannig.net' \
  --key-file       /etc/ssl/private/privkey.pem  \
  --fullchain-file /etc/ssl/private/fullchain.pem \
  --reloadcmd      "sudo systemctl restart stalwart"

Résultat commande ci-dessus

1
2
3
4
[jeu. 23 avril 2026 16:50:28 CEST] Installing key to: /etc/ssl/private/privkey.pem
[jeu. 23 avril 2026 16:50:28 CEST] Installing full chain to: /etc/ssl/private/fullchain.pem
[jeu. 23 avril 2026 16:50:28 CEST] Running reload cmd: sudo systemctl restart stalwart
[jeu. 23 avril 2026 16:50:30 CEST] Reload successful

Domaine yick.eu

Connectez-vous au panneau d’administration de Stalwart avec un compte administrateur.
Dans la section Management → Domains → Domains
Ajouter un domaine, Cliquer sur “Create domain”



Management → Domains → yick.eu

  • Les options
    • DKIM public keys
    • TLSA records
    • SPF records
    • MX records
    • DMARC policy
    • SRV records
    • MTA-STS policy record
    • TLS reporting record
    • CAA records
    • Autoconfig records
    • Legacy Autoconfig records
    • Microsoft Autodiscover records

Créer un utilisateur yick@yick.eu

Ajout utilisateur Ă  Thunderbird

Test https://www.mail-tester.com

cinay.eu

Certificats TLS

On a une création de certificats existante pour le domaine yannig.net, regénérer les certificats en ajoutant le domaine cinay.eu

Les clé OVH

1
2
export OVH_AK="wxxxxxxxxxxxxxxxx"
export OVH_AS="yxxxxxxxxxxxxxxxxxxxxxxx"

Générer les certificats des domaines

1
acme.sh --dns dns_ovh --server letsencrypt --issue --keylength ec-384 -d 'yannig.net' -d '*.yannig.net' -d 'yick.eu' -d 'cinay.eu'

Installer les certificats et redémarrer le service stalwart

1
2
3
4
acme.sh --ecc --install-cert -d 'yannig.net' \
  --key-file       /etc/ssl/private/privkey.pem  \
  --fullchain-file /etc/ssl/private/fullchain.pem \
  --reloadcmd      "sudo systemctl restart stalwart"

Domaine cinay.eu

Connectez-vous au panneau d’administration de Stalwart avec un compte administrateur.
Dans la section Management → Domains → Domains
Ajouter un domaine, Cliquer sur “Create domain”





“View Zone File”

Les enregistrements du domaine cinay.eu sont mises Ă  jour automatiquement par API DNS OVH

Management → Domains → cinay.eu

  • Les options
    • DKIM public keys
    • TLSA records
    • SPF records
    • MX records
    • DMARC policy
    • SRV records
    • MTA-STS policy record
    • TLS reporting record
    • CAA records
    • Autoconfig records
    • Legacy Autoconfig records
    • Microsoft Autodiscover records

Compte de messagerie “yani”

Nous ajoutons un compte email.

Allez Ă  Management > Directory > Accounts
Cliquer sur “Create user”

ATTENTION Username est le nom sans extension , yani et NON yani@cinay.eu



Ajout utilisateur Ă  Thunderbird



Test https://www.mail-tester.com

TLS Certificats Automatiques

Ouvrir Stalwart en mode administrateur

1. Settings → TLS → ACME Providers (ACME Provider)

ACME providers -> Create provider

| Champ | Valeur | | :—————— | :———————————————– | | Directory URL* | https://acme-v02.api.letsencrypt.org/directory | | Challenge type* | DNS-01 | | Contact Email | staladmin@yannig.net ✅ | | Renew before* | R23 (par dĂ©faut : 2/3 de la durĂ©e) | | Key ID | (vide) | | HMAC Key | (vide) | | Max retries* | 10 (par dĂ©faut) | Sauvegarder la configuration

Puis Management -> Actions -> Server settings pour recharger la configuration

2. Management → Domains → domains

Editer un domaine pour effectuer la modification
Sauvegarder

Répéter cette opération pour tous les domaines

Stalwart va maintenant :

  1. GĂ©nĂ©rer une demande de certificat Let’s Encrypt via ACME
  2. CrĂ©er automatiquement l’enregistrement TXT _acme-challenge.yourdomain.com via l’API OVH
  3. Valider le challenge DNS-01 avec Let’s Encrypt
  4. Récupérer le certificat signé
  5. Supprimer l’enregistrement TXT _acme-challenge aprùs validation
  6. Rénover automatiquement avant expiration (2/3 de la durée)

Votre DNS provider OVH est déjà configuré avec les clés API (Application Key, Application Secret, Consumer Key), donc Stalwart pourra utiliser directement ce provider pour les enregistrements TXT ACME.

3. Warning Multiple TLS certificates available

Le serveur est dans le domaine principal yannig.net IN MX 10 yannig.net. avec 2 autres domaines cinay.eu et yick.eu avec un enregistrement DNS IN MX 10 yannig.net.
L’accùs administration web se fait sur le lien https://yannig.net
Les certificats TLS sont gérés automatiquent via API OVH
TOUT FONCTIONNE PARFAITEMENT Ă  un dĂ©tail prĂšs., j’ai validĂ© la mise Ă  jour des certificats TLS pour les 3 domaines et je reçois un avertissement de stalwart:
Warning Multiple TLS certificates available Total=3
Je pense que j’ai fait une erreur, je dois valider TLS Auto pour le domaine yannig.net UNIQUEMENT ?
Si OUI, je supprime le TLS pour les domaines cinay.eu et yick.eu ?

Oui, vous avez fait une erreur : vous devez valider TLS Auto uniquement pour le domaine principal yannig.net, et supprimer/annuler TLS Auto pour cinay.eu et yick.eu

Pourquoi cet avertissement apparaĂźt

Stalwart dĂ©tecte 3 certificats TLS diffĂ©rents pour le mĂȘme IP/hostname, ce qui gĂ©nĂšre le warning visible (Management → Observability → Logs)

Dans votre configuration :

  • Les 3 domaines (yannig.net, cinay.eu, yick.eu) ont le mĂȘme enregistrement MX pointing vers yannig.net
  • L’accĂšs WebUI se fait via https://yannig.net (un seul hostname)
  • Stalwart utilise SNI pour sĂ©lectionner le certificat, mais pour un seul hostname d’accĂšs, un seul certificat est nĂ©cessaire[^1_1]

Ce que vous devez faire

Action Domaine
✅ Maintenir TLS Auto yannig.net (domaine principal)
❌ Supprimer TLS Auto cinay.eu
❌ Supprimer TLS Auto yick.eu

Étapes dans la WebUI Stalwart

1- Aller dans Settings → TLS → Certificates

2- Pour cinay.eu et yick.eu : désactiver/supprimer la configuration ACME/TLS Auto

3- Pour yannig.net : conserver TLS Auto activé

4- Recharger la configuration Stalwart (Management → Actions → Server settings)

Un redémarrage de stalwart est préférable: sudo systemctl restart stalwart

Explication technique

Puisque votre MX est yannig.net. et que vous accĂ©dez Ă  l’administration via https://yannig.net, un seul certificat TLS pour yannig.net est suffisant. Les autres domaines n’ont pas besoin de certificats sĂ©parĂ©s car :

  • Ils utilisent le mĂȘme serveur MX ()
  • Le certificat de yannig.net couvre le hostname d’accĂšs
  • Stalwart sĂ©lectionnera automatiquement le certificat correspondant via SNI

Aprùs cette correction, l’avertissement “Multiple TLS certificates available” devrait disparaütre.

Test et vérification serveur mail

L’outil web le plus complet pour vĂ©rifier et tester un serveur de messagerie est MXToolbox (MXTool.net) — il offre une suite exhaustive de tests tous regroupĂ©s sur une plateforme unique. clientarea.itinsell

Pourquoi MXToolbox est le plus complet

Catégorie Outils disponibles
DNS MX Lookup, SPF Lookup, DKIM Lookup, TXT Lookup, DNSBL (liste noire)
SMTP SMTP Diagnostic (6 tests : durée, open relay, reverse DNS PTR, banniÚre, EHLO/HELO, STARTTLS)
Sécurité SPF validateur, DKIM vérificateur, DMARC check
Autre Ping, Port Check, Whois, Trace Route

Le SMTP Diagnostic réalise 6 tests différents et fournit une transcription complÚte de la session SMTP avec tous les codes serversmtp

Autres excellents outils complémentaires

Outil Spécialité
mail-tester.com Score de qualitĂ© email (spam, format, syntaxe) — vous envoyez un email vers une adresse temporaire et obtenez un score dĂ©taillĂ© levillage
GlockApps Test de livraison + scoring anti-spam (considĂ©rĂ© comme “le gagnant absolu” aprĂšs test de 7 outils) wpmailsmtp
Diagnostic SMTP (NTool) Test connexion SMTP, TLS/STARTTLS, open relay, temps de réponse ntool
DMARCian Vérification complÚte DMARC, SPF, DKIM reddit
MX Lookup (EXPERTE.com) Vérification rapide enregistrements MX experte

Définition SPF DKIM DMARC

SPF

SPF est une norme pour vĂ©rifier l’adresse IP expĂ©ditrice d’un email. La vĂ©rification se fait en utilisant le nom de domaine de l’expĂ©diteur d’enveloppe (MAIL FROM:) et en rĂ©cupĂ©rant un enregistrement DNS qui va lister les adresses IP autorisĂ©es. La vĂ©rification peut aussi se faire par rapport au FQDN annoncĂ© dans le HELO (cf (RFC 7208, 2.3)

Voici un exemple d’enregistrement DNS pour du SPF :

1
@ IN TXT "v=spf1 mx ip4:192.0.2.142 ip4:192.0.2.0/24 ip6:2001:db8::/32 -all"

Voici un exemple d’enregistrement DNS n’autorisant aucun envoi (à mettre pour vos domaines voire sous-domaines qui n’envoient jamais d’emails) :

1
@ IN TXT "v=spf1 -all"

On peut utiliser des include: vers un autre enregistrement TXT.

Chez Evolix, on utilise ainsi include:spf.protection.evolix.net. Si vous utilisez Mailchimp vous devez ajouter include:spf.mandrillapp.com par exemple.

Il faut savoir que l’on peut contourner la longueur maximale de 255 caractùres pour un enregistrement TXT en concatener plusieurs chaünes. On notera qu’au moins une des deux chaünes doit contenir une espace. Voici un exemple :

1
@ IN TXT "v=spf1 mx ip4:192.0.2.142 ip4:192.0.2.0/24" " ip6:2001:db8::/32 ~all"

En pratique il est conseillĂ© d’éviter une longueur totale du champ TXT (FQDN compris) de plus de 450 octets (Ă  vĂ©rifier via MSG SIZE rcvd: avec dig).

Il est Ă©galement conseillĂ© de ne pas mettre plus de 101 adresses ou prĂ©fixes IP (Gmail refuserait au-delĂ  et de ne pas avoir besoin de plus de 10 rĂ©solutions DNS pour savoir si l’IP expĂ©ditrice est incluse dans l’enregistrement SPF.

Attention, la RFC 7208 spĂ©cifie que le mot clĂ© PTR ne devrait pas ĂȘtre utilisĂ© mĂȘme si en pratique ça semble toujours utilisĂ© (OVH l’utilise par exemple).

Enfin, on se demande souvent si l’on doit mettre “~all” ou “-all” : on a tendance Ă  privilĂ©gier de plus en plus -all car cela donnera davantage de rejets explicites (au niveau SMTP par exemple, au lieu d’aller en Spam ou Quarantaine).

DKIM

DKIM est une norme pour ajouter une signature cryptographique dans les entĂȘtes d’un email envoyĂ©. La signature se fait Ă  partir Ă  de l’expĂ©diteur d’entĂȘte (From: d’un email), des entĂȘtes au choix (sujet, date, etc.) et le corps du message. Cela utilise aussi une clĂ© publique stockĂ©e dans un enregistrement DNS TXT.

Voir https://wiki.evolix.org/HowtoOpenDKIM

DMARC

DMARC est une spécification qui vient en complément de DKIM et SPF. Cela permet de spécifier aux serveurs de messagerie comment traiter les emails reçus non conformes aux vérifications SPF et/ou DKIM. Cela permet également de récupérer des informations voire des emails complets si ils ne sont pas conformes. Encore une fois, cela se fait avec un enregistrement DNS TXT.

Attention, l’enregistrement DMARC recherchĂ© est celui du domaine de l’expĂ©diteur d’entĂȘte (From:), appelĂ© aussi “RFC5322.From”.

Pour que la vĂ©rification DMARC passe, il suffit que l’un des cas soit rempli :

  • DKIM passe (et le “RFC5322.From” alignĂ©, mais c’est le principe de base sauf cas tordu)
  • SPF passe ET le “RFC5321.MailFrom” est alignĂ© avec le “RFC5322.From”.

DMARC n’exige pas que DKIM et SPF soit valide. Ainsi DMARC peut ainsi trĂšs bien ĂȘtre “PASS” avec un SPF invalide ou avec une signature DKIM invalide !

Plus d’infos dans la RFC7489 : Domain-based Message Authentication, Reporting, and Conformance (DMARC)

Voici un exemple d’enregistrement DNS basique :

1
_dmarc IN TXT "v=DMARC1; p=reject; sp=reject; aspf=s; adkim=s"

On pourra spécifier :

  • p=none si l’on ne veut pas que les emails non conformes soient rejetĂ©s
  • p=reject si l’on veut que les emails non conformes soient rejetĂ©s (rarement utilisĂ©)
  • p=quarantine si l’on veut que les emails non conformes soient mis de cĂŽtĂ© (dans une sous-boĂźte Spam en gĂ©nĂ©ral)

De façon similaire, on peut spĂ©cifier la politique par dĂ©faut pour les sous-domaines avec sp=. En effet, si un enregistrement _dmarc n’est pas trouvĂ© pour un sous-domaine, il interrogera le « top-level domain » (ou encore appelĂ© « organizational domain »).

Attention, si vous spécifiez rua=mailto:dmarc@example.com vous recevrez pas mal de rapports Report domain de Google, Outlook, etc. vous notifiant des emails non conformes. Les rapports incluent un fichier XML, on peut le lire via des outils comme mxtoolbox ou easydmarc.

On pourra aussi spĂ©cifier que l’on veut un alignement entre l’expĂ©diteur d’enveloppe (MAIL FROM: utilisĂ© par SPF) et l’expĂ©diteur d’entĂȘte (From:) :

  • aspf=r : relaxed, on exige un alignement mais cela peut-ĂȘtre des sous-domaines
  • aspf=s : strict, on exige que cela soit exactement le mĂȘme FQDN

De façon similaire, on peut aussi spĂ©cifier que la signature DKIM corresponde bien Ă  l’expĂ©diteur d’entĂȘte (From:) :

  • adkim=r : relaxed, on exige que cela correspond Ă  un domaine ou sous-domaine
  • adkim=s : strict, on exige que cela soit exactement le mĂȘme FQDN

Voici un exemple d’un enregistrement DNS plus avancĂ© :

1
_dmarc IN TXT "v=DMARC1;p=reject;sp=none;rua=mailto:dmarc+aggr@example.com;ruf=mailto:dmarc+forensic@example.com;fo=1;adkim=s;aspf=s;pct=100"

Un outil gĂ©nial pour tester DMARC est https://www.learndmarc.com/ : il faut envoyer un email et l’on a toutes les explications sur SPF / DKIM / DMARC et notamment l’alignement.

Recommandation pour un test complet

Pour vérifier votre serveur Stalwart de maniÚre exhaustive :

  1. MXToolbox → SMTP Diagnostic + MX/SPF/DKIM/DNSBL
  2. mail-tester.com → Envoyer un email rĂ©el pour score de qualitĂ©
  3. GlockApps → Test de livraison vers les grands fournisseurs (Gmail, Outlook, etc.)

Cette combinaison couvre configuration DNS, sécurité SMTP, livraison réelle et scoring anti-spam.

Sauvegarde RocksDB

Stalwart Mail Server utilise RocksDB pour la gestion des paramĂštres dans le dossier /var/lib/stalwart. J’ai testĂ© la sauvegarde puis la restauration de ce dossier en stoppant le service systemd stalwart. Est il possible de faire une sauvegarde du dossier /var/lib/stalwart sans arrĂȘter le service. Si oui , une procĂ©dure de sauvegarde avec roulement, le tout gĂ©rer par un systemd timer

Il est possible de sauvegarder /var/lib/stalwart sans arrĂȘter le service, mais il faut utiliser la fonctionnalitĂ© de checkpoint de RocksDB plutĂŽt qu’une copie directe du dossier, car une copie simple pendant que le service est actif peut entraĂźner une base corruptible car RocksDB Ă©crit continuellement dans ses fichiers (.sst, log, manifest). Copier ces fichiers pendant que le service tourne risque de capturer un Ă©tat incohĂ©rent.

rsync avec arrĂȘt bref (2-3 secondes)

Script backup stalwart: /usr/local/bin/stalwart-backup.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#!/bin/bash
set -e

# Configuration
DB_PATH="/var/lib/stalwart"
BACKUP_BASE="/var/backups/stalwart"
RETENTION_DAYS=7

# Création des répertoires
mkdir -p "$BACKUP_BASE"

# Date de la sauvegarde
DATE=$(date +%Y-%m-%d_%H-%M-%S)
BACKUP_DIR="${BACKUP_BASE}/${DATE}"
PARTIAL_DIR="${BACKUP_DIR}/partial"

echo "=== Sauvegarde Stalwart (rsync avec arrĂȘt bref) ==="
echo "Source : $DB_PATH"
echo "Destination : $BACKUP_DIR"

# Créer le répertoire de sauvegarde
mkdir -p "$BACKUP_DIR"
mkdir -p "$PARTIAL_DIR"

# PremiĂšre synchronisation (service en cours)
echo "Pass 1 : synchronisation initiale (service en cours)"
rsync -a --delete "$DB_PATH/" "$PARTIAL_DIR/"

# ArrĂȘter briĂšvement le service (2-3 secondes)
echo "ArrĂȘt du service stalwart (2-3 secondes)"
systemctl stop stalwart

# Synchronisation finale avec checksum ( fichiers inchangés)
echo "Pass 2 : synchronisation finale avec checksum"
rsync -a --delete --checksum "$DB_PATH/" "$BACKUP_DIR/"

# Redémarrer le service
echo "Redémarrage du service stalwart"
systemctl start stalwart

# Attendre que le service soit démarré
sleep 2

# Supprimer le répertoire partiel
rm -rf "$PARTIAL_DIR"

# Roulement : suppression des anciennes sauvegardes
echo "Roulement : suppression des sauvegardes > $RETENTION_DAYS jours"
find "$BACKUP_BASE" -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} +

# Afficher les sauvegardes restantes
BACKUPS=$(ls -1 "$BACKUP_BASE" | wc -l)
echo ""
echo "Sauvegardes restantes : $BACKUPS"
ls -la "$BACKUP_BASE"

# Afficher la taille de la sauvegarde
SIZE=$(du -sh "$BACKUP_DIR" | cut -f1)
echo "Taille de la sauvegarde : $SIZE"

echo ""
echo "=== Sauvegarde terminée ==="
echo "Répertoire : $BACKUP_DIR"
# Message
curl --ipv4 \
-H "X-Email: ntfy@cinay.eu" \
-H "Title: 🖂 Sauvegarde Stalwart" \
-H "Authorization: Bearer tk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H prio:low \
-d "=== Sauvegarde terminée ===
Répertoire : $BACKUP_DIR" \
https://ntfy.rnmkcy.eu/yan_infos

Service et Timer systemd

/etc/systemd/system/stalwart-backup.service

1
2
3
4
5
6
7
8
9
[Unit]
Description=Sauvegarde Stalwart Mail Server
After=local-fs.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/stalwart-backup.sh
User=root
Group=root

/etc/systemd/system/stalwart-backup.timer

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=Planification sauvegarde Stalwart quotidienne

[Timer]
OnCalendar=daily
OnCalendar=*-*-* 01:10:00
RandomizedDelaySec=30m
Persistent=true
Unit=stalwart-backup.service

[Install]
WantedBy=timers.target

Création script + services + activation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# Créer les scripts pour rsync :
#sudo cp stalwart-backup-rsync.sh /usr/local/bin/stalwart-backup.sh
sudo tee /usr/local/bin/stalwart-backup.sh > /dev/null << 'EOF'
#!/bin/bash
set -e

# Configuration
DB_PATH="/var/lib/stalwart"
BACKUP_BASE="/var/backups/stalwart"
RETENTION_DAYS=7

# Création des répertoires
mkdir -p "$BACKUP_BASE"

# Date de la sauvegarde
DATE=$(date +%Y-%m-%d_%H-%M-%S)
BACKUP_DIR="${BACKUP_BASE}/${DATE}"
PARTIAL_DIR="${BACKUP_DIR}/partial"

echo "=== Sauvegarde Stalwart (rsync avec arrĂȘt bref) ==="
echo "Source : $DB_PATH"
echo "Destination : $BACKUP_DIR"

# Créer le répertoire de sauvegarde
mkdir -p "$BACKUP_DIR"
mkdir -p "$PARTIAL_DIR"

# PremiĂšre synchronisation (service en cours)
echo "Pass 1 : synchronisation initiale (service en cours)"
rsync -a --delete "$DB_PATH/" "$PARTIAL_DIR/"

# ArrĂȘter briĂšvement le service (2-3 secondes)
echo "ArrĂȘt du service stalwart (2-3 secondes)"
systemctl stop stalwart

# Synchronisation finale avec checksum ( fichiers inchangés)
echo "Pass 2 : synchronisation finale avec checksum"
rsync -a --delete --checksum "$DB_PATH/" "$BACKUP_DIR/"

# Redémarrer le service
echo "Redémarrage du service stalwart"
systemctl start stalwart

# Attendre que le service soit démarré
sleep 2

# Supprimer le répertoire partiel
rm -rf "$PARTIAL_DIR"

# Roulement : suppression des anciennes sauvegardes
echo "Roulement : suppression des sauvegardes > $RETENTION_DAYS jours"
find "$BACKUP_BASE" -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} +

# Afficher les sauvegardes restantes
BACKUPS=$(ls -1 "$BACKUP_BASE" | wc -l)
echo ""
echo "Sauvegardes restantes : $BACKUPS"
ls -la "$BACKUP_BASE"

# Afficher la taille de la sauvegarde
SIZE=$(du -sh "$BACKUP_DIR" | cut -f1)
echo "Taille de la sauvegarde : $SIZE"

echo ""
echo "=== Sauvegarde terminée ==="
echo "Répertoire : $BACKUP_DIR"
EOF
sudo chmod +x /usr/local/bin/stalwart-backup.sh

# Créer le service et le timer
sudo tee /etc/systemd/system/stalwart-backup.service > /dev/null << 'EOF'
[Unit]
Description=Sauvegarde Stalwart Mail Server
After=local-fs.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/stalwart-backup.sh
User=root
Group=root
EOF

sudo tee /etc/systemd/system/stalwart-backup.timer > /dev/null << 'EOF'
[Unit]
Description=Planification sauvegarde Stalwart quotidienne

[Timer]
OnCalendar=daily
OnCalendar=*-*-* 01:10:00
RandomizedDelaySec=30m
Persistent=true
Unit=stalwart-backup.service

[Install]
WantedBy=timers.target
EOF

# Activer
sudo systemctl daemon-reload
sudo systemctl enable --now stalwart-backup.timer

# Vérifier
sudo systemctl list-timers stalwart-backup.timer

Le service est actif

1
2
NEXT                         LEFT LAST PASSED UNIT                  ACTIVATES              
Sat 2026-06-13 00:27:02 CEST  10h -         - stalwart-backup.timer stalwart-backup.service

Pour info: comparaison des méthodes

MĂ©thode ArrĂȘt service CohĂ©rence DĂ©pendances
btrfs snapshot ❌ Non ✅ 100% cohĂ©rent btrfs seulement
rsync + arrĂȘt bref ⚠ 2-3 sec ✅ CohĂ©rent rsync (dĂ©jĂ  installĂ©)
ArrĂȘt complet ✅ 10-30 sec ✅ 100% cohĂ©rent cp (dĂ©jĂ  installĂ©)

btrfs snapshot n’est pas disponible, on utilise rsync avec arrĂȘt bref (2-3 secondes d’arrĂȘt est acceptable pour une sauvegarde quotidienne Ă  1h10 du matin).

Lancement manuel

On va lancer la procédure manuellement pour vérifier son fonctionnement

1
sudo /usr/local/bin/stalwart-backup.sh

Déroulement du script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
=== Sauvegarde Stalwart (rsync avec arrĂȘt bref) ===
Source : /var/lib/stalwart
Destination : /var/backups/stalwart/2026-06-12_14-08-05
Pass 1 : synchronisation initiale (service en cours)
ArrĂȘt du service stalwart (2-3 secondes)
Pass 2 : synchronisation finale avec checksum
Redémarrage du service stalwart
Roulement : suppression des sauvegardes > 30 jours

Sauvegardes restantes : 1
total 12
drwxr-xr-x 3 root     root     4096 12 juin  14:08 .
drwxr-xr-x 3 root     root     4096 12 juin  14:08 ..
drwxr-x--- 2 stalwart stalwart 4096 12 juin  10:48 2026-06-12_14-08-05
Taille de la sauvegarde : 88M

=== Sauvegarde terminée ===
Répertoire : /var/backups/stalwart/2026-06-12_14-08-05

Simuler rotation des dossiers

Le find ne supprime que les dossiers dont le mtime est strictement supérieur à 30 jours (-mtime +30).

Pour afficher ce qui serait supprimé sans rien effacer :

1
2
3
BACKUP_BASE="/var/backups/stalwart"
RETENTION_DAYS=7
find "$BACKUP_BASE" -maxdepth 1 -type d -mtime +$RETENTION_DAYS -printf '%p %TY-%Tm-%Td %TH:%TM:%TS\n'

Maintenance

Configuration Active Stalwart web UI

Actualisation: 19/06/2026

Settings → Sieve → System scripts

reject-forged-recipients

Rejeter si adresse visible différente adresse réelle

Settings → Sieve → System scripts reject-forged-recipients

Test sur le serveur de messagerie

1
swaks   --server yannig.net:25   --from idcywlf@zirenma.tech   --to yani@cinay.eu   --data @Message-FORGED-2026-06-18-1414.eml

Résultat commande

1
<** 550 5.7.1 Message rejected due to excessive spam score.

Chercher dans les logs en mode debug

1
grep "reject" /var/log/stalwart/stalwart.2026-06-19

Résultat de la recherche

1
2026-06-19T04:33:38Z DEBUG Classifying message for spam (spam.classify) listenerId = "smtp", localPort = 25, remoteIp = fe80::f816:3eff:fe25:b53a, remotePort = 37708, queueId = 313657628479717376, result = "reject", reason = "Message rejected due to excessive spam score."

phishing_gouv

Filtrer/rejeter automatiquement les e-mails de phishing prétendant provenir de gouv.fr

Settings → Sieve → System scripts phishing_gouv

Test sur le serveur de messagerie

1
2
3
4
5
6
7
swaks --server yannig.net:25 \
  --from "amendes-antai-gouv@oglix.ba" \
  --to "yani@cinay.eu" \
  --header "From: Agence Nationale de Traitement Automatisé des Infractions <amendes-antai-gouv@oglix.ba>" \
  --header "Subject: ANTAI - test phishing" \
  --header "Authentication-Results: yannig.net; dkim=pass header.d=oglix.ba; spf=pass smtp.mailfrom=oglix.ba; dmarc=none header.from=oglix.ba" \
  --data "Ceci est un test."

Settings → Spam Filter → General

Reject threshold

Settings → Spam Filter → General Reject threshold =1

Cet article est sous licence CC BY 4.0 par l'auteur.