Decision de l exploitant, et elle corrige un mauvais jugement de ma part :
j avais decrit la situation correctement — la seule operation de la flotte
qui exige un humain — puis propose un minuteur maison plutot que le mecanisme
que Debian fournit exactement pour ca.
Le desarmement d aout avait un motif reel (48 minutes de verrou dpkg apres un
rattrapage) mais une contrepartie ecrite sans etre mesuree. Ce qui rend la
coexistence tenable existe maintenant : _attendre-hote attend apt-daily et le
verrou, lock_timeout est pose partout, unattended-upgrades ne traite que
l origine -security, et Automatic-Reboot reste false.
Rearmer ne se deduit pas de ne plus desarmer : passer le drapeau a false
saute la tache, il ne demasque rien. Une tache de rearmement explicite est
donc posee le jour meme ou la decision s inverse.
ET LA PREMIERE VERSION A REJOUE LA COURSE. state: started sur les trois
unites lance le rattrapage en plein deploiement : dix machines sur vingt et
une, avec l erreur meme qui avait motive le masquage. Le travail quotidien ne
passe pas par ce service — le timer appelle apt.systemd.daily directement. On
ARME sans declencher : les minuteurs demarres, le service seulement active.
21 machines, minuteurs armes, prochain passage demain vers 06h, zero unite en
echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Mesure sur les quatorze : aucune sortie TCP vers une adresse publique, apt
par le cache, noms autoritaires en local, unattended-upgrades masked. Et
quatre pairs NTP publics par machine. Le role chrony posait le fuseau et
installait le demon sans jamais toucher a ses sources : le defaut de Debian
tenait depuis le premier jour, herite et jamais choisi.
L autorite est la frontiere, par decision de l exploitant. Elle etait deja
stratum 2 et ecoutait en 123 ; il ne manquait que le passage. 9 anciennes
regles port 123 vers !SETOPS_INTERNES retirees, 9 regles nommees vers
SETOPS_FRONTIERE posees : le changement resserre autant qu il centralise.
Deux chemins parce que la topologie en a deux. Un tenant n atteint pas la
frontiere par sa passerelle de zone — tenue par le SDN — mais par le lien de
transit. Une machine du site a la frontiere pour passerelle directe. Les deux
valeurs sont derivees de l underlay, via reseau_transit() plutot que d un
prefixe d adresse qui aurait menti chez le prochain hebergeur.
La patte face aux tenants manquait a opnsense_if_zones, pour la meme raison
que grappe-controle la veille.
Sonde horloge ecrite en meme temps : synchronisee ET contre la source
DECLAREE. Une machine peut etre parfaitement a l heure contre quatre serveurs
publics — c est exactement l etat d avant.
14 tenant + 7 site, toutes disciplinees, sources publiques = 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Renommer une exposition touche cinq choses. Quatre suivent au deploiement ;
la cinquieme est celle que le navigateur regarde. serveur_nginx pose le vhost
et laisse le SAN en arriere — c est client_pki qui reemet, et rien ne le
reclame. Mesure deux fois le 2026-09-10.
Le controle compare trois listes : les expositions du plan, les noms du
certificat servi, et le code que rend le vhost. Dans les deux sens : un nom
reste dans le SAN apres avoir quitte le plan continue d etre authentifie.
Piege trouve en l ecrivant : client_pki met toujours le FQDN et le nom court
de la machine dans le SAN. Les compter comme vestiges faisait crier le
controle a chaque execution — et un controle qui crie toujours ne se lit plus.
Deux formes de terminaison, une seule question : le locataire termine sur un
edge, le site sur la machine elle-meme. Le porteur se derive de l une ou de
l autre.
Ce n est pas une preuve : rien de statique ne peut lire un certificat servi.
Les quatre controles a la demande n etaient nommes nulle part comme famille ;
ils ont maintenant leur section dans les runbooks.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
auditd tournait, onze regles etaient armees, et rien de tout cela ne servait
a grand-chose. Quatre manques, mesures avant d etre combles.
1. Rien ne sortait. Alloy ne contenait aucune reference a l audit et les cinq
greffons etaient inactifs. Il lit maintenant audit.log et le pousse vers Loki
— sans toucher une permission, alloy etant deja dans le groupe adm. On ecarte
le greffon syslog : journald limite le debit, et une rafale d evenements est
exactement le moment qui compte.
2. Aucune sonde. Elle mesure la COLLECTE, pas l armement : le nombre de
regles est precisement le chiffre qui restait bon pendant la panne du
2026-08-30. Il part en perfdata, jamais en verdict.
3. Retention non declaree. Mesuree a 4,6 Mo/jour au repos ; portee de 40 a
128 Mo. Depuis (1), le local n est plus l archive mais un tampon.
4. Les regles ignoraient la cle privee de l hote. -w /etc/step/ partout, et
-w /etc/step-ca/ sur la seule autorite : auditctl refuse un watch vers un
chemin absent et fait echouer le chargement entier.
Verifie sur l autorite seule d abord, puis 14/14 : regles armees, auditd
actif, sonde a 0, et les quatorze hotes presents dans Loki sous job=audit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Quatrieme reconstruction depuis zero, 32 min 14 s, 14/14. Elle avait un but
precis : trois roles dependent desormais d une variable que le generateur
pose. A froid, si instancier ne la posait pas, le defaut du role reprendrait
la main en silence — juste pour forge et cloud, faux pour observatoire.
Le certificat ne a froid porte observatoire et vigie, aucun ancien nom, et les
deux retours SSO derivent juste sans reprise.
Un seul echec, sans rapport : sur une machine des quatorze, get_url a rendu
0 octet SANS ERREUR — le cache a servi un 200 au corps vide. Le defaut s est
lu deux cents lignes plus loin, dans un apt qui accusait la signature. La
garde posee hier ne mordait pas : retirer une ressource vide ne vaut qu au
passage suivant, quand le fichier existe deja.
Les cinq roles qui telechargent une cle la mesurent maintenant dans la meme
execution. P68 garde le motif. infra-mail-01 redeployee, make valider a
0 echec sur 14 machines.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
icinga.<tenant>.internal devient vigie.<tenant>.internal, sur les trois
locataires a la fois. Le mot avait ete ecarte pour Grafana precisement parce
qu il connote la guette du danger : c est le metier d Icinga.
Quatrieme recopie du meme FQDN a tomber : serveur_oauth2_proxy_redirect_url
etait posee a la main dans les group_vars de chaque instance. Elle derive
maintenant de serveur_oauth2_proxy_hostname. Le repli reste vide et non
fabrique : l assertion doit refuser un deploiement sans exposition, pas
inventer un nom que personne ne resout.
Deploye et VERIFIE sur Chezlepro : le SSO renvoie sur vigie, le certificat
servi porte observatoire et vigie et plus aucun ancien nom. Deployer nginx
pose le vhost mais laisse le SAN en arriere — c est client_pki qui reemet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Le renommage deploye, nginx servait observatoire, le certificat le portait,
les deux zones le publiaient — et Grafana fabriquait toujours son URL de
retour OIDC avec l ancien nom.
Quatre roles portaient en defaut une devinette du nom sous lequel ils sont
servis. Tant que le plan suit la meme convention, la devinette tombe juste et
rien ne revele qu il y a deux sources. Keycloak avait deja son remede, dans le
role — donc trois roles sans remede.
instancier derive desormais <groupe>_hostname de l exposition unique declaree
par le plan. Six services en heritent. P67 garde la derivation. Les quatre
instances sont regenerees, 67 preuves vertes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
grafana.chezlepro.internal et tableaux.genese.internal nommaient le meme
service de deux facons. Les deux deviennent observatoire.
Un nom de produit dans une URL se grave aussi dans les SAN du certificat et
dans les URI de redirection du SSO : remplacer Grafana obligerait alors a
renommer le service. Le nom dit desormais la fonction.
Le renommage a revele que les URI des clients Keycloak repetent a la main les
FQDN declares dans expose:. Rien ne les reliait. P66 garde ce lien, ecrite en
meme temps que le premier renommage.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Doctrine posee par l exploitant : des lors que le site a son Loki, la
journalisation de la frontiere et des hyperviseurs doit y etre dirigee.
CE QUI ETAIT CASSE. La destination syslog d OPNsense pointait
10.17.20.11:3100 - une adresse de TENANT, sur le port de Loki, en UDP, ce
que Loki ne sait pas lire. La VM a ete rasee ; une cible morte a arrete
TOUTE la journalisation pendant dix jours. La destination a ete eteinte
pour reparer et jamais remplacee. Deux fautes en une : plus de journaux, et
une cible chez un locataire, ce que D-87 refuse dans l autre sens.
L intention etait juste - bonnes facilites, info et au-dessus. On l a
REPRISE telle quelle et change uniquement la destination : ces choix
avaient ete faits, ce n etait pas a nous de les redecider.
UN TRADUCTEUR, parce que Loki ne parle pas syslog : loki.source.syslog dans
l Alloy qui tourne DEJA sur le collecteur. Port 1514 et non 514, donc
ecoute sans privilege - un collecteur qui aurait besoin des droits du
systeme pour entendre un equipement serait un mauvais echange.
UNE REGLE DE RELABEL SANS GARDE N IGNORE PAS : ELLE EFFACE. Trois quarts d
heure sur un symptome absurde - la configuration deposee portait
host = "bifrost-1", visible dans le fichier, et le flux arrivait sans
etiquette. Sans regex, la regle correspond TOUJOURS, meme quand sa source n
existe pas, et pose host = "". Loki jette une etiquette vide, et celle de l
ecouteur disparaissait avec elle.
Et la verification finale a corrige une seconde erreur, la mienne :
label/host/values rendait une liste en CACHE. La requete directe rendait
bien un flux. Un index qui ne montre pas une chose ne prouve pas qu elle n
existe pas.
LA GARDE, qui manquait depuis l incident. journaux-frontiere demande a LOKI
ce qu il a RECU, pas a la frontiere ce qu elle croit avoir envoye : la
destination est le seul juge, et un emetteur qui parle a un trou noir se
porte tres bien. La fenetre est DERIVEE du debit observe - environ 1500
lignes par minute - pas choisie.
Trois etats eprouves sur une copie : frontiere muette rc=2, Loki
injoignable rc=3, debit normal rc=0. Le 3 compte autant que le 2 : « je ne
peux rien affirmer » n est pas « c est casse ».
Mesure : 46 681 lignes recues en 30 min, site a 68 services tous OK.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Les journaux de la fabric, et le defaut de classe que leur mise en place a
revele. 10 hotes dans Loki (7 VM du site + 3 hyperviseurs), site a 67
services tous OK contre 51 avant.
METRIQUES TIREES, JOURNAUX POUSSES. Un scrape part du collecteur et doit
REVENIR : il exige un chemin symetrique, que la route par defaut gelee
interdit. Un push part de la source et n attend qu un accuse.
Trois trous dans les generateurs. Le devis de la frontiere ne connaissait
fabric qu en DESTINATION - un flux entrant tombait dans « rien d autre n
entre » sans rien dire. La regle etait posee sur la patte de la destination
alors que D-61 raisonne en ARRIVEE, et opt7 manquait a la table des zones.
Et le plus grave : fabric etait un mot RECONNU mais NON RESOLU. Source
vide, donc regle sans saddr - tcp dport 3100 accept, ouvert a tous. Un mot
reconnu mais non resolu est pire qu un mot inconnu : celui-ci serait refuse
a la validation, celui-la produit une porte grande ouverte qui a l air d un
flux precis.
LA CLASSE ENTIERE EST REFERMEE. Le defaut n etait pas propre a fabric :
toute paire nommant un ensemble et ne resolvant rien ouvrait le port.
Trouve en lisant les fichiers generes, l API de supervision d un tenant
etait ouverte a tous parce que pair: serveur_backup ne resout rien - cet
ecosysteme depose chez le site. expositions et externe, eux, veulent bien
dire tout le monde : c est une intention. Ailleurs, pas de source, pas de
regle, et le generateur le DIT.
Trois regles se referment, chacune verifiee AVANT d appliquer. Deux etaient
sans effet ; la troisieme portait Grafana, qui ecoute bien sur 3000. Sa
declaration disait pair: edge - juste chez un tenant, faux au site qui n a
pas d edge. Ajout de admin : ce qui etait accidentel devient explicite.
Et la mesure a montre autre chose : Grafana etait DEJA injoignable depuis
le poste, la frontiere ne laissant pas passer le 3000. Le site a une
console deployee et sans chemin d acces. Ce n est pas corrige ici, mais
c est dit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
La supervision du site voyait ses sept VM et rien d autre. Au depart, depuis
site-mon-01, les trois hyperviseurs, les neuf pattes de la frontiere et sa
PROPRE passerelle par defaut rendaient tous 100 pourcent de perte au ping.
16 hotes UP sur 16 dont 9 pattes de frontiere en controle ACTIF
11 cibles Prometheus dont 3 hyperviseurs, job fabric separe
LE PARTAGE. Les hyperviseurs portent node_exporter - D-48 l autorise - et
exposent 1005 unites systemd avec leur etat, soit ce que la sonde sante
mesurait, plus la charge et le disque. Ils n entrent PAS dans le socle :
leur appliquer serveur_durci reecrirait le pare-feu, le SSH et les sysctl
de la machine qui tient tout le reste. La frontiere, elle, n accueille
aucun agent : controle actif, une entree par PATTE, parce qu une interface
eteinte coupe une zone pendant que les autres vont bien.
ON TIRE, ON NE POUSSE PAS. J avais propose du passif et il avait ete
valide ; la mesure a dit non. Un hyperviseur envoie vers un routeur qui ne
connait pas les reseaux du site, et sa route par defaut est GELEE (D-57).
Le porteur de sante y expirait en 20 s.
LE VRAI DEFAUT ETAIT UNE LISTE QUI N A PAS SUIVI. Le mecanisme de routage
existait deja sur vmbr0, avec un commentaire du 2026-08-26 tenant
exactement le raisonnement qu on venait de refaire. Sa liste s arretait a
10.0.34.0/24 quand le site en declare six : les zones sauvegarde et
supervision sont nees, les routes n ont pas suivi. Le symptome ne
ressemblait pas a une route manquante - il ressemblait a un pare-feu, puis
a un probleme de reseau chez l exploitant.
make routes-fabric-etat compare desormais TROIS choses : zones declarees,
routes declarees dans /etc/network/interfaces, routes vivantes dans le
noyau. Le cas le plus traitre est vivante mais non declaree : tout
fonctionne, la supervision est verte, et la panne attend la prochaine
maintenance. Eprouvee dans les deux sens.
Deux defauts trouves en construisant. bifrost-2 est un nom RESERVE, pas un
boitier - l underlay le disait en prose, illisible par le moteur ; il porte
desormais etat: reserve. Et un service passif n existe que pour un hote qui
peut POUSSER : l appartenance a un groupe sert deux choses qui ne
coincident pas toujours, a qui l on deploie et de qui l on attend un
rapport.
Les commutateurs restent dehors, choix de l exploitant, coherent avec D-48.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Question de l exploitant : le modele vit sur vishnu, les clones sur asgard,
qu arriverait-il si vishnu tombait ? Mesuree, la reponse se coupe en deux.
LES DONNEES SURVIVENT. Le pool CephNVMe est en size=3 / min_size=2 avec des
OSD sur les trois hotes, et les images du gabarit y sont repliquees.
L image reste lisible avec un noeud en moins, et les quatorze VM d un
ecosysteme tournent ailleurs sans s apercevoir de rien.
LA REPRODUCTION, NON. La configuration du gabarit porte le nom du noeud
dans son chemin - /etc/pve/nodes/vishnu/qemu-server/9006.conf - et le
clonage appelle nodes/vishnu/... Noeud eteint, aucune VM nouvelle ne peut
naitre. Or la reproduction est ce que ce depot existe pour garantir.
La decision est d ASSUMER la dependance et de la rendre COURTE, pas de la
supprimer : depuis la migration du gabarit sur stockage partage ce matin,
la remise en route est un deplacement de fichier de configuration, sans
mouvement de donnees. Un benefice qu on n avait pas cherche : la migration
sur Ceph a raccourci une panne qu on n avait pas encore nommee.
Documentee en trois endroits, parce qu un seul ne suffit pas : D-88 pour
nommer la dependance, le runbook section 7 pour la manoeuvre et l ordre
des gestes, et le bloc gabarit du plan du site - c est la que l exploitant
lit noeud: vishnu.
Ce qui n est PAS fait et qui est dit : rien ne MESURE cette dependance.
gabarit_etat compare le declare au reel, il ne demande pas si le noeud du
gabarit heberge autre chose que le gabarit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
LA GARDE FICHIER ENTIER, en deux corrections. Un telechargement
interrompu laisse un fichier de zero octet QUI EXISTE, et toutes les gardes
demandaient seulement s il etait la. infra-mail-01 a garde une cle
smallstep de 0 octet apres l epreuve hors ligne.
La premiere correction n a pas suffi. Ajouter le controle de taille faisait
bien s executer la tache - et le fichier faisait toujours 0 octet au
passage suivant. get_url sur une destination existante emet une requete
CONDITIONNELLE : l amont repond non modifie, le module rend ok, la ruine
reste. Le play etait vert et ne reparait rien. Il faut effacer avant de
redemander.
Controle negatif : 0 -> 1022 octets, 0 erreur apt. Cinq roles.
LA SONDE CORRECTIFS, 23e. Set-OPS desarme unattended-upgrades et applique
les correctifs au deploiement - choix defendable, le verrou dpkg a fait
decrocher une machine d une reconstruction entiere le matin meme. Mais rien
ne disait QUAND le geste etait du : une flotte pouvait deriver des mois en
restant verte.
Elle mesure les paquets de securite en attente ET depuis quand. Elle ne
lance pas apt-get update - une sonde qui rafraichit l index toutes les
quinze minutes deviendrait la cause de la panne qu elle surveille. Et le
seuil de 72 h est un choix d exploitation, pas une derivation : le
mecanisme qui applique les correctifs est un geste humain.
P64 REFUSAIT UNE DECLARATION CORRECTE. serveur_debian et serveur_durci sont
des roles de declaration pure, sans une tache ; le travail est fait par les
roles que leur playbook applique. La preuve exigeait declaration et depot
dans le meme role - vrai des vingt-deux premieres sondes, faux des qu une
sonde appartient au socle. Une garde qui force a contourner ce qu elle
protege est un defaut. Elle suit desormais le playbook du groupe.
Mesure : 21/21 machines vertes, 65 preuves, 23 sondes, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
get_url IGNORE la configuration d apt : le mandataire pose dans
/etc/apt/apt.conf.d/ ne vaut que pour apt. Les six cles de signature
sortaient donc TOUJOURS en direct, malgre tout le travail sur le remap. Un
trou reste ouvert derriere une porte qu on croyait fermee.
Et ce n etait pas theorique. Depuis collab-01 :
en direct grafana 200 collabora TIMEOUT
via le cache collabora 200
La route directe vers Collabora ne passe pas depuis cette zone. Trois cles
sur quatre avaient reussi PAR CHANCE, parce que leurs fournisseurs etaient
joignables. Le meme geste corrige les deux : plus rien ne sort, et la
machine qui n avait pas de route en trouve une.
POURQUOI SEULE UNE NAISSANCE POUVAIT LE MONTRER. Mes deploiements de
convergence rendaient failed=0 parce que les cles etaient DEJA sur disque
et que la tache etait sautee. Le defaut existait depuis le premier commit
du remap, invisible a tout deploiement sur une flotte existante. C est l
argument de la reconstruction depuis zero, applique a moi-meme.
Troisieme reconstruction : 32 minutes, un seul echec - celui-ci. Clonage
3 min 52, zero fatal dans le journal, 963 Mo servis par le cache contre
183 tires de l Internet, soit 81 pourcent servis localement.
Et la derive s est effacee toute seule : apt-cacher-ng tournait encore sur
forge-01 que plus aucun plan ne declarait. Je proposais de l arreter a la
main ; la reconstruction l a fait. Ce qui n est pas au plan n existe pas
apres une naissance.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Deux mouvements d une seule doctrine : le site fournit tout ce dont un
tenant a besoin pour venir au monde.
1. LES DEPOTS TIERS. Grafana, Icinga, Smallstep et Collabora ne publient
qu en HTTPS ; apt-cacher-ng ne relaie pas un tunnel, et le socle pose donc
Acquire::https::Proxy DIRECT. Chaque machine sortait elle-meme sur
Internet. Le cache declare desormais un Remap par fournisseur, et chaque
role demande en {{ ..._depot_schema }}:// - http des qu un cache est
declare, https sinon. Le TLS n est rompu nulle part : il est TERMINE au
cache, qui est notre machine, et l integrite vient des signatures.
avant : 4 fournisseurs en HTTPS direct, 14 machines sortant seules
apres : 0 source en HTTPS direct, 0 erreur apt sur 14 machines
Trois lecons. Le remap appartient au cache qui SORT : pose sur un cache
chaine, il tente le HTTPS a travers son amont et rend 503. apt_repository
AJOUTE au lieu de remplacer, donc l ancienne ligne https sortait toujours.
Et la liste des fournisseurs ne se devine pas - j en avais trois, l audit
en a revele un quatrieme.
2. LE CACHE DU TENANT. Sa ligne portait son propre retrait depuis toujours
- service MUTUALISABLE, un ecosysteme au premier age peut pointer sur celui
de son hote. Retiree. Ce qu on perd, dit franchement : plus de trafic
inter-zone et plus de charge sur site-cache-01, contre un service de moins
a poser, superviser et reproduire.
3. UN ROLE QU ON RETIRE DOIT DEFAIRE CE QU IL A FAIT. Le retrait a montre
que rien ne nettoie derriere. Le fichier apt visait un cache eteint en
ecrasant le plancher qui fonctionnait - le defaut deja paye a quinze
machines. Et les sondes du cache restaient, le porteur poussant pour des
services qu Icinga ne definit plus (404). Le socle retire le premier,
client_sante derive les sondes attendues et retire les orphelines.
P65 refuse tout role visant un depot relaye en https ecrit en dur. Sa
limite est dite : elle empeche une regression sur ce qui est connu, elle ne
decouvre pas l inconnu.
Mesure : Icinga 87 OK sur 96, prouver 65 OK, lint 0 defaut.
Reste, et c est dit : apt-cacher-ng tourne toujours sur forge-01 que plus
aucun plan ne declare.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Seconde reconstruction complete de Chezlepro dans la journee, pour
EPROUVER les quatre correctifs livres entre les deux. Rien de nouveau
n a ete construit : c est une mesure.
gabarit sur CephNVMe clonage 4 min 30 contre ~30 min
placement declare {asgard: 14} - les quatorze au bon endroit
hosts_statiques conditionne changed au 1er passage, skipping au 2e
monitoring-plugins au role ping4 14/14 OK sur une mon-01 nee neuve
Le troisieme est le plus instructif : les DEUX branches sont exercees dans
la meme execution. infra-pki-01 recoit le gabarit maitre de cloud-init au
premier passage, puis la tache est sautee au second, le durcissement
l ayant retire. Aucune preuve statique ne pouvait montrer cela - il fallait
une naissance.
Le facteur mesure est 6,6 et non 45 : un clone isole prend 8 s, mais quatre
clones se disputent le pool et le redimensionnement du disque s ajoute. On
retient la mesure en conditions reelles, celle qu on paie.
Des trois echecs du matin il ne reste rien. Le verrou dpkg ne s est pas
reproduit - c etait une course, et rien ne dit qu elle ne reviendra pas.
Et le cache apt N ETAIT PAS un defaut : les deux seuls fatal de cette
execution sont suivis de ...ignoring, ce sont les sondes de
client_artefacts qui laissent la machine servie par le plancher du SITE.
C est la filiation en train de fonctionner. Le matin, j avais compte ces
deux lignes comme des echecs sans lire la suivante.
Icinga : 89 OK, 9 UNKNOWN sur 98, aucun WARNING, aucun CRITICAL. Les neuf
sont tous des sauvegarde dont le minuteur nocturne n a pas encore visite
une flotte nee il y a vingt minutes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Le role pose /etc/cloud/templates/hosts.debian.tmpl - le gabarit maitre
dont cloud-init regenere /etc/hosts au demarrage. Or D-85 fait retirer
cloud-init par serveur_durci, et le repertoire part avec lui.
L echec n avait aucun sens : ce gabarit ne sert qu a survivre a une
reecriture qui n a plus lieu. Plus de cloud-init, plus de reecriture, le
plancher tient tout seul - c est le resultat recherche par D-85.
CE QUE CA A COUTE. _amorcer-socle monte infra-pki-01 et infra-dns-01 en
entier d abord, durcissement compris. La tache echouait au second passage,
l hote sortait du play, et TOUT ce qui suivait n etait jamais pose - dont
icinga-ca.crt. Leur porteur de sante tournait ensuite normalement et chaque
rapport echouait sur curl: (77), en silence. Un echec bruyant au bon
endroit avait produit une panne muette ailleurs.
Et sauter la tache seule aurait deplace l echec d un cran : la garde qui
suit compare le nombre d entrees du plancher a celui du gabarit, donc 21
contre 0. Elle accuserait une divergence la ou il ne reste qu un fichier.
Une garde qui survit a ce qu elle gardait ne mesure plus rien : elle
invente. Les trois taches suivent desormais la meme condition.
Verifie sur les deux machines memes qui echouaient : failed=0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Quatorze machines detruites, quatorze refaites. 1 h 08, 0 injoignable.
D-86 TIENT, et la mesure le dit : 30 resultats de controle recus a
12:20:41 alors que la reconstruction ne s est terminee qu a 12:35:29.
Trente services rapportaient leur etat pendant que Keycloak, Forgejo et
Nextcloud montaient encore.
Sa limite, dite franchement : D-86 affirme que le DNS peut rester en
couche 6 grace au plancher /etc/hosts. Or _amorcer-socle monte
infra-dns-01 EN ENTIER d abord. Le DNS etait debout, le plancher n a rien
eu a porter, et la partie la plus audacieuse de la decision reste non
testee.
LE PLACEMENT DES VM N ETAIT DECLARE NULLE PART. Les quatorze vivaient sur
asgard depuis toujours, mais SETOPS_NOEUD valait le vide : ce placement
n existait que dans l etat d execution de Proxmox. Sans cible, le clone
reste sur le noeud du gabarit - vishnu, qui a 14 Go libres et heberge
eregion et site-forge-01. Le defaut avait survecu a la reconstruction du
2026-09-02 parce que les VM existaient deja et que le clone les sautait.
Il faut un from-zero VRAI pour voir ce genre de chose.
LE CLONAGE ETAIT 45 FOIS TROP LENT, et pas a cause du reseau : source et
destination etaient sur le meme stockage. C est le LVM epais qui interdit
a Proxmox tout clone autre que complet. Gabarit deplace sur CephNVMe,
mesure 480 s -> 8 s. On garde les clones complets : le clone lie descend
a 1 s mais enchaine chaque VM a l image de base pour toujours.
Un champ stockage: entre au gabarit, branche en quatre points - declare,
expose, consomme par le Makefile, garde par gabarit_etat. Declarer sans
consommer, c est decorer.
ICINGA NE POUVAIT PAS FAIRE SES PROPRES CONTROLES : icinga2 n apporte
aucun greffon, et la supervision etant passive, le manque etait masque.
Quatorze ping4 muets d une seule cause. monitoring-plugins-basic entre au
role. Le site l avait deja - pose A LA MAIN, jamais declare : troisieme
occurrence du jour d un etat qui ne survivrait pas a une reconstruction.
Trois defauts laisses ouverts : le cache apt attendu pendant l amorcage,
la regression D-85 sur /etc/cloud - qui a fait decrocher deux hotes de la
tache deposant icinga-ca.crt, rendant leurs sondes muettes en silence - et
auditd sans regles dans le gabarit.
Mesure finale : Icinga 93 OK sur 98, site 51/51, Prometheus 15/15,
prouver 64 OK, lint 0 defaut. Les quatre non-OK restants sont des
sauvegarde dont le minuteur nocturne n a pas encore visite une flotte nee
il y a deux heures.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Application de ce que l entree precedente avait prepare : 49 regles creees,
5 retirees. Cibles Prometheus 2/8 -> 8/8, hotes dans Loki 1/7 -> 7/7.
Puis correction de ce que l application a revele. Cinq defauts, tous de la
meme famille : un reglage qui ne suit pas l interrupteur dont il depend.
- la sonde de Loki interrogeait en HTTPS un Loki servant en clair ;
- la sonde de la forge visait http:// sur un port 443 chiffre, puis
validait un certificat emis pour le FQDN en interrogeant 127.0.0.1 ;
- la sonde du runner comparait six depots a UNE branche quand le plan en
declare une par depot. Elle contredisait la declaration qu elle etait
censee verifier : elle n accusait pas la machine, elle s accusait
elle-meme.
Le tenant restait juste dans les cinq cas. C est le site, qui deploie ces
roles autrement, qui les a tous reveles d un coup.
La sonde des journaux, elle, avait deux defauts a la naissance. Elle criait
une perte deja reparee, faute de dire sur QUELLE fenetre - un ecart sans sa
fenetre n est pas une mesure, c est un nombre. Et elle alertait sur la
cicatrice plutot que sur la plaie : le compteur d Alloy est cumulatif, donc
six machines restaient orange pour toujours. Ce qui alerte est desormais la
CROISSANCE. En echange, un cas muet leve maintenant : zero envoi et zero
rejet n est pas la sante, c est un agent qui ne fait rien.
Enfin, le runner ne pouvait plus cloner le genome. Defaut PREEXISTANT,
revele par le redeploiement et non cause par lui - le diff des regles
generees le montre. generer_nftables(site=True) lisait le plan du TENANT :
derive se resolvait donc a 3000, le port que Forgejo ecoute derriere un
edge, alors que le plan du site dit 443 et explique pourquoi. La forge
ouvrait un port que personne n ecoute et laissait 443 ferme a toute la
flotte.
Mesure finale : Icinga 51/51, Prometheus 8/8, Loki 7/7, prouver 64 OK,
lint 0 defaut sur 82 fichiers. Controles negatifs sur des COPIES des
sondes : les quatre rendent CRITICAL.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
D-87 disait que l hebergeur n a pas le droit de voir les journaux de ses
locataires. La decision avait une face cachee : a force de refuser de voir
ceux des autres, le site s etait prive des siens. Ses sept machines
n expediaient nulle part.
Il prend donc sa propre pile : prometheus, loki et grafana sur site-mon-01,
sans aucun lien avec ceux d un tenant. L exemption qui bloquait portait sa
propre condition de levee, ecrite cinq jours plus tot dans le plan.
Grafana au site n a pas de SSO, et le role l ignorait : il reclamait l IdP
avant de regarder s il en voulait un. L interrupteur existait, il n etait
pas honore. Le role refuse desormais SSO eteint ET formulaire local eteint
- la combinaison deploie un Grafana en sante ou personne ne peut entrer -
et le reglage du formulaire sort du if du SSO, ou il disparaissait en
laissant le defaut amont decider en silence.
Deux manques se cachaient l un l autre dans le devis de la frontiere, et
Prometheus voyait 1 cible sur 7 :
- le devis derivait les groupes d une machine du site de applications.yml
seul, et ne voyait donc aucune integration universelle - alors que
client_metrique ouvre un port d ecoute ;
- une sortie vers un role du site visait !SETOPS_INTERNES, qui exclut
precisement la machine nommee. Le devis autorisait a expedier les
journaux du site a n importe quel Loki du monde, et a nul autre endroit
qu a celui-la. Neuf flux dans ce cas.
Et deux declarations justes ne font qu une regle : appliquer_opnsense pose
tout en direction: in (D-61).
Les deux agents se supervisent enfin eux-memes. La sonde des journaux ne
demande pas si Alloy tourne, elle lit ce qu il a du JETER. Elle a fait ses
preuves le jour meme : Alloy actif, /-/ready a 200, et cinquante lignes
perdues sur six machines.
Mesure : metriques 7/7 vert, journaux 1/7 - les six autres attendent la
regle de frontiere, et le disent. prouver 64 OK, ansible-lint 0 defaut.
Reste a la main de l exploitant : make frontiere-appliquer CONFIRMER=true,
et le secret vault_grafana_admin a deposer dans underlay.vault.yml.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Question posee : quels roles ne pas embarquer dans le site ? La table de
mutualisation existait et repondait presque — mais une de ses lignes
CONTREDISAIT ce qui tourne.
Elle disait « observabilite | oui | l hebergeur surveille ses locataires ».
Or chaque ecosysteme a son propre Icinga, et celui du site ne voit que ses
sept machines. L implementation avait raison, la doctrine avait tort.
Et cette case autorisait ce que la ligne du dessous interdit. LES JOURNAUX
CONTIENNENT DU CONTENU — un mot de passe dans un message d erreur, une
donnee metier dans une trace, qui a fait quoi et quand. Un hebergeur qui
ingere les journaux de son locataire en sait PLUS que s il detenait son
annuaire : l annuaire dit qui existe, les journaux disent ce qu ils font.
Decoupee en trois : disponibilite oui (une VM tombee est un fait de la
fabric), metriques oui avec reserve (elles disent quand et combien, ce qui
suffit a lire l activite d une organisation), journaux NON.
ET LA LIGNE PKI EST TRANCHEE : NON. Une AC intermediaire signee par l hote
lui donnerait le pouvoir d emettre des certificats valides pour les noms
du locataire — donc de se presenter comme n importe lequel de ses
services, devant les propres machines du locataire, qui les accepteraient
puisque c est ce que la chaine de confiance leur demande. Meme pouvoir que
l annuaire, sous une forme moins visible : aucune trace cote locataire.
Une PKI par ecosysteme, jamais derivee de l hote.
LE REVERS, MESURE ET ASSUME : le site n a ni client_journal ni
client_metrique, aucun loki ni prometheus. A refuser de voir ceux des
locataires, il s est prive des siens. Le remede n est pas d assouplir la
regle mais de lui donner sa propre pile.
Verifie par ailleurs : rien d intime n est au site aujourd hui. La
frontiere etait tenue en pratique avant d etre ecrite au net.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
CORRECTION DE COMPTE D ABORD. J avais annonce cinq groupes sans sonde. La
mesure en donne VINGT-SEPT : j avais compte ceux que j avais en tete, pas
ceux que le depot contient. Il en reste vingt-deux.
LES CINQ, PAR ORDRE DE DEGAT SILENCIEUX.
autorite (step_ca) — la plus urgente : nos certificats vivent 24 h, une AC
muette ne casse rien aujourd hui et casse TOUT demain, d un coup, sur les
21 machines. Elle surveille aussi l expiration de la RACINE, que personne
ne regarde parce qu elle vit des annees (relevee a 3642 jours).
base (postgresql) — une VRAIE requete, pas pg_isready : celui-ci dit que
le port repond, pas que la base sert. Plus le compte des connexions : a
saturation, chaque application tombe sans que la base ait l air morte.
annuaire (openldap) — elle COMPTE les entrees. Un annuaire vide repond
success a tout : le mensonge des sauvegardes vides, vert et sans contenu.
zones (powerdns) — un autoritatif sans zone repond NXDOMAIN a tout, ce qui
se lit comme « ce nom n existe pas ».
edge (nginx) — elle valide la configuration SUR DISQUE : nginx sert la
derniere valide, et une configuration cassee ne se voit qu au prochain
demarrage, souvent des mois plus tard.
Les cinq eprouvees vertes sur le sain puis rouges PAR PARAMETRE, sans
toucher a un service.
Etat : 20 sondes sur 19 roles, 23 services distincts, 70 instances, 67 au
vert. Les trois autres sont connues : deux sauvegardes sans donnee a
emporter, et Loki en delai de stabilisation apres redeploiement.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
LA SCISSION. cache-apt fondait deux causes aux DELAIS differents : « ne
repond pas » arrete tout apt de l ecosysteme, on agit dans la minute ;
« volume a 90 % » est un billet pour demain. Les fondre obligeait soit a
reveiller quelqu un pour un disque, soit a traiter une panne comme un
billet. Deux sondes, chacune avec son etat, son historique, son
acquittement — et prouvees INDEPENDANTES :
port ferme -> cache-apt CRITIQUE, cache-apt-volume OK
seuil impossible -> cache-apt OK, cache-apt-volume AVERTISSEMENT
CE QUE LA VERIFICATION A REVELE. Un resultat pousse et accepte (code 200)
n apparaissait pas en base. Hypothese testee et confirmee : IcingaDB n
ECRIT service_state QUE SUR CHANGEMENT D ETAT. Un OK identique repete ne
produit aucune ecriture ; un AVERTISSEMENT pousse ensuite est ecrit en 13 s.
Or la sonde moteur, ecrite quelques heures plus tot, lisait exactement
max(last_update) de service_state pour juger de la fraicheur. Elle
mesurait le CHANGEMENT. Sur un ecosysteme parfaitement STABLE — celui
qu on veut — plus rien ne change, last_update vieillit, et elle serait
passee en avertissement a 15 min puis en critique a 90. Une alarme qui se
declenche PARCE QUE tout va bien, avec un delai qui l aurait rendue
difficile a rattacher a sa cause.
La bonne source existait : icingadb_instance porte le battement du
synchroniseur, ecrit en continu. Releve a 1 s sur un systeme sain. Seuils
ramenes de 15/90 min a 1/5 min. Controle negatif rejoue.
Dix-huit services, tous verts sauf sauvegarde 7/9 (deja connu).
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Question posee : « une sonde par role, est-ce parce qu elles agregent
plusieurs verifications ? » Oui — et « une par role » n etait pas mon
critere, c etait une coincidence : la plupart de ces roles n ont qu une
preoccupation. Mesure : les quatorze sondes agregent de 2 a 6 chemins d
echec chacune.
Le critere, applique en silence jusqu ici, est desormais ecrit : UNE SONDE
PAR CAUSE D ACTION — ni par role, ni par verification.
CE QUE COUTE UNE AGREGATION ABUSIVE, dans le modele d Icinga : un service
= un etat, un historique, un acquittement. Fondre deux causes qui
appellent des gestes differents, c est ne plus pouvoir acquitter l une
pendant que l autre alerte, et lire comme un service instable ce qui est
deux faits distincts qui alternent.
CE QUE COUTE L EXCES INVERSE : un voyant de plus est un voyant de moins
regarde.
Le test : les deux echecs appellent-ils le meme geste, de la meme
personne, dans le meme delai ? Si oui une sonde, et le message nomme
lequel a parle. Si non, deux.
Par ce critere, deux sondes existantes sont abusives : `certificat` (trois
gestes — minuteur bloque, AC changee, consommateur a recharger) et
`cache-apt` (deux delais — panne immediate contre billet pour demain).
Non scindees : c est une decision sur le nombre de voyants au mur.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
boites (dovecot) · cache-apt (artefacts) · certificat (client_pki, 14/14)
collaboration (nextcloud) · collecte (prometheus) · file-courriel (postfix)
forge (forgejo) · identite (keycloak) · ingestion (loki) · moteur (icinga)
resolution (resolveur) · runner (serveur_ops) · tableaux (grafana)
voute (ops_tenant) — toutes vertes, sans une ligne ecrite dans Icinga.
DEUX PRINCIPES QUE LA PREMIERE SONDE A IMPOSES.
Une sonde doit pouvoir etre mise en defaut PAR PARAMETRE : cible et seuils
sont des variables du role, on prouve le rouge avec un port ferme ou un
seuil impossible, sans rien casser. Et la sonde vit LA OU VIT LA VERITE :
« ce noeud est-il collecte ? » appartient a prometheus, pas au client —
une seule y voit les N noeuds, et surtout elle voit le cas SILENCIEUX.
ON DEMANDE AU SERVICE CE QU IL PENSE DE LUI-MEME quand il sait le dire
(healthz, /ready, status.php, decouverte OIDC). Quand il ne sait pas, on
va chercher la verite de terrain : « moteur » ne regarde ni le service ni
le port, il demande a la base depuis combien de temps elle n a pas ete
rafraichie — la lecon des sauvegardes appliquee a la supervision.
QUATRE FOIS J AI ECRIT LA SONDE AVANT DE MESURER, QUATRE FOIS ELLE A EU
TORT. La forge : port et chemin des depots inventes, elle ecoute en 3000
derriere l edge et n a legitimement aucun depot. Loki : « panne
persistante » conclue sur deux lectures a quelques secondes d intervalle
juste apres un redemarrage — deux mesures rapprochees ne distinguent pas
un etat d un instant. Keycloak : vise en 8443, il ecoute en 8080. Le
runner : git en root refuse un depot d un autre proprietaire. A chaque
fois le remede est le meme — lire la verite du role, ne pas la supposer.
Et le meme piege Jinja qu avec client_sante : ${#tableau[@]} contient {#.
Le remede etait deja au depot ; je l ai reecrit au lieu de le chercher.
RESTE : client_smtp, client_artefacts, client_journal, icingaweb2 et
ops_site. Ce sont des chemins de report, dont la panne se voit deja par le
silence des sondes qu ils portent.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute (P64 : 14 sondes).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Ajout de meta/supervision.yml a six roles, chacun deposant sa propre sonde
selon le contrat des greffons Nagios.
DEUX PRINCIPES POSES AU DOCUMENT DE CONCEPTION, parce que la premiere
sonde les a imposes :
1. UNE SONDE DOIT POUVOIR ETRE MISE EN DEFAUT PAR PARAMETRE. Cible et
seuils sont des variables du role : on la prouve rouge avec un port ferme
ou un seuil impossible, sur une machine reelle, sans rien casser, et
aussi souvent qu on veut. Une sonde qu on ne peut prouver qu en cassant un
service ne sera prouvee qu une fois.
2. LA SONDE VIT LA OU VIT LA VERITE. « Ce noeud est-il collecte ? » est
une sonde de serveur_prometheus, pas de client_metrique : une seule y voit
les N noeuds, et surtout elle voit le cas SILENCIEUX — celui qui a cesse d
etre collecte ne peut pas s en plaindre.
LES SIX : cache-apt (artefacts, repond + place), resolution (resolveur,
zone interne ET Internet — deux chemins distincts), forge (forgejo, son
propre /api/healthz), collecte (prometheus, 15/15 cibles), tableaux
(grafana, base ok), ingestion (loki, PRET a ingerer, pas seulement en
ecoute).
TROIS FOIS J AI ECRIT LA SONDE AVANT DE MESURER, ET TROIS FOIS ELLE A EU
TORT. La forge : port 443 et chemin des depots INVENTES — elle ecoute en
3000 derriere l edge et n a legitimement aucun depot. Loki : j ai conclu
« panne persistante » sur deux lectures prises a quelques secondes d
intervalle, juste apres un redemarrage ; l anneau etait ACTIVE et la
reponse est passee a ready moins d une minute plus tard. Le delai de
stabilisation est desormais un AVERTISSEMENT nomme, pas une panne.
On demande au service ce qu il pense de lui-meme quand il sait le dire
(healthz, /ready, /api/health) plutot que d inventer un critere de l
exterieur.
make prouver : CONFORME.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
On n allume pas la lumiere une fois la maison finie. L observabilite et le
moteur de supervision etaient deployes APRES presque tout ce qu ils
surveillent. Une reconstruction depuis zero est pourtant le moment ou l on
a le plus besoin de voir, et c etait le seul moment ou l on ne voyait rien.
4. observabilite postgresql, prometheus, loki, grafana, icinga
5. agents_supervision client_metrique, client_journal, client_sante
DEPLACER LES SERVEURS SANS LES AGENTS N AURAIT RIEN CHANGE : ce sont les
agents qui rapportent, et ils etaient en derniere couche. Les deux couches
vont donc ensemble. Des la couche 5, chaque hote expedie ses metriques,
ses journaux et l etat de ses unites — tout ce qui se deploie ensuite est
mesure pendant qu on le construit.
COUT : serveur_postgresql monte aussi (icinga l exige, il n exige rien).
C est le seul entrainement.
RESTE TARD A DESSEIN : icingaweb2 et oauth2_proxy reclament LDAP et
Keycloak. C est la CONSOLE, pas la mesure.
CE QUI REND CE DEPLACEMENT POSSIBLE : le DNS reste en couche 6, donc apres
la supervision, alors qu icinga joint sa base par un NOM. Ca tient grace au
plancher /etc/hosts pose des la couche 1 — 34 entrees, verifie. C est
exactement ce pour quoi il existe.
LIMITE : les notifications dependent de client_smtp, encore en derniere
couche. Pendant une reconstruction, l etat est mesure et consultable, mais
rien ne part par courriel avant la fin.
ET : l ordre est VALIDE, pas EPROUVE. P08 accepte, le graphe accepte,
site.yml regenere passe le syntax-check sur 782 lignes de plan. La seule
preuve reelle d un ordre de reconstruction, c est une reconstruction.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
J ai ecrit il y a une heure que la panne PMTUD « etait la, silencieuse,
sur les sept machines de l hebergeur ». La mesure ne le soutient pas :
site-mon-01 -> autre zone du site : MTU de chemin 1500
site-mon-01 -> Internet : MTU de chemin 1500
ops-01 (tenant, overlay EVPN) : MTU 1450, chemin vers Internet 1450
Le site est a 1500 de bout en bout. Aucun lien du chemin ne plafonne plus
bas, donc aucun message « fragmentation necessaire » n avait lieu d etre
emis, donc rien n etait casse entre zones du site. La contrainte a 1450
vit chez les TENANTS, sur l overlay — pas chez l hebergeur.
Les six regles restent un vrai manque : elles couvrent le site parlant
vers l EXTERIEUR, ou un correspondant distant peut plafonner plus bas, et
elles seraient necessaires si une zone du site passait sur l overlay. Mais
c etait une PROTECTION ABSENTE, pas une panne active.
Decrire l un comme l autre est l exageration que ce depot ne doit pas
contenir : une correction qu on ne mesure pas se raconte toujours plus
grande qu elle n est. La correction est portee au CHANGELOG et dans le
commentaire de devis_opnsense.py, la ou on la relira.
Ce qui reste vrai et mesure : l Icinga du site tenait 6 de ses 7 machines
pour mortes, et 7/7 apres.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
LA CAUSE EXACTE. devis_opnsense traitait tout `port` non numerique comme
SYMBOLIQUE, a resoudre par le plan. Vrai pour `derive`, le port d un
service que seul le plan connait. FAUX pour l ICMP : echo-request et
frag-needed sont des litteraux. Ils tombaient dans la branche « le plan ne
resout pas » et aucune regle n etait emise. Une ligne de condition, et le
silence de toute une flotte.
CE QUE LA CORRECTION A REVELE EN PLUS. Huit regles a creer, zero a
retirer — et SIX sont du PMTUD entre zones du site, absent pour la meme
raison. Le depot dit de ces messages : bloques, la connexion s etablit,
les petites requetes passent et les grosses reponses restent suspendues —
la panne la plus couteuse a diagnostiquer. Elle etait la, silencieuse.
CE QUE LA REGLE AUTORISE, EXACTEMENT. appliquer_opnsense n envoie
destination_port que pour TCP et UDP : une regle ICMP ouvre le PROTOCOLE
entre deux pairs, pas le seul type. Le type reste porte par la regle d
HOTE, que resoudre_flux emet precisement. La frontiere dit qui peut parler
a qui, l hote dit ce qu il accepte d entendre. Emettre un icmptype a la
frontiere aurait demande de traduire frag-needed dans le vocabulaire de
pf, au risque de casser le PMTUD pour gagner de la precision sur une
barriere qui n est pas la derniere.
MESURE APRES APPLICATION :
ping site-mon-01 -> les six autres zones : 6/6 repondent
hotes UP : 1/7 -> 7/7 | ping4 : 1/7 -> 7/7 | certificat 7/7 | sante 7/7
tenant inchange : 14/14
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
« mon-01 tape dans l fond. » Il tapait : load 5,10 sur 4 coeurs, 8
processus check_disk a 70-99 % de CPU chacun, jusqu a 28 minutes de vie.
check_disk 2.4.0-3+deb13u1 ne rend jamais la main sur cet hote (etat R).
Icinga en relancait un a chaque intervalle pour le service `disk` de son
hote de DEMONSTRATION, et aucun ne mourait.
RETIRE : conf.d/hosts.conf, l hote NodeName livre par le paquet. Les apply
Service s y accrochaient — disk, http, swap, apt, load, procs, users — et
trois etaient rouges en permanence (swap sur une VM sans swap, http sur un
port ou rien n ecoute, apt pour un paquet). On retire l HOTE et non les
services : sans lui les apply ne s accrochent a rien, et on ne touche pas
a un fichier que le paquet remplacera. Ca garde ping4, qui vise nos hotes
et sert vraiment.
avant : load 5,10 — 8 check_disk — 3 alarmes rouges permanentes
apres : load 0,77 — 0 check_disk — certificat 14/14, sante 14/14, ping4 14/14
TROUVE EN VERIFIANT : l Icinga du SITE tenait 6 de ses 7 machines pour
MORTES (1/7 UP, contre 14/14 au tenant). hostalive est un ping, le site
est decoupe en zones, et l ICMP inter-zones n etait declare nulle part —
100 % de perte, mesure. Or Icinga SUPPRIME les notifications des services
d un hote DOWN : une supervision qui croit tout mort n alerte plus de
rien, tout en ayant l air de fonctionner.
Le flux est declare des DEUX cotes, et le registre a refuse la premiere
moitie seule — exactement sa raison d etre. CODES_ICMP apprend
echo-request. Regles d hote posees sur les 21 machines.
RESTE OUVERT : le generateur de la frontiere ne sait pas traduire un TYPE
ICMP pour un pair INTERNE — il le note et n emet rien. Le site reste a
1/7. Corriger devis_opnsense.py est le prochain geste.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Question posee : « tu connais le paquet monitoring-plugins ? » Oui — et le
contrat que docs/supervision-conception.md decrivait quelques heures plus
tot EST le sien, mot pour mot. Je l avais reinvente sans le nommer, alors
que positionnement.md dit l inverse : adopter aux seuils, ne pas
reimplementer.
Le document nomme desormais l API des greffons Nagios, ajoute le code 3
(INCONNU) et la partie « | metriques » qui manquaient, et dit la
consequence : un greffon standard EST une sonde valide, sans colle. Le
paquet en fournit 54. On n ecrit du shell que lorsque la verite a mesurer
est propre a Set-OPS. Le porteur separe maintenant texte et
performance_data.
ESSAYER UN VRAI GREFFON A REVELE DEUX DEFAUTS DU PORTEUR.
Un envoi refuse faisait taire TOUTES les sondes suivantes : rapporter
sortait en exit 1. Une sonde deposee mais non declaree supprimait le
rapport des autres, sante comprise — le tableau ne devenait pas rouge, il
devenait vide, et le ttl le perimait des heures plus tard sans dire
pourquoi.
Aucun delai de garde sur les sondes. check_disk 2.4.0-3+deb13u1 sur mon-01
tourne sans fin (etat R) quels que soient ses arguments : un greffon
STANDARD, sur une machine saine, qui boucle. Sans garde il figeait le
rapport entier toutes les quinze minutes. Chaque sonde tourne desormais
sous timeout 20 ; au-dela on rapporte INCONNU en le disant.
La lecon n est pas que les greffons standards sont mauvais : c est qu
adopter un standard ne dispense pas de l eprouver, et que le porteur doit
survivre a une sonde qui se comporte mal.
CONSTATE AU PASSAGE, NON CORRIGE : la configuration d exemple d Icinga
crie en permanence sur mon-01 — swap sur une VM sans swap, http sur un
port ou rien n ecoute, apt pour un paquet. Trois alarmes qui ne peuvent
que rester rouges, dans le seul endroit qui doit rester lisible.
Etat : certificat 14/14, sante 14/14 au tenant ; 7/7 au site.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
LE CONSTAT. 39 roles declarent leurs flux, 32 leur empreinte, 32 leur
authentification — tous derives. Et 19 groupes sur 19 declaraient une
surveillance en prose que RIEN n executait ; Icinga en surveillait deux.
La carte disait ce qui etait surveille, et personne ne surveillait.
LE MECANISME. Un role declare ses sondes dans meta/supervision.yml et
depose lui-meme son script dans /usr/local/lib/setops/sondes/. Le porteur
client_sante les fait toutes tourner et pousse un resultat passif par
sonde, sans savoir ce qu elles mesurent. serveur_icinga derive les objets
Service ET le filtre de permission d API des memes declarations. Ajouter
une sonde ne demande de toucher ni au porteur ni a Icinga.
PREMIERE SONDE : client_pki/certificat. Heures restantes sur le certificat
reellement pose, chaine verifiee, et empreinte SERVIE comparee au disque
quand un service le consomme. 14/14 au tenant, 7/7 au site.
QUATRE OBSTACLES, ET TROIS SONT LA MEME LECON.
La sonde a rendu 14/14 en CRITIQUE sur une PKI saine : openssl verify
-CAfile racine ne trouve pas l intermediaire qui signe nos certificats.
step certificate verify, lui, repond VALIDE.
Deployee au site, elle a rendu 5/7 : le seuil d avertissement (12 h)
etait AU-DESSUS du point de renouvellement (8 h, le tiers restant). Elle
criait avant que le mecanisme ne soit cense agir. Seuils ramenes a 6 h et
3 h. Un seuil se DERIVE du moment ou le mecanisme surveille agit.
Une alarme toujours allumee ne vaut pas mieux qu une alarme jamais
allumee : elle apprend a ne plus regarder. Une sonde se prouve DEUX FOIS,
verte sur le sain et rouge sur le casse.
Le filtre d API etait ecrit avant la lecture des declarations : les
services auraient existe et Icinga aurait refuse leurs resultats.
Et mon controle negatif a casse un service reel : substituer le certificat
d hote a fait propager un cert sans sa clef vers node_exporter. Un controle
negatif se fait sur une COPIE.
P64 tient les deux bouts : declaree sans etre deposee, ou deposee sans
etre declaree. Trois controles negatifs rejoues.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Le role portait une branche « aucun serveur_icinga : rien a poser » et un
when sur tout son bloc. Ni l une ni l autre ne pouvait s executer.
Eprouve sur le modele public, dans une copie jetable : instancier ne pose
une integration UNIVERSELLE que si son serveur existe dans l ecosysteme.
Sans Icinga au plan, le groupe client_sante est ABSENT de l inventaire
genere — comme client_metrique et client_journal le sont deja. Le role n
est donc jamais appele sans destinataire.
Une garde qui ne peut pas se declencher n est pas une garde : elle rassure
sans rien tenir, et elle coute le jour ou l on cherche pourquoi rien n a
alerte.
Ce qui la remplace se declenche vraiment, et les deux cotes sont eprouves :
hote vide -> FAILED, secret vide -> FAILED, et l echec dit lequel des deux
manque. Le bloc, prive de sa condition, est aplati : douze taches a plat.
Rejoue sur les deux flottes : zero changement sur zero hote.
make prouver : CONFORME, 63 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
7 machines du site deployees, 0 echec au playbook — et CINQ rapports sur
sept en TimeoutError. Un playbook vert ne prouve pas qu une chose
fonctionne ; seul l essai de bout en bout l a dit.
1. LE PAIR DE LA FRONTIERE. Le role client declarait son egress 5665, la
politique de sortie etait accept, la regle d entree de l hote autorisait
la source — et les paquets mouraient ENTRE les deux. La frontiere filtre
l inter-zones du site et ne resout que les roles que les machines PORTENT
AU PLAN ; une integration universelle n y figure pas, elle est derivee.
pair: client_sante produisait donc une regle est-ouest correcte et AUCUNE
regle a la frontiere. Le pair devient serveur_debian — le vocabulaire du
depot pour « tout noeud », que le generateur traite deja comme tel, et
exact au sens strict. Six regles creees, zero retiree, une par patte de
zone.
2. LE RAPPORTEUR S ACCUSAIT LUI-MEME. Pendant l heure de blocage,
setops-sante.service a echoue ; une fois debloque, cinq machines ont
rapporte CRITIQUE en citant leur propre rapporteur, et systemd garde l
etat failed jusqu a un reset-failed. Sa propre unite est desormais exclue
du compte — non par complaisance : sa sante est deja mesuree, et mieux,
par la FRAICHEUR de ses envois. S il ne peut plus parler, le ttl perime le
service, ce qui se voit precisement quand il ne peut PAS ecrire.
ETAT FINAL : 7/7 au site, 14/14 au tenant, tous OK. Controle negatif
rejoue sur les deux flottes.
make prouver : CONFORME, 63 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
CE QU IL FERME. openipmi.service echouait a chaque demarrage sur les
quatorze machines depuis le 2026-09-02, et systemctl --failed rendait ZERO
partout : non parce qu elles allaient bien, mais parce qu aucune n avait
redemarre depuis. Il a fallu qu un humain redemarre une machine pour que
le defaut existe aux yeux de quelqu un. Un controle qui ne peut echouer
qu au demarrage ne mesure rien tant que rien ne demarre.
PASSIF, ET A DUREE DE VIE. Un controle actif ne voit pas la machine MUETTE.
Ici c est le noeud qui parle, et le ttl de son envoi fait la fraicheur :
sans nouvelle, Icinga perime le service tout seul. Le silence alerte autant
que l echec. Le minuteur declenche AU DEMARRAGE autant que toutes les 15
min : les echecs de cette famille naissent au boot.
CRITIQUE DES LA PREMIERE UNITE, jamais un seuil — une unite en echec est
soit un vrai probleme soit du bruit a retirer, et un seuil ferait vivre le
bruit. Les tolerances se nomment une par une, vide par defaut.
CONTROLE NEGATIF. Unite factice sur obs-01, etat relu dans IcingaDB :
CRITICAL, et le verdict NOMME l unite. Les treize autres OK. Apres
nettoyage : 14/14 OK.
UN CONFLIT EVITE. setops-sauvegardes.conf definissait les object Host ; un
second fichier de controle aurait redefini les memes, et Icinga refuse un
objet en double — la configuration entiere aurait ete rejetee, donc AUCUNE
supervision, en voulant en ajouter. Les hotes vivent maintenant dans
setops-hotes.conf, definis une fois.
TROIS OBSTACLES. ${#tableau[@]} contient {# que Jinja lit comme un debut de
commentaire (remede : comment_start_string en tete du gabarit). Ma premiere
sonde a traduit un 403 « Missing permission: objects/query/service » en
« 0 service » — encore un echec qui ecrasait permission ; l etat se lit
dans IcingaDB. Et un echec apt transitoire sur mon-01, local et disparu au
second essai : mesure avant conclusion.
NON FAIT : le SITE n a pas recu client_sante.
make prouver : CONFORME, 63 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
make site-appliquer GROUPE=client_pki : 7 hotes, 0 echec. site-backup-01 a
recu quatorze changements — depot apt Smallstep, step-cli, STEPPATH, mot de
passe du provisioner, etablissement de la confiance dans l AC, certificat
d hote emis, unite et minuteur de renouvellement actives.
Verifie sur les sept : chaine VALIDE (step certificate verify contre la
racine locale), racine presente, timer cert-renewer@<fqdn>.timer en
enabled/active avec une passe ce soir. site-pki-01 est la seule sans ancre
dans /usr/local/share/ca-certificates/, et c est juste : elle PORTE l
autorite.
TROIS DE MES SONDES ONT MENTI AVANT LA BONNE : un nom d unite devine, puis
la colonne « service active » lue a la place de la minuterie — un service
declenche par minuteur est normalement disabled, ce qui se lit comme une
panne quand on regarde la mauvaise ligne. La question etait serieuse :
sans minuteur, les certificats du site expiraient dans 24 h.
Et le changed=2 des six autres machines n etait pas une non-idempotence :
c etait le depot initial de step-cli. Rejoue sur site-forge-01 : changed=0.
make prouver : CONFORME.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
make site-appliquer GROUPE=serveur_durci : 7 hotes, 0 echec, 0 injoignable.
Configuration reseau intacte sur les sept, ifquery rend l adresse attendue
sur chacune, zero unite cloud-init restante, zero unite en echec.
Le site HEBERGE, d ou la verification apres coup depuis les machines qui
ont le flux : la forge repond 200 et sert toujours ce depot au bon commit,
le cache APT repond 200, le DNS resout, step-ca rend status ok.
Le site ne portait pas le piege openipmi : il n applique pas
client_metrique.
TROUVE EN VERIFIANT, SANS RAPPORT : site-backup-01 est DANS le groupe
client_pki et n a ni /etc/step, ni minuterie de renouvellement, ni meme la
racine de l AC. Les six autres ont leur certificat et leur minuterie
quotidienne. L appartenance au groupe dit « couverte », la machine dit le
contraire. Non corrige — c est une decision d exploitation.
Corrige au passage deux affirmations fausses du CHANGELOG : le site n est
plus « arme, pas applique », et il ne faut pas passer par site-ops-01 pour
le deployer.
make prouver : CONFORME.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
LE REDEMARRAGE A TENU. obs-01 a redemarre avec son disque cloud-init
RETIRE de Proxmox — sans paquet et sans source de donnees — et elle est
revenue avec son adresse, sa passerelle et son resolveur. Le retrait de
cloud-init est desormais prouve par un demarrage reel.
ET IL A REVELE AUTRE CHOSE. Une unite en echec : openipmi.service. La
chaine est prometheus-node-exporter -> recommande collectors -> recommande
ipmitool -> recommande openipmi. Trois recommandations en cascade,
raisonnables sur du metal. Dans une VM il n y a pas de BMC et le script d
init echoue a chaque demarrage.
LE POINT N EST PAS LE PAQUET, C EST POURQUOI PERSONNE NE L AVAIT VU.
openipmi datait du 2026-09-02. systemctl --failed rendait pourtant ZERO
sur les quatorze machines — non parce qu elles allaient bien, mais parce
qu aucune n avait REDEMARRE depuis. Six jours et vingt heures pour obs-01.
Un controle qui ne peut echouer qu au demarrage ne mesure rien tant que
rien ne demarre.
Le degat n est pas cosmetique : une unite en echec permanent use le seul
signal qui devrait alerter. Le jour ou une vraie unite tombe, --failed
rend 2 au lieu de 1, et personne ne fait la difference.
CORRECTION A LA SOURCE ET CONDITIONNELLE. client_metrique retire ipmitool
et openipmi, mais SEULEMENT dans une VM (virtualization_role == guest) :
sur du metal le collecteur IPMI est legitime. Ils ne sont que RECOMMANDES,
donc les retirer n emporte pas les collectors, qui servent. Un handler
efface l etat failed que le retrait ne nettoie pas.
Applique aux quatorze : ipmi=0, collectors=1, node_exporter=active,
echecs=0. Second passage : zero changement sur zero hote.
RESTE OUVERT : rien dans le harnais ne regarde systemctl --failed sur la
flotte. Ce defaut a ete trouve parce qu un humain a redemarre une machine.
make prouver : CONFORME, 63 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
CE QUE JE DISAIS ETAIT FAUX. « Il n y a rien sur origin » — le DEPOT y
est, et a jour, exactement notre HEAD. C est le WIKI qui etait vide. Je
l avais recopie d une session precedente sans le remesurer.
LA GARDE AVAIT RAISON DE REFUSER, ET TORT DE S ARRETER LA. wiki-publier
refuse un wiki vide parce que publier y inventerait un nom de branche.
Son message renvoyait a l interface Forgejo — injoignable depuis ce poste,
et ce n est pas une panne : la forge du site n accepte le 443 que des
machines qui declarent le flux.
Forgejo DECLARE pourtant la reponse : wiki_branch, dans son API. Interroge
depuis ops-01 — machine qui a le flux — il repond main. On ne devinait
pas : on ne demandait pas. WIKI_BRANCHE= ajoute a la recette, le refus
reste le defaut. Les deux cotes eprouves.
Resultat : 26 pages sur les deux forges, contenu identique au fichier pres.
LECON D INSTRUMENT. Trois sondes fausses avant la bonne : connect() direct
rend TimeoutError (politique, pas route manquante) ; un tunnel par la
frontiere ne repondait pas ; et git ls-remote fonctionnait tres bien, parce
que ~/.ssh/config passe par un ProxyJump que la sonde ignorait.
make prouver : CONFORME, 62 OK, 0 echec, 1 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Applique apres confirmation. Ordre suivi : obs-01 seul d abord, verifie,
puis les treize autres.
Releve sur les quatorze machines : paquet=0, unites=0, reseau=oui,
drapeau=oui, networking=enabled, echecs=0 — et sur chacune, ifquery rend
EXACTEMENT l adresse vive. C est le point : ifquery ne lit pas la memoire
du systeme, il RELIT le fichier que le retrait aurait pu emporter, donc il
repond ce que le prochain demarrage fera.
Second passage sur obs-01 : changed=1, et ce seul changement est la tache
nftables_baseline qui se declare toujours modifiee, anterieure a ce
chantier. Le retrait est idempotent.
make valider apres deploiement : 0 echec, 0 injoignable.
CE QUI N EST PAS PROUVE. Aucune machine n a ete REDEMARREE : la garde de
securite du poste a refuse le redemarrage, et on ne contourne pas une
garde. Le chemin de demarrage a donc ete prouve autrement — networking
(ifupdown) actif, systemd-networkd desactive, ifquery relit le fichier et
rend la bonne adresse, zero unite cloud-init dans multi-user.target, zero
unite en echec, nom d hote et cles SSH persistants. C est fort, ce n est
pas un redemarrage.
LE SITE. SITE-Chezlepro est une autre instance de CE depot : meme
serveur_durci, memes roles. Ses sept machines actives sont durcies depuis
le 2026-09-02 — leur prochain passage retirera cloud-init chez elles
aussi. Le site se deploie depuis son propre runner, pas depuis ce poste.
make prouver : CONFORME, 62 OK, 0 echec, 1 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
La premiere redaction se lisait comme une emancipation. Elle n en est pas
une, et il valait mieux le dire que de laisser un lecteur presse en
conclure trop.
Retirer cloud-init n ote AUCUN pouvoir a l hebergeur. qemu-guest-agent est
au gabarit — il doit y etre (P56) — et l API Proxmox expose sur son dos,
sur toute VM vivante de la flotte, un pouvoir strictement plus grand que
le lecteur cloud-init. Releve le 2026-09-09 sur edge-mta-01, avec le jeton
du site : exec, exec-status, file-read, file-write, set-user-password,
shutdown.
Ce que D-85 ferme est donc precis et etroit : une reapplication
AUTOMATIQUE a chaque demarrage, depuis un support que le plan ne possede
pas et qu aucune preuve ne lit ; et le code de cloud-init lui-meme, un
interpreteur Python complet execute en root au boot avec ses ~29
dependances. La mainmise d un hyperviseur sur ses invites est une
propriete de la VIRTUALISATION, pas de cloud-init — elle appelle sa propre
decision, qui n est pas prise.
LE SEUIL EST NOMME. L alternative existe et sa piece est deja au gabarit :
poser adresse et cle par agent/file-write + agent/exec, sans reseau.
Aujourd hui ce serait reimplementer un standard, ce que positionnement.md
interdit, au moment le plus fragile et pour le pire mode de panne — une VM
injoignable. Le jour ou une premiere seconde ne pourra plus etre amorcee
par Proxmox (autre hyperviseur, metal nu, hebergeur sans API), ce chemin
devient LE chemin portable.
La nuance est portee partout ou l affirmation est faite : D-85, le README
et l entete du role, AGENTS.md, le wiki.
make prouver : CONFORME, 62 OK, 0 echec, 1 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
cloud-init n est pas un logiciel d installation : c est une SOURCE DE
VERITE EXTERNE. Il se reveille a chaque demarrage et relit le lecteur
attache par l hyperviseur, qui peut redefinir comptes, cles SSH, mots de
passe et reseau. Sur une machine que le plan possede, c est un second
maitre — que le plan ne decrit pas, que make valider ne mesure pas, et
qui parle en premier.
Sa tache est finie a la premiere seconde : c est parce qu il a REUSSI a
poser l adresse et les cles qu Ansible a pu entrer.
TROIS MOITIES, ET ELLES SE DEFONT SEPAREMENT.
- le GABARIT le garde : sans lui un clone n a ni adresse ni nom ;
- le SOCLE ne l installe plus : le garder produisait un va-et-vient a
chaque deploiement, deux changed par passage, idempotence perdue ;
- le DURCISSEMENT le retire (roles/cloud_init_retrait, en dernier).
P63 garde les trois, plus le CONTENU du role : une coquille vide passerait
les trois premiers controles sans rien fermer. Quatre controles negatifs
rejoues.
CE QUI REND LE RETRAIT SUR EST MESURE, PAS SUPPOSE (obs-01, 2026-09-09) :
/etc/network/interfaces.d/50-cloud-init n appartient a aucun paquet — dpkg
-S ne le trouve pas — et le postrm ne le nomme jamais, meme en purge.
L adresse survit. Le role le verifie quand meme, avant et apres, et n
accuse que si le retrait l a emporte : une VM qui perd ce fichier ne se
plaint pas, elle repart sans adresse et plus personne ne peut entrer.
DEUX CHOIX DITS FRANCHEMENT. cloud-guest-utils reste (growpart : ni
service, ni port, ni source de donnees). Les ~29 paquets orphelins ne sont
pas retires par defaut : autoremove deciderait a partir des drapeaux dpkg,
et un durcissement ne doit pas pouvoir surprendre.
NON DEPLOYE : le code est ecrit, valide et prouve ; il n a pas ete
applique a la flotte. Essai a blanc sur obs-01 : cloud-init a retirer,
configuration reseau intacte.
make prouver : CONFORME, 62 OK, 0 echec, 1 saute (63 preuves).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
CHAMPS_ECRITS_A_LA_MAIN est vide. Serveurs et applications, les deux plus
gros, sont passes au generateur — chargement, rendu et sauvegarde.
L EPREUVE QUI COMPTE. Ouvrir chaque vue et enregistrer sans rien toucher
doit renvoyer exactement le plan qu on vient de lire : 14 serveurs, 25
applications, 2 domaines, 4 bases, IDENTIQUE partout. C est ce qui separe
un formulaire genere d un formulaire qui en a l air — un champ visible a
l ecran et perdu en silence a l enregistrement serait le pire des deux
mondes. test_rendu_gui.py le mesure a chaque make prouver.
TROIS DEFAUTS TROUVES EN CHEMIN.
Le formulaire annoncait des defauts INVENTES : 2048 Mo, 2 coeurs, 16G. Il
n existe aucun defaut fixe — deriver_ressources calcule depuis les roles
portes (1024 et 1 pour infra-pki-01, 5632 et 4 pour collab-01). Un repere
faux fait croire qu on connait la valeur. Le schema nomme le champ derive,
et l ecran montre la valeur reelle de cet hote. L option vide d un select
dit desormais ce qu elle produira : « (defaut : asgard) ».
Une SECONDE occurrence du defaut d hier dormait dans sourceDeValeurs :
elle lisait encore data.nomenclature. Elle n avait jamais leve parce que
la vue Serveurs, seule a emprunter cette source, avait un formulaire ecrit
a la main. Elle a leve a la seconde ou le generateur l a prise. Le banc ne
voit que les chemins vivants : verifier_gui.py fait donc aussi une
verification STATIQUE, qui voit ce qui dort.
La validation client s accrochait a data-v, pose a la main sur trois
champs. Le formulaire genere l aurait perdu et la validation serait passee
au vert sur ZERO champ. Le generateur marque chaque controle, et la
sauvegarde refuse si elle n en inspecte aucun.
DEUX CHAMPS GARDENT LEUR EDITEUR, et le schema le dit (x-editeur) : la
matrice des integrations montre les universelles et les exemptions, et
l editeur de liens contraint le role a meta/liens.yml. Le generateur s
efface plutot que de remplacer un editeur qui en sait plus que lui.
LIMITE : je n ai toujours pas ouvert ces pages dans un navigateur.
make prouver : CONFORME, 61 OK, 0 echec, 1 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
En voulant generer deux formulaires de plus, j ai trouve pire que ce que
je cherchais.
CE QUI ETAIT DEJA LA. Les quatre ecrivains de registre ecrasaient le
fichier au safe_dump. Mesure sur les fichiers reels : domaines.yml 6->3,
applications.yml 27->5, serveurs.yml 18->3. Quarante lignes, detruites
par n importe quel clic sur Sauvegarder dans les vues Serveurs,
Applications ou Domaines. Parmi elles, celle qui explique pourquoi
backup-01 a ete retire, et celle qui dit dans quel ordre les deux roles
du runner s appliquent. C etait l incident du 2026-08-18, jamais corrige
pour les registres du plan. Les quatre passent par _ecrire_registre :
aller-retour a vide identique a l octet, sur les quatre fichiers.
TROIS ECARTS DE SCHEMA, trouves en confrontant le schema aux VALIDATEURS
et non aux seuls plans :
- edge designe un GROUPE, pas un hote. Le schema disait serveurs : un
formulaire genere aurait offert une valeur qu aucun hote ne reconnait,
donc aucun SAN, donc la panne du 2026-08-25 reintroduite ;
- exposition, entierement valide par le moteur, manquait au schema ;
- liens etait items: {type: object} — une liste d objets sans forme.
Et mail, offert par la vue Domaines depuis sa creation, decrit ici comme
un booleen, saisi la-bas comme du texte, lu par rien : retire.
P62 garde tout ca. Elle separe l entite du reste mecaniquement : un
validateur lit son entite par des variables LOCALES, les autres registres
par ses PARAMETRES. Controle negatif rejoue.
LES FORMULAIRES. Serveurs de BD et Domaines sont generes, chargement et
sauvegarde compris. Quatre registres sur six. Le generateur a appris la
liste d objets.
LIMITE : restent serveurs et applications, les deux plus gros ; et je n ai
toujours pas ouvert ces pages dans un navigateur.
make prouver : CONFORME, 61 OK, 0 echec, 1 saute (62 preuves).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q