fix(deploy): passe de DuckDNS à deSEC, filtré par l'école

Le filtrage du réseau de l'école bloque duckdns.org, site et API, depuis
les postes comme depuis la VM : sans API, pas de défi DNS-01. deSEC
(dedyn.io) répond depuis les deux.

- Domaine enervision-g3.dedyn.io ; provision-host.sh publie par l'API
  deSEC l'enregistrement du domaine et son joker vers la VM.
- make tls-desec remplace tls-duckdns. acme.sh recopie le jeton dans
  acme/account.conf : le dossier est retiré aux autres comptes.
- deploy.yml ne demande un certificat qu'à un .env déjà réaligné sur
  le domaine deSEC, pour ne pas faire échouer un déploiement en cours
  de migration.
This commit is contained in:
Johan LEROY
2026-09-23 11:38:44 +02:00
parent 3e871a3e8b
commit d687d7dc58
8 changed files with 74 additions and 48 deletions
@@ -1,4 +1,4 @@
# 0018 - Noms DuckDNS, certificats Let's Encrypt par DNS-01 et frontal SNI sans port
# 0018 - Noms deSEC, certificats Let's Encrypt par DNS-01 et frontal SNI sans port
- Statut : accepté
- Date : 2026-09-23
@@ -13,21 +13,24 @@ rien de présentable à un jury, et rien d'utilisable par quelqu'un qui n'a pas
poste.
Contraintes : la VM n'a qu'une IP privée, `10.101.200.37`, que ni Internet ni Let's Encrypt ne
joignent, et le réseau de l'école ne doit pas être touché. Deux vérifications faites le 23/09 :
les résolveurs de l'école rendent bien une adresse privée pour un nom public, et la VM sort en
HTTPS vers Let's Encrypt.
joignent, et le réseau de l'école ne doit pas être touché. Vérifications faites le 23/09 : les
résolveurs de l'école rendent bien une adresse privée pour un nom public, la VM sort en HTTPS
vers Let's Encrypt et vers l'API de deSEC, mais le filtrage de l'école bloque duckdns.org, site
et API, depuis les postes comme depuis la VM.
## Décision
**Des noms publics qui visent l'IP privée.** `enervision-g3.duckdns.org` porte la prod,
`rec.` et `dev.` en sous-domaines, que DuckDNS résout d'office. Tout poste du réseau de l'école
les résout sans configuration ; hors de ce réseau, l'IP ne mène nulle part.
**Des noms publics qui visent l'IP privée.** `enervision-g3.dedyn.io`, zone gratuite de deSEC,
porte la prod, et un enregistrement joker `*` porte `rec.` et `dev.`. `provision-host.sh` publie
ces deux enregistrements par l'API deSEC : le DNS est décrit par le code comme le reste. Tout
poste du réseau de l'école les résout sans configuration ; hors de ce réseau, l'IP ne mène
nulle part.
**Des certificats Let's Encrypt par défi DNS-01.** Le défi passe par l'API DuckDNS, qui pose
l'enregistrement TXT : Let's Encrypt n'a jamais à joindre la VM. `make tls-duckdns` (acme.sh
**Des certificats Let's Encrypt par défi DNS-01.** Le défi passe par l'API deSEC, qui pose
l'enregistrement TXT : Let's Encrypt n'a jamais à joindre la VM. `make tls-desec` (acme.sh
épinglé) le joue dans chaque stack ; il ne renouvelle qu'à échéance, d'où son rejeu à chaque
déploiement et chaque nuit par cron. Un certificat par environnement : DuckDNS ne tient qu'un
TXT à la fois, ce qui interdit un certificat unique pour le domaine et son joker.
déploiement et chaque nuit par cron. Un certificat par environnement plutôt qu'un joker : chaque
stack garde le sien, et la clé de la prod n'est pas lisible depuis le clone de dev.
**Un frontal SNI sur 443, le seul composant exposé.** `infra/front`, un nginx sur le réseau de
l'hôte, lit le nom demandé dans le ClientHello et relaie le flux TLS intact vers la stack visée,
@@ -49,6 +52,8 @@ clone de la prod, en retard sur `main`, sans dépendre de son `.env.example`.
- **Garder `/etc/hosts` et l'auto-signé** : trois manipulations par poste et trois
avertissements, précisément ce qu'il fallait supprimer.
- **DuckDNS** : premier choix, inscription en un clic, mais bloqué par le filtrage de l'école :
sans son API, pas de défi DNS-01.
- **nip.io ou sslip.io** : résolution sans compte, mais aucun moyen d'y obtenir un certificat.
- **Services à certificat joker public (traefik.me, local-ip.co)** : leur clé privée est publiée
par conception, n'importe qui peut usurper ces noms.
@@ -67,9 +72,12 @@ clone de la prod, en retard sur `main`, sans dépendre de son `.env.example`.
aux services homonymes, tombe : le frontal ne joint que des ports de la boucle locale.
- Sans le frontal, plus rien n'est joignable sur la VM. `deploy.yml` le relance à chaque
déploiement de la prod, et son `restart: unless-stopped` le ramène après un redémarrage.
- Le jeton DuckDNS vit dans `/srv/enervision/duckdns.token`, jamais dans git, GitHub ni le state
Terraform. Qui le détient peut repointer les trois noms.
- DuckDNS devient une dépendance : s'il tombe, les noms cessent de résoudre et les
- Le jeton deSEC vit dans `/srv/enervision/desec.token`, jamais dans git, GitHub ni le state
Terraform ; acme.sh en garde une copie dans `infra/proxy/acme/`, retirée à la lecture des
autres comptes. Qui le détient peut repointer les trois noms.
- deSEC devient une dépendance : s'il tombe, les noms cessent de résoudre et les
renouvellements échouent. Les certificats valent 90 jours, la marge est large.
- Un filtrage de l'école qui viendrait à bloquer deSEC arrêterait les renouvellements, pas les
noms : la résolution passe par les serveurs DNS de l'école, pas par le site.
- Les noms sont publics mais ne mènent qu'à une IP privée : ils révèlent l'existence de la VM,
pas son contenu.