Guide pratique pour faire évoluer l'application capbe-meca. Les mêmes
commandes servent avec ou sans IA : une IA (agent de code) peut manipuler
les fichiers locaux puis utiliser les scripts deploy/ pour publier.
Règle d'or : jamais d'édition directe dans les conteneurs. On travaille en local (kit + source dev), puis on publie avec les scripts.
🚀 05/08/2026 — Journée messagerie (bascule « 1 IP » + comptes applicatifs)
- Bascule « 1 IP » : tout le mail CAPBE passe par l'IP dédiée
51.79.11.52de capbe-mail (egress + entrée + webmail).51.79.11.50ne sert plus que les apps web ; PTR.50→ci.capbe.ovh(purement web). - Comptes applicatifs :
odoo@,meca@(etagro@)capbe.ovhcréés sur Stalwart (587 STARTTLS) — mots de passeMAIL_APP_*_PASSdansplaybook/config/secrets.env, création idempotente dans07-mail.sh§3b. - Alias postmaster :
postmaster@capbe.ovh→admin@capbe.ovh(RFC 5321) — créé par07-mail.sh§3b (idempotent). - Audit délivrabilité :
playbook/audit-deliverability.sh(auth 587 + sonde MX Gmail + chaîne DNS) — modes--alert(login seul + alerte si échec) et--install-cron(cron mensuel root, 1er du mois 06h00). - Smoke-test : section 7
--app-accounts(auth SMTP 587 des 4 comptes, login seul). Validé en réel : 27 OK / 0 échec.
✉️ 05/08/2026 — Mail sortant : capbe-mail (le relais Gmail est supprimé)
Toutes les applications envoient leurs mails via capbe-mail
(mail.capbe.ovh:587 STARTTLS + auth) — plus aucun relais smtp.gmail.com :
- Odoo (tenants
meca/agro) :ir_mail_server→mail.capbe.ovh:587, compteodoo@capbe.ovh(mot de passe :MAIL_APP_ODOO_PASSdansplaybook/config/secrets.env). - FastAPI MECA :
_send_email()dansapp/services/whatsapp.pyenvoie réellement via SMTP (587 STARTTLS + auth) — variablesSMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASSWORD,SMTP_FROMdans/srv/meca/api/.env(comptemeca@capbe.ovh,MAIL_APP_MECA_PASS). Si SMTP non configuré, repli démo (log uniquement). - DKIM/SPF/DMARC sont signés par capbe-mail (domaine
capbe.ovh).
1. Cycle d'évolution de l'API (FastAPI)
1.1 Récupérer le code (une seule fois, ou à chaque base de travail)
sudo ./deploy/deploy-api.sh --pull
# → copie /srv/meca/api (capbe-pgis) → ./api-work/ (sans .env ni __pycache__)
1.2 Modifier
Édite les fichiers dans ./api-work/ (ou dans la source dev
src/stack-flutter/api puis copie). Pour une évolution
guidée par IA, fournis à l'IA : le code local (./api-work/), la carte
d'identité (README.md), les conventions (docs/MIGRATION.md) et le point
d'entrée app/main.py.
1.3 Tester en local (si possible)
# Dans ./api-work/ avec un venv :
# pip install -r requirements.txt
# uvicorn app.main:app --port 8000 (ou pytest, voir tests/)
1.4 Publier
sudo ./deploy/deploy-api.sh --push # code → pgis + restart meca-api
sudo ./ops/smoke-meca.sh # validation front + API + tenant
deploy-api.sh :
- ne pousse jamais le .env (les secrets restent sur pgis) ;
- réinstalle les dépendances uniquement si requirements.txt a changé ;
- fait un healthcheck interne (/api/v2/health sur :8000) après redémarrage.
1.5 ⚠️ Nouvel endpoint = mise à jour du Caddyfile
L'API meca sert sous /api/v2/* mais le front appelle /api/*. Caddy
réécrit uniquement les ressources listées dans la regex du bloc
meca.app.ci.capbe.ovh (voir deploy/caddy-meca.conf). Tout nouvel
endpoint (ex. /api/contrats) doit y être ajouté :
@api_rewrite path_regexp api_rewrite ^/api/(health|...|contrats)(/.*)?$
puis : sudo ./playbook/09-caddy-config.sh (recharge Caddy) et
sudo ./ops/smoke-meca.sh.
2. Cycle d'évolution du front (Flutter)
# 1. Modifier le code Flutter dans src/stack-flutter/flutter
# 2. Builder :
cd src/stack-flutter/flutter && flutter build web
# 3. Publier :
sudo ./deploy/deploy-front.sh # → capbe-meca:/var/www/html + restart nginx
# 4. Valider :
sudo ./ops/smoke-meca.sh
Le front est un build statique (SPA) : la logique métier vit dans l'API. Si l'appelleur doit changer d'URL d'API, préfère le même-origine (
/api/*) déjà en place — aucun changement de build nécessaire.
3. Évolution du tenant Odoo (base meca)
# Modules / données ERP : passer par l'interface Odoo (https://meca.ci.capbe.ovh)
# ou installer un module :
sudo ./ops/db.sh --write --shell odoo # psql interactif sur la base meca
⚠️ Le tenant meca est une base réelle (676 modules) : toute modification de schéma doit passer par les mécanismes Odoo (install/upgrade de modules), pas par du SQL direct sauf cas maîtrisé.
4. Sauvegarde / restauration projet
sudo ./ops/backup-meca.sh # dumps meca_api + meca + snapshot front + code API
# Restauration d'un dump :
sudo ./ops/db.sh --write --shell api # psql interactif → \i /tmp/dump.sql
La sauvegarde globale de l'infrastructure reste playbook/10-backup.sh
(cron 02h00) — ce kit est complémentaire (ciblé projet).
💾 Automatisée :
backup-meca.shtourne chaque nuit à 02h30 (cron root, décalé de la globale à 02h00) → log/var/log/capbe-meca-backup.log. Gardeflock: un run manuel pendant le cron est refusé proprement.⏱️ NB pool ZFS fichier-image : la création du snapshot front peut prendre 5-15 min quand le pool est chargé (constaté en réel). Piège évité : un
timeoutclient tue l'opération SERVEUR Incus — le script lance donc la création en arrière-plan sans timeout puis attend la présence effective du dataset ZFS (borne 20 min) avant de conclure (✓ ou WARN).
5. Supervision au quotidien
sudo /data/CAPBE/scripts/status-global.sh # 🌍 résumé GLOBAL des 2 kits en 1 commande
sudo ./ops/status.sh # tableau de bord complet
sudo ./ops/check-nightly.sh # ✅ le matin : le run de nuit (02h30) s'est-il bien passé ?
sudo ./ops/monitor-meca.sh # surveillance endpoints (manuel, ou cron auto toutes les 5 min)
sudo ./ops/logs.sh api # journaux meca-api (api|front|odoo|all, -f pour suivre)
sudo ./ops/api.sh --list # endpoints connus de l'API
sudo ./ops/api.sh dashboard # exemple d'appel GET (lecture seule)
🌍
scripts/status-global.sh(racine du dépôt) : conteneurs Incus, santé des 2 kits (front/API/tenant Odoo), sauvegardes de nuit, crons, alertes récentes et état git — tout en une commande, sortie 0 = tout vert, 1 = point(s) rouge(s). ⏰ Automatisé : cron root 07h40 avec--alert→ trace journalière/var/log/capbe-status.log, et mail de synthèse (rapport complet, sujet[CAPBE] État global : N point(s) rouge(s)) uniquement si le statut n'est pas vert — rien n'est envoyé quand tout est vert (aucun bruit).🌙
check-nightly.sh: vérifie en une commande que la sauvegarde de nuit s'est bien passée (run présent et terminé, dumps SQL < 26 h, snapshot ZFS du kit < 26 h, snapshot global10-backup.sh< 26 h, aucune alerte mail depuis le run). Sortie 0 = nuit saine, 1 = problème(s) détaillés.⏰ Automatisé : lancé par cron chaque matin à 07h30 (agro : 07h35) avec
--alert→ en cas d'échec, un mail[CAPBE-MECA] Check nightly : échecest envoyé àadmin@capbe.ovh(SMTP 587 STARTTLS, mdp par environnement). Log :/var/log/capbe-check-nightly.log. Rien n'est envoyé quand la nuit est saine (aucun bruit).📮 Envoi des mails centralisé :
send_alert_mail()danslib/mail.sh(racine du dépôt — source UNIQUE, sourcée par la lib de kit) — SMTP 587 STARTTLS, mdp par environnement--env, jamais en argv — utilisée parmonitor-meca.sh,check-nightly.shetstatus-global.sh.📡 Monitoring automatique :
monitor-meca.shtourne toutes les 5 minutes (cron root) → log/var/log/capbe-monitor.log. En cas d'échec (front, API public/interne, endpoint kit, données réelles, tenant Odoo, sauvegardes), une alerte mail est envoyée àadmin@capbe.ovhvia capbe-mail (SMTP 587 STARTTLS — mot de passe par environnement, jamais en argv).💾 Checks sauvegardes (fraîcheur < 26 h) : dumps SQL du kit, snapshot ZFS de
capbe-meca, snapshot ZFS global (10-backup.shvia capbe-pgis) — un cron backup manqué est donc détecté et alerté automatiquement. 📧 Alerte testée en réel : arrêt volontaire demeca-api→ 5/10 échecs → mail[CAPBE-MECA] Alerte monitoringreçu dans l'INBOX (SMTP 587 → IMAP 993), puis redémarrage → 10/10.
6. Checklist d'une évolution livrée
- [ ] Code testé (tests de
./api-work/tests/si l'API, ou smoke manuel) - [ ]
deploy-api.sh --push/deploy-front.shexécutés - [ ]
ops/smoke-meca.sh100 % vert - [ ] Nouvel endpoint → regex Caddy mise à jour +
09-caddy-config.sh - [ ]
ops/backup-meca.shlancé après une évolution majeure - [ ] Aucun secret dans le code poussé (
.envjamais copié)