ADR-013 — Déploiement de production : TLS par Caddy, migrations isolées, analyse d'image (M7, lot 3)¶
- Statut : proposé
- Date : 2026-10-04
- Décideurs : à valider par le porteur du projet
- Concerne :
docker-compose.prod.yml,deploy/Caddyfile,.gitlab-ci.yml,illwatch/cli/feeds.py(entretien quotidien),illwatch/modules/foundation/status.py
Contexte¶
Après les lots 1 et 2, trois manques empêchaient encore une mise en ligne :
- aucune terminaison TLS : l'API servait du HTTP en clair, l'en-tête HSTS n'avait de sens que derrière un proxy qui n'existait pas ;
- l'API exécutait les migrations à son démarrage, donc détenait le mot de passe du propriétaire des tables, ce qui annulait en partie la séparation des rôles d'ADR-012 ;
- l'image Docker n'était analysée par aucun outil.
Deux constats d'exploitation s'y ajoutent : refresh_tokens croît sans limite, et une panne
d'EPSS rend P0 inatteignable sans aucun signal (bilan du lot 2, § 4).
Décision¶
- Caddy termine TLS (Let's Encrypt automatique ; autorité interne pour
localhost), compresse, retire l'en-têteServer, réécritX-Forwarded-Foravec l'adresse réelle du client. Il est le seul service publié (80, 443, 443/udp pour HTTP/3). - Overlay de production
docker-compose.prod.yml: conteneur éphémèremigrate(propriétaire), API et worker en rôle applicatif sansMIGRATION_DATABASE_URL, ports de PostgreSQL, Redis et de l'API retirés de l'hôte, secrets obligatoires (${VAR:?}), adresse fixe de Caddy (172.30.0.10) seule autorisée à transmettreX-Forwarded-For. - Production refusée avec un mot de passe de base absent ou de développement.
- CI : l'image est poussée dans le registre du projet sous son SHA et analysée par le
gabarit GitLab Container Scanning (non bloquant au départ) ; les deux fichiers Compose
sont validés à chaque pipeline (
compose-config). - Entretien quotidien par le worker : purge des jetons de rafraîchissement expirés ou
révoqués depuis plus de 30 jours ; journal
cve.epss_stalesi EPSS date de plus de 48 h.illwatch statusaffiche le même avertissement.
Justification¶
- nginx : écarté, il exige une gestion manuelle des certificats (certbot) ; Caddy les obtient et les renouvelle seul, pour un fichier de configuration de quinze lignes.
- Traefik : écarté, configuration par étiquettes Docker plus diffuse, intérêt surtout en orchestrateur multi-services.
- Migrations au démarrage de l'API (comportement de l'image par défaut, conservé pour le développement) : écartées en production pour la raison 2 du contexte.
- Analyse Trivy en job dédié : écartée, les binaires et la base de vulnérabilités sont distribués hors du registre GitLab ; le gabarit officiel est maintenu par GitLab.
Conséquences¶
- Positives : HTTPS/2 et HTTP/3 sans gestion de certificats ; l'API ne peut plus modifier la structure de la base, même compromise ; adresse client fiable pour la limitation de débit et l'audit ; vulnérabilités de l'image visibles dans chaque MR ; plus de croissance infinie des sessions ; panne EPSS visible.
- Négatives :
- Compose v2.24 ou plus requis pour l'overlay (
!reset) ; l'anciendocker-composev1 de certaines distributions ne convient pas ; - une image par commit dans le registre : prévoir une politique de nettoyage GitLab ;
container_scanningnon bloquant tant que le registre n'est pas confirmé actif ;- Let's Encrypt exige un nom DNS public et les ports 80/443 ouverts.
Suivi¶
- Rendre
container_scanningbloquant pour les vulnérabilités CRITICAL corrigibles. - Déployer en préproduction (VPS UE), constater 7 jours de collecte (M11).