POST-DEPLOY — Dernier point rouge : PTR (reverse DNS) & sort des héritages

📄 Source : playbook/POST-DEPLOY.md 🕒 Généré le 06/08/2026 09:56
Sommaire

État au 05/08/2026 : l'infrastructure CAPBE est entièrement déployée et validée. Évolutions : le serveur de messagerie possède son IP publique dédiée (51.79.11.52, NIC routée Incus) — le mail entre et sort par sa propre IP — et le domaine mail est capbe.ovh (racine de la zone) : boîtes @capbe.ovh, serveur mail.capbe.ovh. Bascule « 1 IP » (05/08/2026) : TOUTE la messagerie (webmail SnappyMail, JMAP, autoconfig/autodiscover, protocoles SMTP/IMAP/POP3) est servie DIRECTEMENT par capbe-mail sur 51.79.11.52 — Caddy interne + certificat wildcard Let's Encrypt. webmail/autoconfig/autodiscover.capbe.ovh résolvent vers .52 ; le forward 51.79.11.50 ne sert plus que les applications web. Les anciens noms *.ci.capbe.ovh ont été supprimés (clients à reconfigurer).

⚠️ Le forward public (51.79.11.50 → 10.10.10.31, créé uniquement côté Incus, web UI) ne porte plus QUE le web (80/443 → caddy, applications odoo/meca/agro) : les ports mail en ont été retirés (05/08/2026). Toutes les vérifications du smoke-test sont en lecture seule.


1. Pourquoi une seule IP pour le mail (51.79.11.52) ?

IP Rôle
51.79.11.52 IP dédiée du serveur mail (NIC routée Incus) — TOUT le mail : SORTIE (egress, vue dans le header Received), entrée (SMTP/IMAP/POP3/JMAP) et le web du mail (webmail, autoconfig/autodiscover — Caddy interne + TLS wildcard)
51.79.11.50 Adresse d'écoute du forward Incus — applications WEB uniquement (odoo/meca/agro, 80/443 → caddy). Plus aucun port mail (retirés le 05/08/2026)
192.99.150.151 IP principale de l'hôte — ne sert plus au mail (bascule « IP dédiée »)

Un PTR manquant sur l'IP sortante fait plonger le score de réputation (mail-tester.com, Gmail, Outlook…) : envois dégradés/spam. PTR attendu : - 51.79.11.52 (egress)mail.capbe.ovh (mail.capbe.ovh résout vers cette IP — FCrDNS validé par OVH, constaté en réel).

PTR de 51.79.11.50 : purement web, aucun lien avec le mail. Depuis la bascule « 1 IP », il pointe vers ci.capbe.ovh (corrigé le 05/08/2026 : il indiquait encore webmail.capbe.ovh — un nom lié au mail qui résout désormais vers .52, FCrDNS cassé). .50 ne sert que les applications web (odoo/meca/agro, hub ci) : son PTR ne doit JAMAIS nommer un hôte mail (mail.*, webmail.*…), le mail vit uniquement sur 51.79.11.52.

2. Procédure (API OVH — recommandée)

