fix(mail): certificat TLS de poste.io synchronisé depuis CapRover
Le certificat de mail.sans.pub servi par poste.io avait expiré le 2021-02-06 : son renouvellement Let's Encrypt intégré ne peut pas fonctionner derrière le nginx de CapRover. Le script mail/mail-cert-sync.sh (cron quotidien) copie désormais le certificat renouvelé par CapRover et recharge Dovecot/Haraka. L'alerte du backup n'a plus besoin de -k. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f974203973
commit
3fc9ae52c9
@@ -117,11 +117,18 @@ Endpoints utiles :
|
|||||||
- Particularités des bases : `limesurvey-mariadb-db` n'accepte root qu'en TCP (`-h127.0.0.1`, le mot de passe de `root@localhost` est différent) ; `writefreely-db` a une table `mysql.proc` incompatible (dump sans `--routines`). Le script essaie automatiquement ces variantes
|
- Particularités des bases : `limesurvey-mariadb-db` n'accepte root qu'en TCP (`-h127.0.0.1`, le mot de passe de `root@localhost` est différent) ; `writefreely-db` a une table `mysql.proc` incompatible (dump sans `--routines`). Le script essaie automatiquement ces variantes
|
||||||
- Premier snapshot complet : 2026-10-03 (~53 Gio, ~45 Gio stockés) ; restauration testée (`restic dump` + comparaison SHA256)
|
- Premier snapshot complet : 2026-10-03 (~53 Gio, ~45 Gio stockés) ; restauration testée (`restic dump` + comparaison SHA256)
|
||||||
- Rétention : 7 quotidiens, 4 hebdos, 6 mensuels ; `prune` + `check` (5 % des données) le dimanche
|
- Rétention : 7 quotidiens, 4 hebdos, 6 mensuels ; `prune` + `check` (5 % des données) le dimanche
|
||||||
- Log : `/var/log/restic-backup.log` ; mail à `pierre@sans.pub` en cas d'échec (via SMTP de poste.io avec `curl -k` car son certificat a expiré, donc **pas d'alerte si le serveur entier tombe**)
|
- Log : `/var/log/restic-backup.log` ; mail à `pierre@sans.pub` en cas d'échec (via SMTP de poste.io `mail.sans.pub:465`, donc **pas d'alerte si le serveur entier tombe**)
|
||||||
- Consulter : `ssh sans.pub 'sudo bash -c ". /root/restic/env && restic snapshots"'`
|
- Consulter : `ssh sans.pub 'sudo bash -c ". /root/restic/env && restic snapshots"'`
|
||||||
- **Ancien système (arrêté)** : Duplicity (`tecnativa/duplicity`) configuré dans `/root/backup/` sur le serveur (`docker-compose.yaml` + `config.json`, nov. 2020) → OVH Public Cloud Archive `backup-principal` (données) + Swift `backup-principal-metadata` (manifestes), région GRA. Conteneur et image absents du serveur au 2026-10-03 : plus aucun backup automatique. Ces deux fichiers contiennent des secrets (identifiants OVH, passphrase de chiffrement) — ne jamais les afficher ni les versionner.
|
- **Ancien système (arrêté)** : Duplicity (`tecnativa/duplicity`) configuré dans `/root/backup/` sur le serveur (`docker-compose.yaml` + `config.json`, nov. 2020) → OVH Public Cloud Archive `backup-principal` (données) + Swift `backup-principal-metadata` (manifestes), région GRA. Conteneur et image absents du serveur au 2026-10-03 : plus aucun backup automatique. Ces deux fichiers contiennent des secrets (identifiants OVH, passphrase de chiffrement) — ne jamais les afficher ni les versionner.
|
||||||
- Suites (Vaultwarden, alerte externe, rotation des identifiants OVH) : voir `plan-migration.md`, phase 0.
|
- Suites (Vaultwarden, alerte externe, rotation des identifiants OVH) : voir `plan-migration.md`, phase 0.
|
||||||
|
|
||||||
|
## Mail (poste.io) — certificat TLS
|
||||||
|
|
||||||
|
- poste.io (`analogic/poste.io:2.4.11`) est derrière le nginx de CapRover : son renouvellement Let's Encrypt intégré ne fonctionne pas (certificat resté expiré du 2021-02-06 au 2026-10-03)
|
||||||
|
- Solution (2026-10-03) : `/root/mail-cert-sync.sh` (source : `mail/mail-cert-sync.sh`), cron `/etc/cron.d/mail-cert-sync` à 04:15. Si le certificat `mail.sans.pub` renouvelé par CapRover (`/captain/data/letencrypt/etc/live/mail.sans.pub/`) diffère de `/data/ssl/server.crt` de poste.io : copie + `21-certificate.sh` + rechargement Dovecot (SIGHUP) + redémarrage Haraka (quelques secondes). Log : `/var/log/mail-cert-sync.log`
|
||||||
|
- Le certificat ne couvre que **`mail.sans.pub`** : configurer les clients mail avec ce nom (pas `smtp.sans.pub`, qui donnerait une erreur de nom)
|
||||||
|
- Vérifier : `echo | openssl s_client -connect mail.sans.pub:993 2>/dev/null | openssl x509 -noout -enddate`
|
||||||
|
|
||||||
## Nextcloud — détails techniques
|
## Nextcloud — détails techniques
|
||||||
|
|
||||||
- **Cron** : service CapRover `nextcloud-cron` (image perso `img-captain-nextcloud-cron:4`, PHP 8.1, mai 2023 — Nextcloud lui-même tourne en PHP 8.3) qui monte le même volume `nextcloud-data` et lance `cron.php` toutes les 5 min. Mode `backgroundjobs_mode = cron`.
|
- **Cron** : service CapRover `nextcloud-cron` (image perso `img-captain-nextcloud-cron:4`, PHP 8.1, mai 2023 — Nextcloud lui-même tourne en PHP 8.3) qui monte le même volume `nextcloud-data` et lance `cron.php` toutes les 5 min. Mode `backgroundjobs_mode = cron`.
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ notify_failure() {
|
|||||||
pass=$(sed -n 's/^ *SMTP_PASS: *//p' /root/backup/docker-compose.yaml)
|
pass=$(sed -n 's/^ *SMTP_PASS: *//p' /root/backup/docker-compose.yaml)
|
||||||
printf 'From: system@sans.pub\r\nTo: %s\r\nSubject: [sans.pub] ECHEC backup restic\r\n\r\n%s\r\n\r\nVoir %s sur le serveur.\r\n' \
|
printf 'From: system@sans.pub\r\nTo: %s\r\nSubject: [sans.pub] ECHEC backup restic\r\n\r\n%s\r\n\r\nVoir %s sur le serveur.\r\n' \
|
||||||
"$MAIL_TO" "$(printf '%s\n' "${ERRORS[@]}")" "$LOG" |
|
"$MAIL_TO" "$(printf '%s\n' "${ERRORS[@]}")" "$LOG" |
|
||||||
# -k : le certificat de poste.io a expiré (2021-02-06) ; connexion vers ce même serveur
|
curl -sS --url smtps://mail.sans.pub:465 --mail-from system@sans.pub --mail-rcpt "$MAIL_TO" \
|
||||||
curl -sS -k --url smtps://smtp.sans.pub:465 --mail-from system@sans.pub --mail-rcpt "$MAIL_TO" \
|
|
||||||
--user "system@sans.pub:$pass" --upload-file - || echo "envoi du mail d'alerte impossible"
|
--user "system@sans.pub:$pass" --upload-file - || echo "envoi du mail d'alerte impossible"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Synchronise le certificat Let's Encrypt de mail.sans.pub (renouvelé par CapRover)
|
||||||
|
# vers poste.io, qui ne sait pas le renouveler lui-même derrière le nginx de CapRover.
|
||||||
|
# Installé dans /root/mail-cert-sync.sh, lancé chaque jour par /etc/cron.d/mail-cert-sync
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
LIVE=/captain/data/letencrypt/etc/live/mail.sans.pub
|
||||||
|
SSL=/var/lib/docker/volumes/captain--mail-data/_data/ssl
|
||||||
|
LOG=/var/log/mail-cert-sync.log
|
||||||
|
exec >> "$LOG" 2>&1
|
||||||
|
|
||||||
|
# Déjà à jour ?
|
||||||
|
if cmp -s "$LIVE/cert.pem" "$SSL/server.crt"; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
openssl x509 -in "$LIVE/cert.pem" -noout -checkend 86400 \
|
||||||
|
|| { echo "$(date -Is) certificat CapRover expiré ou invalide, rien fait"; exit 1; }
|
||||||
|
|
||||||
|
echo "$(date -Is) nouveau certificat : $(openssl x509 -in "$LIVE/cert.pem" -noout -enddate)"
|
||||||
|
stamp=$(date +%Y%m%d%H%M%S)
|
||||||
|
for f in server.crt server.key ca.crt; do
|
||||||
|
[ -f "$SSL/$f" ] && cp -p "$SSL/$f" "$SSL/$f.bak-$stamp"
|
||||||
|
done
|
||||||
|
install -m 644 -o mail -g mail "$LIVE/cert.pem" "$SSL/server.crt"
|
||||||
|
install -m 644 -o mail -g mail "$LIVE/chain.pem" "$SSL/ca.crt"
|
||||||
|
install -m 600 -o mail -g mail "$LIVE/privkey.pem" "$SSL/server.key"
|
||||||
|
# Garder seulement les 3 dernières sauvegardes de chaque fichier
|
||||||
|
for f in server.crt server.key ca.crt; do
|
||||||
|
ls -1t "$SSL/$f".bak-* 2>/dev/null | tail -n +4 | xargs -r rm -f
|
||||||
|
done
|
||||||
|
|
||||||
|
# Distribution dans le conteneur (script d'init de poste.io) puis rechargement des services TLS
|
||||||
|
M=$(docker ps -q -f name=srv-captain--mail)
|
||||||
|
docker exec "$M" bash /etc/cont-init.d/21-certificate.sh
|
||||||
|
docker exec "$M" s6-svc -h /var/run/s6/services/dovecot # IMAP/POP : relecture à chaud
|
||||||
|
docker exec "$M" s6-svc -t /var/run/s6/services/haraka-smtp # SMTP 25/465 : redémarrage (quelques s)
|
||||||
|
docker exec "$M" s6-svc -t /var/run/s6/services/haraka-submission # SMTP 587
|
||||||
|
echo "$(date -Is) certificat installé et services rechargés"
|
||||||
+1
-1
@@ -175,7 +175,7 @@ Le changement d'IP est le principal risque :
|
|||||||
|
|
||||||
## 4. Problèmes découverts en route (2026-10-03)
|
## 4. Problèmes découverts en route (2026-10-03)
|
||||||
|
|
||||||
- [ ] **Certificat TLS de poste.io expiré depuis le 2021-02-06** (`CN=mail.sans.pub`, ports 465/587/993) — les clients mail l'acceptent malgré tout ; à renouveler (poste.io gère Let's Encrypt lui-même, ou via les certificats CapRover montés dans `/my-certs`)
|
- [x] Certificat TLS de poste.io expiré depuis le 2021-02-06 — corrigé le 2026-10-03 en réutilisant le certificat CapRover, synchronisation quotidienne (voir `CLAUDE.md` § Mail). Dans la nouvelle archi, prévoir le certificat du mail dès le départ (Caddy ne sert pas les ports mail)
|
||||||
- [ ] `writefreely-db` (MariaDB 10.7) : table système `mysql.proc` incompatible → lancer `mariadb-upgrade` (ou corriger lors de la migration par dump/restore)
|
- [ ] `writefreely-db` (MariaDB 10.7) : table système `mysql.proc` incompatible → lancer `mariadb-upgrade` (ou corriger lors de la migration par dump/restore)
|
||||||
- [ ] `limesurvey-mariadb-db` : `root@localhost` et `root@%` ont des mots de passe différents → à harmoniser (ou ignorer : réglé à la migration)
|
- [ ] `limesurvey-mariadb-db` : `root@localhost` et `root@%` ont des mots de passe différents → à harmoniser (ou ignorer : réglé à la migration)
|
||||||
- [x] Cron Nextcloud en panne du 2026-08-09 au 2026-10-03 (DNS overlay perdu) — corrigé, voir `CLAUDE.md`
|
- [x] Cron Nextcloud en panne du 2026-08-09 au 2026-10-03 (DNS overlay perdu) — corrigé, voir `CLAUDE.md`
|
||||||
|
|||||||
Reference in New Issue
Block a user