Le jeton OVH avec les droits /ip/* fait tout (le publish-mail-dns.sh le tente automatiquement, best effort) :

sudo ./publish-mail-dns.sh   # A mail/webmail/autoconfig/autodiscover → 51.79.11.52 ; PTR 51.79.11.52 → mail.capbe.ovh

NB : OVH exige que le hostname du PTR RÉSOLVE vers l'IP (contrôle FCrDNS) — c'est pourquoi mail.capbe.ovh résout vers l'IP dédiée 51.79.11.52. Depuis la bascule « 1 IP », les scripts publient A mail/webmail/autoconfig/ autodiscoverIP dédiée quand l'egress détectée depuis capbe-mail est une IP locale du conteneur (NIC routée), sinon → PUBLIC_IP (repli forward, PTR via mail-out.capbe.ovh).

À la main (si pas de jeton /ip/*) : manager OVH → Serveurs → IP → Configurer le reverse → mail.capbe.ovh pour 51.79.11.52.

3. Vérification

dig +short -x 51.79.11.52        # attendu : mail.capbe.ovh.     (IP dédiée mail — egress)
dig +short A mail.capbe.ovh       # attendu : 51.79.11.52
dig +short A webmail.capbe.ovh    # attendu : 51.79.11.52 (depuis la bascule « 1 IP »)
dig +short A autoconfig.capbe.ovh # attendu : 51.79.11.52
dig +short A autodiscover.capbe.ovh # attendu : 51.79.11.52
dig +short MX capbe.ovh           # attendu : 10 mail.capbe.ovh.
sudo ./smoke-test.sh              # le check PTR de l'egress passe au vert → tout est vert

Le smoke-test vérifie le PTR de l'IP sortante (déduite du SPF ip4: → attendu mail.capbe.ovh) et les A des hôtes mail (webmail/autoconfig/ autodiscover → IP dédiée) — lecture seule.

4. Test de délivrabilité final — mail-tester.com

4a. Vérifications préalables (depuis l'hôte — records DNS verts avant l'envoi)

# Le smoke-test intègre désormais les checks A + SRV + PTR (tout le §3) :
# (le nombre de checks dépend des conditions : A mail dédiée = si egress locale
# à capbe-mail, PTR = 1 ou 2 IP, boucle mail = optionnelle --mail-loop)
sudo ./smoke-test.sh            # tout vert attendu (hors PTR si encore en attente OVH)

# Contrôle manuel des records clés (propagation DNS, ~5–60 min après publication) :
dig +short MX capbe.ovh                        # attendu : 10 mail.capbe.ovh.
dig +short TXT capbe.ovh                       # attendu : "v=spf1 mx ip4:<egress> -all" (egress = 51.79.11.52)
dig +short TXT _dmarc.capbe.ovh                # attendu : "v=DMARC1; p=quarantine; ..."
dig +short TXT <sélecteur>._domainkey.capbe.ovh  # attendu : "v=DKIM1; k=...; p=..." (admin Stalwart → Domaines)
dig +short A mail.capbe.ovh                    # attendu : 51.79.11.52 (IP dédiée mail)
dig +short A webmail.capbe.ovh                 # attendu : 51.79.11.52 (IP dédiée mail — bascule « 1 IP »)
dig +short SRV _imap._tcp.capbe.ovh            # attendu : 0 0 993 mail.capbe.ovh.
dig +short SRV _submission._tcp.capbe.ovh      # attendu : 0 0 587 mail.capbe.ovh.
# PTR (IP sortante uniquement) :
dig +short -x 51.79.11.52                     # attendu : mail.capbe.ovh.    (egress / IP dédiée)

SPF vérifié côté récepteur : l'envoi sort de l'egress 51.79.11.52, qui est bien listée en ip4: dans le SPF — sinon les serveurs stricts répondent 550 SPF fail (constaté en réel, mail-tester.com).

4b. Envoi du test mail-tester

# 1. Ouvre https://www.mail-tester.com → note l'adresse jetable (ex. test-xxxx@mail-tester.com)
# 2. Depuis le serveur, envoie un mail via le relais local (SMTP 587 STARTTLS) :
# NB : le mot de passe passe par une variable d'environnement (--env), PAS en
# argument de python3 — un argv serait visible dans `ps aux` du conteneur.
incus exec capbe-mail --env MAIL_PASS="$(grep '^MAIL_ADMIN_PASS=' playbook/config/secrets.env | cut -d'"' -f2)" -- \
  python3 - "admin@capbe.ovh" "test-xxxx@mail-tester.com" <<'PY'
import smtplib, os, sys
sender, dest = sys.argv[1], sys.argv[2]
pw = os.environ["MAIL_PASS"]
s = smtplib.SMTP("127.0.0.1", 587, timeout=15)
s.ehlo(); s.starttls(); s.ehlo()
s.login(sender, pw)
s.sendmail(sender, [dest], "Subject: CAPBE deliverability test\n\nTest final\n")
s.quit(); print("ENVOYE")
PY
# 3. Clique « Then check your score » sur mail-tester.com

Critère de validation : score ≥ 9/10 (SPF ✓, DKIM ✓, DMARC ✓, PTR ✓). Si un point reste faible, voir DEPLOY.md → « Pièges connus » (SPF / PTR).

Après la bascule du domaine (ci.capbe.ovhcapbe.ovh), refais ce test avec une adresse @capbe.ovh : le score dépend du domaine vu dans l'enveloppe (From), donc du domaine actif dans Stalwart.

4c. Audit automatique — audit-deliverability.sh (rejouable)

Le score mail-tester n'est plus affichable en gratuit (paywall). Pour un audit automatisé et rejouable : audit-deliverability.sh vérifie pour CHAQUE compte (admin@, odoo@, meca@, agro@capbe.ovh) :

  • A. auth SMTP 587 STARTTLS + envoi réel (chemin complet : mail.capbe.ovh → Stalwart → signature DKIM → cible)
  • B. sonde d'enveloppe vers le MX Gmail depuis l'egress réelle (MAIL FROM / RCPT — sans DATA, donc aucune livraison)
  • C. chaîne DNS : MX, SPF, DMARC, sélecteurs DKIM (publiés vs DNS), PTR / FCrDNS
sudo ./audit-deliverability.sh                       # cible interne admin@capbe.ovh (aucun mail externe)
sudo ./audit-deliverability.sh monadresse@gmail.com  # audit côté récepteur (4 mails envoyés)

Interprétation : tout « AUTH OK + envoi OK » et « MAIL FROM 250 » = délivrabilité OK côté émetteur ; la chaîne DNS verte (SPF ip4:<egress>, DKIM publié, DMARC, PTR + FCrDNS cohérent) = ce que verra le récepteur. Pour la preuve visuelle (SPF/DKIM/DMARC: PASS), ouvrir un mail reçu → ⋮ → Afficher l'original. Aucune boîte externe n'est requise pour l'audit de base.

5. Migration du domaine mail vers capbe.ovh

Décision : le domaine des boîtes est passé de ci.capbe.ovh à capbe.ovh (racine de la zone OVH). En résumé :

  1. Stalwart : defaultDomaincapbe.ovh, serverHostnamemail.capbe.ovh, compte admin@capbe.ovh (ancien compte à supprimer).
  2. DNS : records déplacés à la RACINE de la zone capbe.ovh (A mail / webmail / autoconfig / autodiscover, MX, SPF TXT, _dmarc, DKIM *._domainkey, SRV _imap._tcp etc.) — publier avec sudo ./publish-mail-dns.sh.
  3. Caddyfile : blocs mail / webmail / autoconfig / autodiscover en .capbe.ovh ; sudo ./09-caddy-config.sh.
  4. Suppression des anciens records/noms *.ci.capbe.ovh (choix : pas d'alias — reconfigurer les clients mail : serveur mail.capbe.ovh, adresses @capbe.ovh).
  5. Certificat wildcard Stalwart : -d capbe.ovh -d '*.capbe.ovh' (DNS-01 OVH, zone racine).

⚠️ La bascule du domaine mail est sans retour pour les adresses : un ancien mail @ci.capbe.ovh ne sera plus délivré (ou à re-router via un alias Stalwart si nécessaire).

5bis. Guide de reconfiguration des clients mail

Après la bascule, chaque client (Thunderbird, Outlook, mobiles, webmail) doit être reconfiguré — les anciens réglages @ci.capbe.ovh / mail.ci.capbe.ovh ne fonctionnent plus (anciens noms supprimés).

Réglages universels (tous les clients) :

Champ Valeur
Adresse e-mail admin@capbe.ovh (et toute boîte @capbe.ovh)
Serveur entrant (IMAP) mail.capbe.ovh — port 993, SSL/TLS
Serveur sortant (SMTP) mail.capbe.ovh — port 587, STARTTLS (ou 465 SSL)
Nom d'utilisateur l'adresse e-mail complète
Webmail https://webmail.capbe.ovh

Configuration automatique (recommandée) : Thunderbird et la plupart des clients mobiles détectent tout seuls via les records publiés :

  • Thunderbird : Fichier → Nouveau → Compte existant → saisir l'adresse admin@capbe.ovh → Thunderbird interroge autoconfig.capbe.ovh et pré-remplit IMAP 993 / SMTP 587 (mail.capbe.ovh). Vérifier que le mot de passe est demandé, puis valider.
  • Outlook (Windows/Mac) : Fichier → Comptes → Ajouter un compte → l'autodiscovery (autodiscover.capbe.ovh + SRV _autodiscover._tcp) pré-remplit IMAP/SMTP.
  • Mobiles (Android/iOS) : ajouter un compte e-mail « manuel » avec les réglages ci-dessus, ou scanné depuis le webmail si SnappyMail l'expose.

Pièges à vérifier après reconfiguration :

  • L'ancienne boîte @ci.capbe.ovh ne reçoit plus rien — récupérer les mails importants AVANT la bascule, ou créer un alias Stalwart @ci.capbe.ovh@capbe.ovh si un relais temporaire est nécessaire.
  • Vérifier l'envoi : SMTP 587 STARTTLS avec le mot de passe de admin@capbe.ovh (jamais en clair sur le réseau — le STARTTLS est obligatoire).
  • Un client configuré en POP3 verra aussi le serveur mail.capbe.ovh : 995 SSL ou 110 STARTTLS.
  • L'assistant d'un client peut écrire mail.capbe.ovh en mail.capbe.ovh:587 ou en SSL 465 — les deux écoutent sur capbe-mail.

5ter. Séquence opératoire de bascule (à lancer sur l'hôte, dans l'ordre)

cd /data/CAPBE/playbook

# 1. Publication DNS — records capbe.ovh (A mail → IP dédiée détectée auto),
#    MX/SPF/DMARC/DKIM/SRV + nettoyage des anciens records *.ci.capbe.ovh
#    + PTR best-effort (jeton /ip/* requis pour les PTR) :
sudo ./publish-mail-dns.sh

# 2. Déploiement du Caddyfile (blocs mail/webmail/autoconfig/autodiscover en
#    .capbe.ovh, anciens noms supprimés) + rechargement caddy :
sudo ./09-caddy-config.sh

# 3. Smoke-test — tout doit être vert (records A/SRV/PTR + points d'entrée) :
sudo ./smoke-test.sh
#    Boucle mail réelle (SMTP 587 → IMAP 993, message relu) :
sudo ./smoke-test.sh --mail-loop

# 4. Délivrabilité — §4 : audit automatique (audit-deliverability.sh) ou
#    mail-tester.com (score ≥ 9/10) — voir §4b/4c ci-dessus

# 5. Reconfiguration des clients mail (@capbe.ovh / mail.capbe.ovh) — §5bis

Si le jeton OVH n'a pas les droits d'écriture (mode manuel affiché par publish-mail-dns.sh), crée les records listés dans l'espace client OVH puis relance publish-mail-dns.sh (idempotent — ne crée que les manquants).

6. Sort des conteneurs héritage (agrimeca / agroworoba) — ✅ DÉCOMMISSIONNÉ

⚠️ Décision manuelle, uniquement APRÈS : smoke-test 100 % vert et mail-tester ≥ 9/10. Les projets migrés (capbe-meca / capbe-agro) sont déjà autonomes sur pgis/odoo/fronts.

✅ État au 05/08/2026 — décommissionnement effectué

Les conteneurs héritage agrimeca et agroworoba ne sont plus présents sur l'hôte (vérifié le 05/08/2026) :

  • incus list → aucun conteneur agrimeca / agroworoba (seuls les 7 conteneurs capbe-* tournent, plus 2 hors périmètre arrêtés : db, ubt)
  • crontab -l → aucune tâche résiduelle référençant les anciens noms
  • /var/backups/ → aucun répertoire de sauvegarde hérité

Les bases migrées (meca_api, agro_api, tenants Odoo meca/agro) tournent sur capbe-pgis/capbe-odoo ; le décommissionnement n'a affecté aucun service CAPBE (réseau capbe-br0 séparé). Un dump SQL de sauvegarde agro avait été committé dans le dépôt source avant suppression (CAPBE-AGRO/src — « chore: sauvegarde dumps SQL agro avant décommissionnement agroworoba »).

📜 Procédure d'origine (trace pour un autre projet / ré-exploitation)

Par conteneur hérité, dans l'ordre :

incus stop agrimeca              # 1. arrêt propre → observer quelques jours
incus start agrimeca             #    (si besoin de vérifier quelque chose)
# 2. après période d'observation sans régression sur capbe-meca :
incus delete agrimeca            # 3. suppression définitive (irréversible !)
# 4. nettoyage : vérifier l'absence de crons / sauvegardes / scripts
#    référençant l'ancien nom (grep -i 'agri\|woroba' crontab, /var/backups)
# Répéter pour agroworoba → capbe-agro

Règle d'or : ne supprimer un héritage qu'après la validation finale (smoke-test vert + mail-tester ≥ 9/10). Pour CAPBE, cette étape est faite.

7. Récapitulatif de l'état au 05/08/2026

Vérification Résultat
Smoke-test 27 OK / 0 échec (05/08, après correction du check PTR — dig +short -x requis)
Boucle mail SMTP 587 → IMAP 993 ✅ message relu
Smoke-test --app-accounts (§7) ✅ auth SMTP 587 des 4 comptes applicatifs (login seul, aucun envoi)
Comptes applicatifs (odoo@/meca@/agro@capbe.ovh) ✅ créés sur Stalwart (587 STARTTLS, MAIL_APP_*_PASS générés) — Odoo meca/agro + MECA API envoient leurs mails via capbe-mail
Audit de délivrabilité (audit-deliverability.sh) ✅ 4/4 comptes AUTH + envoi OK + sonde MX Gmail 250/250 (egress .52) + chaîne DNS verte (SPF/DKIM/DMARC/PTR FCrDNS)
Délivrabilité réelle (Gmail) Boîte de réception + SPF/DKIM/DMARC : PASS (confirmé par l'utilisateur)
SPF / MX / DKIM / DMARC / SRV ✅ publiés et corrects
PTR 51.79.11.52 (IP dédiée mail) actifmail.capbe.ovh (vérifié : NS autoritaires OVH + résolveurs publics)
Bascule « 1 IP » 05/08/2026 — tout le mail sur 51.79.11.52 ; forward .50 : apps web uniquement (ports mail retirés)
Mail : IP dédiée + egress 51.79.11.52 (NIC routée Incus, egress vérifié)
Domaine mail capbe.ovh (boîtes @capbe.ovh, hôte mail.capbe.ovh, anciens noms *.ci.capbe.ovh supprimés)
Webmail ✅ servi directement par capbe-mail sur l'IP dédiée (Caddy interne + TLS wildcard)
Admin Stalwart https://admin-mail.capbe.ovh (→ /admin/ ; UI de gestion des domaines/comptes/DKIM — proxysée par le Caddy interne, TLS wildcard). Connexion : utilisateur admin + mot de passe de récupération (STALWART_RECOVERY_ADMIN dans /opt/stalwart/etc/stalwart.env sur capbe-mail — ≠ MAIL_ADMIN_PASS)
Routage entrant IP dédiée (ufw) corrigé le 06/08/2026 — règles ufw route allow to/from 51.79.11.52 ; le trafic ENTRANT était DROPPÉ par FORWARD (admin-mail/webmail/mail injoignables de l'extérieur, ERR_CONNECTION_TIMED_OUT)
Cron sauvegardes 02h00 + kits 02h30/02h45 ✅ confirmés (crontab root)
Check-nightly kits (07h30/07h35) ✅ nuit saine (05/08, meca + agro)
Monitoring 5 min + alertes mail ✅ aucun signal sur 24 h
Sort des héritages agrimeca/agroworoba décommissionnés (05/08, aucun résidu)
Forward public (créé uniquement côté Incus) ✅ 80/443 → caddy (apps web) — plus aucun port mail

⚠️ Incident 06/08/2026 — routage entrant de l'IP dédiée 51.79.11.52. Avec ufw actif et sa politique « deny routed » par défaut, le trafic entrant vers la NIC routée (IP dédiée de capbe-mail) était DROPPÉ par la chaîne FORWARD de l'hôte : seules les règles SORTANTES (-s 51.79.11.52) existaient → https://admin-mail.capbe.ovh (et webmail, SMTP/IMAP entrants) répondaient localement mais restaient injoignables depuis Internet (ERR_CONNECTION_TIMED_OUT). Diagnostic : les SYN arrivaient bien sur eno1 (tcpdump) mais n'atteignaient jamais le veth du conteneur. Correction (appliquée, idempotente dans 07-mail.sh §6b) :

bash sudo ufw route allow to 51.79.11.52 # trafic entrant → IP dédiée (indispensable) sudo ufw route allow from 51.79.11.52 # trafic sortant (parité)

Vérifié depuis Internet (check-host.net) : 443, 25 et 587 joignables. Le playbook (07-mail.sh §6b) recrée ces règles à chaque déploiement quand l'IP dédiée est détectée (NIC routée) — rien à faire manuellement en re-run.