Commit graph

39 commits

Author SHA1 Message Date
8d40c687e1 site : journaux allégés, porteur de santé retiré des hyperviseurs
- client_sante : tasks/retirer.yml, joué sur hyperviseurs:!client_sante ;
  le minuteur resté depuis le 2026-09-10 visait 10.0.36.11 et échouait
  toutes les 15 min (une unité en échec permanente par hyperviseur)
- site_inventaire : plus de client_sante_icinga_url pour les hyperviseurs
- client_journal : loki.process jette le bruit de la sonde connectivite,
  phrase exacte et seulement depuis une machine de client_sante
- serveur_loki : log_level warn (Loki réingérait ses propres requêtes)
- auditd : règle never pour adjtimex de node_exporter (35 % de l'audit) ;
  nouveau handler augenrules --load, un restart d'auditd ne rechargeait
  pas les règles sur Debian 13
- audit : rapport de preuves du 2026-10-03, carte à 51 pièces

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:58:47 -04:00
788c5073dc DNS public, phase 1 : le locataire ecrit, le site sert
Role serveur_dns_public (secondaire public, transfert signe TSIG, aucune zone interne) ;
serveur_powerdns exerce enfin autorite primaire-cache dans une instance pdns@public a part,
pour que le site ne puisse jamais interroger la zone .internal. Relations derivees des plans
des locataires, mots de flux dns_public_site et primaires_dns_locataires. Eprouve avant
d ecrire : allow-axfr-ips et TSIG sont alternatifs, le primaire notifie aussi ses NS, le
serial fige aurait gele le secondaire. P82 refuse l exposition sans DNSSEC.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 18:08:20 -04:00
bef0655112 le site reconstruit depuis zero : 7/7, 0 echec, et seize corrections
SITE-Chezlepro n avait jamais ete rase. La limite qu on repetait partout —
l infrastructure d accueil n a jamais ete reconstruite depuis zero — se
lisait comme de la prudence. C etait seize defauts que rien d autre n aurait
pu reveler.

Un locataire naît dans un monde deja peuple : le site lui fournit paquets,
noms, genome, heure et depot. Un site n a personne au-dessus, sauf sa
frontiere. Onze des seize murs viennent de la.

DEUX CAPACITES QUI N EXISTAIENT PAS. make site-raser — rien ne detruisait les
machines du site, donc la limite etait un trou d outillage. make
forge-amorcer — la forge naît vide et le runner y clone ; l amorcage part du
poste, seul endroit qui detienne alors le genome.

TROIS GARDES QUI VERIFIAIENT LA FORME. La plus couteuse des familles : elles
donnent l apparence d une verification. Le resolveur comparait des adresses
au lieu de mesurer si la resolution aboutit, et protegeait ainsi l etat
casse. L administration etait reconnue a son port. Un flux a deux paires
n obtenait qu une branche.

UN ECART DE SECURITE. Le PostgreSQL du site servait le certificat auto-signe
de Debian, sans reseaux autorises ni hostssl — invisible tant qu aucun client
n exigeait la verification. Le defaut n a pas casse la construction : la
construction a revele le defaut.

UN ACCES ACCIDENTEL. Celui de l exploitant tenait au chevauchement d
adressage que le renumerotage a supprime. Separer les index n a pas cause le
probleme, il a retire le hasard qui le masquait.

La sequence du premier jour est ecrite : runbooks §9, avec les seize murs et
ce que chacun enseigne.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-12 19:08:31 -04:00
c6a7150c60 les depots tiers passent par le cache, et le tenant n a plus le sien
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
2026-09-10 14:53:48 -04:00
6d23121dc2 supervision : systemctl --failed entre dans Icinga (role client_sante)
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
2026-09-09 20:32:08 -04:00
53d7b4c4c2 durcissement : cloud-init nait avec la VM et ne lui survit pas
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
2026-09-09 09:25:42 -04:00
3ea0c95492 sauvegarde : l etat d un locataire quitte enfin sa propre flotte
Some checks are pending
verifier / verifier (push) Waiting to run
Chezlepro rangeait ses instantanes sur une VM DE SA PROPRE FLOTTE. Raser
l ecosysteme pour le reconstruire, c etait raser le filet avec.

Le site a son depot ; les neuf detenteurs d etat y deposent ; une
restitution est sortie (annuaire LDAP lisible, hors flotte).

Isolation par compte Unix, pas par convention : home 0700, cle exclusive,
racine partagee a root en 0711 (traversable, non listable). Les deux refus
constates. Le site heberge du chiffre : il ne peut ni lire ni ouvrir, d ou
la verification deplacee chez le locataire qui detient la cle.

Quatre defauts reveles par ce deuxieme usage :
- la racine des depots ne peut etre le home de personne (StrictModes rendait
  Permission denied publickey pour un refus de CHEMIN)
- la racine nie le TLD internal, et harden-below-nxdomain etendait ce non a
  toute la zone sans jamais interroger l autoritatif : aucun locataire ne
  pouvait nommer un service du site
- le gabarit transporte des fichiers de durcissement perimes, et les machines
  du site ne recoivent jamais ssh_hardening
- MaxStartups compte les connexions non authentifiees : un depot de site en
  voit la somme de ses locataires

Constat non corrige : les machines du site ne sont pas durcies.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-01 22:16:20 -04:00
a5c9a88f00 resolveur du site : le troisieme service prete pendant la jeunesse d un tenant
Apres les paquets (serveur_cache_site) et le genome (serveur_forge_site), les NOMS.
Meme patron : un installateur, un marqueur.

CE QUE CA CORRIGE, mesure sur infra-pki-01, premiere machine a porter l autorite
de Chezlepro :

    DNS               BLOQUE      un tenant resout chez lui, sa requete ne sort pas
    443 sortant       OK          par adresse
    apt via le cache  OK          le mandataire resout a sa place

apt s en sortait ; TOUT LE RESTE ETAIT AVEUGLE AUX NOMS. Versionner la cle de
signature Smallstep a fait passer une tache et l echec s est deplace d un cran : le
depot lui-meme devait etre joint par son nom.

POURQUOI PAS L UNBOUND DE LA FRONTIERE : il tourne sur le boitier sans etre un
service gere, et le plan du site l avait deja ecrit une fois — un processus n est
pas un service. site-dns-01 est deploye par le moteur et verifie par le harnais.

OU VIT LA DERIVATION : dans site_inventaire.py, qui connait le plan du site ET le
registre des tenants. Le role tourne sur une machine qui n a aucune raison de lire
la carte de l hebergeur — la derivation appartient a qui detient les deux sources.

PIEGE DE FILTRE, ATTRAPE EN LE BRANCHANT : _supernets_voisins() EXCLUT l instance
montee (personne n est son propre voisin). Le site sert TOUS ceux qu il heberge — y
compris celui qu on deploie. Reutilise tel quel, il privait de resolution le seul
tenant en cours de montage. On reutilise donc la DECOUVERTE partagee sans son
filtre : deux recensements divergent, deux filtres non.

Le marqueur verifie deux choses : que le resolveur ECOUTE, et que sa liste
d autorisation ADMET reellement les tenants. Sans la seconde, la panne chez le
locataire ressemblerait a un DNS mort alors que c est une ACL.

make verifier : vert. make prouver : CONFORME, 55 OK, 0 echec, 0 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-08-30 12:37:33 -04:00
58ce3dfea4 forge du site : le marqueur manquant — le genome n etait ouvert a personne
MEME PATRON QUE serveur_artefacts + serveur_cache_site : un installateur, un
marqueur. Le site rend DEUX services a ses locataires pendant leur jeunesse, les
PAQUETS et le GENOME. Le premier etait declare, le second ne l etait pas — alors
que D-81 fait de cette forge l autorite dont tout ecosysteme se reproduit.

Mesure sur ops-01, premiere machine de la reconstruction de Chezlepro :

    cache du SITE 10.0.33.21:3142 : OK
    forge du SITE 10.0.33.11:443  : BLOQUE

Le plan du tenant declarait pourtant lire son genome a cette adresse. UNE
DEPENDANCE DECLAREE CHEZ LE CONSOMMATEUR, SANS FLUX CHEZ LE FOURNISSEUR — et rien
ne le signalait : la garde de matrice de resoudre_flux ne verifie que les paires
role->role, jamais un pair symbolique comme voisins_site.

POURQUOI UN ROLE A PART : ajouter cet ingress a serveur_forgejo aurait ouvert LA
FORGE DE CHAQUE TENANT a ses voisins. La responsabilite appartient a une machine
precise, pas au logiciel qu elle fait tourner.

Il verifie que la forge ECOUTE vraiment : sans ca il attribuerait l autorite du
genome a un port muet, et l ecosysteme venu s y reproduire attendrait sans savoir
pourquoi — ce qui est exactement arrive, quinze minutes durant.

TROIS GARDES ONT TRAVAILLE : le catalogue a refuse un role qu il ne nomme pas, la
carte a corrige ses deux chiffres, et P49 a exige la regeneration du registre.
P33 a impose partage: true — le marqueur emprunte l ecoute de serveur_forgejo.

Frontiere : 4 objets crees, 0 retire. Verifie depuis ops-01 : 443 OK.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-08-28 16:15:42 -04:00
5e4d711b97 socle : la source d'artefacts d'amorcage — nourrir la premiere machine
LA PREMIERE MACHINE D'UN ECOSYSTEME N'A NI RESOLVEUR NI CACHE, ET C'EST ELLE QUI
DOIT LES CONSTRUIRE. Mesure sur ops-01, premiere machine de la reconstruction de
Chezlepro : le socle restait bloque sur son premier apt update.

    sortie Internet TCP 443    OK
    DNS UDP 53 -> 9.9.9.9      MUET

Le DNS sortant est ferme PAR CONCEPTION — un tenant resout chez lui. Or apt vise
deb.debian.org par son NOM, et le cache de l'ecosysteme n'existe pas encore.

UN MANDATAIRE HTTP RESOUT CE QUE LE CLIENT NE PEUT PAS RESOUDRE : apt lui envoie
l'URL absolue et c'est lui qui traduit. La machine n'a besoin d'aucun DNS, seulement
d'une ADRESSE. Symetrique exacte de , meme place dans le socle.

AUCUN FLUX A OUVRIR :  accepte deja le 3142 depuis
, qui resout les SUPERNETS des tenants — donc toute machine, pas
seulement leur cache. Verifie depuis ops-01 : HTTP 200 en 0,158 s.

C'EST DE LA FILIATION, PAS UNE RUSTINE. L'emprunt est declare (l'intrant nomme
l'amont) et il s'efface :  ecrit 00-setops-artefacts, qui trie
APRES, donc gagne des que l'ecosysteme a sa source. Le plancher reste dessous,
comme /etc/hosts reste sous le DNS. Le retirer le jour venu est une emancipation —
un geste, pas un effet.

DIAGNOSTIC CORRIGE EN CHEMIN : j'avais lu "BLOQUE" vers le resolveur, le cache et
la PKI du tenant comme un pare-feu. C'etait une ABSENCE — ops-01 est la seule VM de
Chezlepro qui existe. Un port muet ressemble a un refus.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-08-28 15:05:11 -04:00
8890c997af runner : serveur_ops_tenant — le runner d'un tenant recoit enfin sa voute
Some checks are pending
verifier / verifier (push) Waiting to run
La doctrine des runners decrit trois portees depuis le 2026-08-22 :

  calculer      plan -> inventaire        aucune voute        serveur_ops
  configurer    roles sur ses machines    voute du TENANT     <- revendiquee, jamais recue
  materialiser  creer/detruire des VM     voute du SITE       serveur_ops_site

La deuxieme ligne etait un trou. RIEN ne deposait jamais la voute d'un tenant sur
son runner. Un runner pouvait deriver son inventaire et ne rien pouvoir en faire :
chaque role qui demande un secret echouait sur son assertion, et l'echec ne disait
pas qu'il manquait un FICHIER, seulement que les valeurs etaient vides.

Decouvert en preparant la reconstruction de Chezlepro. Le runner du SITE peut
materialiser ses quinze machines ; il ne peut pas les configurer, parce que
Chezlepro a sa PROPRE autorite de certification — donc `client_pki` y reclame un
secret de Chezlepro. Le runner du site ne l'a pas, et NE DOIT PAS l'avoir : c'est
la ligne qui rend l'hebergement mutualise defendable.

`serveur_ops_tenant` est le symetrique exact de `serveur_ops_site` : un MARQUEUR,
pas un installateur. Il depose la voute `decrypt: false`, puis RELIT l'en-tete du
fichier depose — une voute dechiffree par accident est une fuite silencieuse. Le
dossier d'inventaire (`principal` ou `production`) se DECOUVRE sur la machine
plutot que d'etre ecrit.

Pourquoi un role a part et non une option de `serveur_ops` : donner sa voute a un
runner est un POUVOIR, pas un reglage. Le declarer au plan force a repondre a
« cette machine a-t-elle le droit de configurer cet ecosysteme ? » — une option
activee par defaut y repondrait a notre place.

CHEZLEPRO LISAIT ENCORE SON GENOME CHEZ PATIENT 0.

Trouve au passage, et bloquant pour la reconstruction : `serveur_ops_forge_amont`
pointait sur `10.29.16.11` — la forge de patient 0, l'amont d'avant que le site
ait la sienne. D-81 a tranche depuis. Laisse tel quel, Chezlepro se serait
reconstruit depuis un moteur perime, sur un reseau que le decoupage en zones a de
toute facon deplace.

Corrige vers la forge du site, PAR SON IP — `forge.genese.internal` appartient a
la zone souveraine du site, et un tenant ne resout que la sienne ; le certificat
SERVI porte bien `IP Address:10.0.33.11`. La racine de l'AC du site est desormais
versionnee a cote de la carte de la fabric a laquelle elle appartient, et son
chemin se DERIVE du symlink `underlay.yml` : il vaut depuis le poste comme depuis
un runner.

Le role est inscrit dans les quatre registres qui l'exigeaient — couches de
deploiement, graphe des dependances, catalogue des services, carte d'orientation.
Ce sont les preuves P08, P38 et P48 qui l'ont reclame, chacune a son tour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:30:51 -04:00
1a7c042e5b site : quatre zones d'autorite, et l'ordre inscrit dans les integrations
Le site n'est plus un /24 plat. Une zone par nature d'autorite — pilotage, autorite,
genome, service — chacune son VLAN et sa patte sur la frontiere. L'inversion corrigee,
mesuree : les cinq VM du site n'avaient AUCUN filtrage est-ouest, contre policy_in=DROP
sur une machine de tenant. La plus autoritaire etait la moins protegee.

Filtrage nord-sud par choix de l'exploitant : un seul point de police, un seul devis.
90 -> 117 regles. Chaque flux `flotte` produit une regle par zone SOURCE, destination
nommee — ce qui etait gratuit devient police.

L'ORDRE FAIT PARTIE DE L'INTEGRATION. client_pki tournait en parallele sur tous les hotes ;
sur celui qui porte l'autorite il recharge step-ca, et les quatre autres echouaient dans
cette fenetre sur `TLS handshake timeout` — un message qui accuse le reseau. Chaque
integration declare desormais sa dependance dans meta/integration.yml, les playbooks en
sont le miroir genere, et P44 refuse l'ecart (4 controles negatifs). `serveur: ~` est une
reponse valable : client_metrique pose un exportateur qu'on vient LIRE.

Autres defauts du meme soir :
  - le plancher /etc/hosts venait APRES le premier apt, qui vise le cache par son NOM :
    boucle fermee des que les adresses changent. Il ne s'installe pas, il rend installable.
  - dns_amorcage ecrit en dur a eu tort deux fois ; il se derive de serveur_resolveur.
  - l'ACL du resolveur derivait d'un seul sous-reseau : trois zones refusees sur quatre.

ET UNE ERREUR A MOI : j'ai diagnostique un trou noir de MTU et declare 1450. Faux — pas de
VXLAN sur ce chemin, tout est a 1500 de bout en bout. Ma mesure etait reelle, mon
interpretation non : je venais de debrancher la carte a chaud, et chaque `ip link set mtu`
reconfigurait l'interface. C'est la reconfiguration qui debloquait, pas la valeur.

44 preuves vertes, ansible-lint profil production.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 17:31:07 -04:00
ea67b75a15 dns : le site resout chez lui, et le socle cesse de le defaire
Mise au point de l'exploitant : la frontiere n'a pas de service DNS actif et gere. Un
Unbound y tourne — il repondait, ce qui m'a induit en erreur — mais un processus n'est pas
un service. La delegation de zone que j'y avais posee est retiree.

Et le site a son propre DNS : `dns_amorcage` pointait encore sur la frontiere, valeur d'un
moment ou site-dns-01 n'existait pas. Elle vaut desormais 10.0.3.51.

Deux defauts revelés au passage :

  - devis_opnsense lisait encore underlay.machines(), vide depuis le deplacement du plan.
    Il proposait de RETIRER 36 objets — tous les alias et regles du site. Aucune preuve ne
    couvre ce devis : c'est le plan avant application qui l'a attrape.
  - le socle defaisait la bascule de client_resolveur a chaque passage. Sa garde ne
    protegeait que l'hote du resolveur (127.0.0.1). Invisible chez un tenant, ou
    dns_amorcage vaut l'adresse du resolveur : la coincidence masquait le defaut. Ca ne
    s'est vu qu'en retirant la regle de pare-feu — les cinq machines ont perdu la
    resolution d'un coup.

L'amorcage ne s'applique plus que si rien de sense n'est en place. Verifie : socle
`changed=0`, les cinq machines restent sur 10.0.3.51.

42 preuves vertes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 13:57:48 -04:00
6e126dd8a9 site : le chemin qui materialise les machines de l'hebergeur
- site_machines.py : traduit une declaration d'underlay en SETOPS_*, que cloner-vm
  consomme deja. Le clone reste le seul chemin eprouve.
- site_inventaire.py : inventaire DYNAMIQUE. Un site ne derivant de rien, sa declaration
  est deja sa forme finale — un hosts.yml genere ne rendrait rien plus inspectable.
  Les groupes sont les services : playbooks/groupes/<role>.yml trouve ses hotes seul.
- cibles site-decrire / site-inventaire / site-creer (CONFIRMER=true) / site-appliquer,
  toutes independantes d'une instance montee : le site existe avant tout tenant.
- playbook de groupe manquant pour serveur_cache_site, et son classement en couche.

Le premier garde-fou de site-appliquer refusait un GROUPE vide : il ne pouvait jamais
se declencher (GROUPE a un defaut global). Le vrai risque, observe en le testant : un
playbook de tenant contre l'inventaire du site ne matche aucun hote et sort avec 0 — un
succes qui n'a rien fait. Refus desormais de tout groupe absent de cet inventaire.

42 preuves vertes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 23:11:32 -04:00
db2d6f6bf0 resolveur : un par tenant, et non plus un par machine
Mesure avant de decider : ~21 Mo de RSS par VM pour 28 a 189 requetes servies.
Le gain de cache est negligeable ; ce qu'on recupere, c'est un demon au lieu de
cinq et un endroit a regarder au lieu de cinq.

Pas sur la frontiere : un resolveur de SITE devrait connaitre la zone interne de
chaque tenant, et un tenant dont le resolveur vit chez l'hebergeur ne peut plus
s'emanciper avec. La recursion est generique, la zone interne ne l'est pas.

L'autoritatif se replie sur 127.0.0.1:5300 -- derive de la colocalisation, pas
declare a la main. Son port devient `derive` dans meta/flux.yml : les deux lient
53 mais sur des adresses differentes.

Deux pieges. Unbound refuse d'interroger une loopback par defaut : sans lever
do-not-query-localhost, toute la zone rendait SERVFAIL. Et le plancher
/etc/hosts MASQUAIT la panne -- getent repondait, dig disait SERVFAIL. La tache
de validation du role avait raison contre moi.

client_unbound n'installant plus Unbound, son nom mentait : client_resolveur.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 16:59:34 -04:00
2b55761fba runner : separer le pouvoir de configurer de celui de materialiser
La ligne de partage est celle des voutes. serveur_ops calcule et configure --
voute du tenant, SSH chez lui. serveur_ops_site materialise -- voute du SITE,
API de l'hyperviseur, jamais de SSH chez un tenant.

Un runner par tenant qui materialiserait mettrait la voute du SITE en N
exemplaires. Un runner unique qui ferait tout traverserait le default-deny
inter-tenant et rendrait l'emancipation impossible.

Le role depose la voute CHIFFREE et relit l'en-tete apres avoir ecrit : sans
`decrypt: false`, Ansible dechiffre la source quand il detient le mot de passe
-- constate le jour meme, 776 octets en clair au lieu de 3465. Controle negatif
fait, la garde mord.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 15:30:03 -04:00
32e1f6fbcd artefacts : la forge sert le code, il manquait qui sert les binaires
Some checks failed
verifier / verifier (push) Has been cancelled
serveur_artefacts (apt-cacher-ng) + client_artefacts, integration universelle
qui s'eteint quand aucun hote ne porte le service et RETIRE la direction posee.
Chez patient 0 : colocalise sur forge-01 -- la forge est la source, du code et
des binaires.

La preuve est le mode hors ligne : paquet en cache servi en 0 o/s, paquet absent
refuse par un 503. Tant qu'internet repond, un apt update qui reussit ne dit pas
d'ou vient l'octet.

Trois lecons : apt fait heriter Acquire::https::Proxy de la valeur HTTP (d'ou
403 CONNECT denied sur les depots tiers, et smallstep injoignable) ; un service
ne doit pas dependre de lui-meme pour se reparer (l'apt update du role passait
par le cache hors ligne) ; et rediriger 2>/dev/null, c'est choisir de ne pas
voir.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 14:41:56 -04:00
665b07ba82 serveur_ops : la difference entre une archive et une matrice
Some checks are pending
verifier / verifier (push) Waiting to run
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.

Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.

setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.

Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.

Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
cc6026641f empreintes muettes, courses de premier demarrage, collision de noms
Quatre meta/empreinte.yml declaraient leurs valeurs A LA RACINE, sans la cle
`setops_empreinte:` : collabora, nextcloud, web_dorsal, web_frontal. Le lecteur
les voyait vides et rendait {0,0,0} — en silence. collab-01 s'est retrouvee avec
1 coeur / 1 Go pour porter Nextcloud ET Collabora, et a cesse de repondre en SSH
faute de memoire. Corrigee : 4c/5632Mo. Une garde refuse desormais cette forme.

Un fichier qui existe mais ne dit rien est pire qu'un fichier absent : le repli
aurait donne des valeurs sensees.

Deux courses de premier demarrage :
- le clone rend la main avant que son .conf existe -> attente active sur l'API ;
- le verrou dpkg frappait hors de `common_packages` -> `lock_timeout` pose en
  module_defaults sur les 30 playbooks de groupe, une declaration au lieu de 30.

Au passage, j'ai failli livrer pire que le defaut : une URL coupee avec `>-`
inserait une ESPACE en son milieu. Le lint passait, la requete non.

Enfin : `proxmox_kvm` identifie une VM par son NOM. Une VM heritee homonyme lui
a fait rapporter `ok` sans rien cloner — un deploiement peut donc PARAITRE
reussi alors qu'aucune VM n'existe. Touche D-37 directement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 16:22:38 -04:00
ba70b80197 amorcage_acces : le role qui cree UN acces puis se retire
Cree uid=sysadmin et cn=sysadmin dans LDAP. Prouve sur idm-01 : le compte
s'authentifie, et le second passage ne touche a rien (changed=0, 7 taches
sautees) — idempotence par EXISTENCE, pas par conformite (D-67).

Il suit l'annuaire au lieu de se declarer au plan : il ecrit par `ldapi:///` et
doit tourner sur cet hote. Le declarer comme groupe obligerait chaque instance a
le poser sur le bon hote, et elles ne le nomment pas pareil (idm-01 ici,
id-ldap-01 chez Technolibre) — je l'ai d'abord pose sur infra-pki-01 par erreur.

Trois defauts trouves en le construisant :

1. `pwdReset` n'existe pas dans ce schema (overlay ppolicy non charge) :
   l'entree entiere etait rejetee et `no_log` masquait la cause. J'avais suppose
   un mecanisme sans verifier. Le role le DETECTE maintenant, et la doctrine ne
   promet plus un changement force qui n'a pas lieu.

2. Le mot de passe aurait ete stocke EN CLAIR : `ldap_entry` ecrit userPassword
   litteralement. Hache par `slappasswd -h {SSHA}` desormais.

3. `voute.py` ne scannait que roles/<groupe> : un role applique par un playbook
   sans etre un groupe echappait au recensement, ce que D-20 interdit. Il suit
   maintenant les listes `roles:` des playbooks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 13:42:27 -04:00
e276e76f32 dns : client_unbound universel, et un resolveur d'amorcage
Une VM ne peut pas s'installer sans resoudre des noms. PowerDNS repond
UNIQUEMENT pour la zone souveraine et ne recurse pour personne : il manquait un
resolveur recursif. `client_unbound` est l'outil ecrit pour ca — il rejoint
`client_journal` et `client_metrique` parmi les integrations universelles.

`infra-dns-01` est exempte (PowerDNS occupe son port 53), et
`serveur_powerdns_listen_addresses` passe de 0.0.0.0 a l'adresse de l'hote pour
laisser 127.0.0.1:53 libre. Mais l'appartenance au groupe est AUSSI ce qui ouvre
le port 53 a la frontiere : en exemptant la machine, je lui retirais le droit de
resoudre. `serveur_powerdns` declare donc son propre flux sortant — il ne
recurse pour personne, mais doit resoudre pour lui-meme.

Nouvel intrant `dns_amorcage`, derive jusqu'a `make creer-vm`. Cloud-init
l'ecrit bien mais sans effet : `dns-nameservers` exige `resolvconf`, absent du
gabarit, et installer resolvconf demande apt, qui demande la resolution.
`serveur_debian` pose donc le resolveur en pre_tasks, avant le premier apt, avec
une garde qui respecte la bascule ulterieure de client_unbound.

Defaut corrige en chemin : `_intrants_communs()` lisait `instance/` en dur ; le
chemin derive maintenant de l'inventaire recu, et un test le prouve.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 21:41:58 -04:00
af13fc37c9 Rôles web : renommer web_frontal/dorsal -> serveur_web_frontal/dorsal (convention)
Aligne sur la convention serveur_* de tous les rôles de service (vars incluses).
Le modèle presence-web (pré-existant) utilisait déjà ces noms -> il colle enfin.
Aussi : serveur_web_dorsal ne chown plus le code (reste root, lecture seule pour
l'app = plus sûr + git idempotent, fini le 'propriété douteuse' au pull).
Idempotence prouvée (2e passage changed=0). lint production.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 18:49:31 -04:00
eee7dbd108 web_dorsal : rôle webapps dynamiques (2e brique plateforme, 100% natif)
Runtime (venv/paquets) + service systemd + nginx local, derrière l'edge, ZÉRO
conteneur. Chaque app : git clone (depth 1) → venv + pip → unité systemd durcie
(app en localhost, user webapp, NoNewPrivileges/PrivateTmp) → vhost nginx local
qui la fronte. data_dir persistant pour l'état local (SQLite) ; BD réseau via
resoudre_base sinon.

Éprouvé bout-en-bout sur web-frontal-01 par le rôle : monregistraire (FastAPI+
uvicorn+SQLite) cloné de Forgejo, servi via l'edge en HTTPS step-ca, API OK.
Avec web_frontal, la plateforme webapp native est complète. lint production: 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 18:37:47 -04:00
f453f77268 web_frontal : rôle sites statiques (1re brique plateforme webapp, 100% natif)
nginx + sites statiques depuis un dépôt git souverain, derrière l'edge. Pas de
conteneur, pas de runtime, pas de BD — l'éthos libre/natif. Chaque site :
git clone → vhost (headers sécurité + CSP self-only, gzip, try_files). SAN edge
+ plancher auto-dérivés. meta/flux.yml (ingress 80 depuis edge).

Spike prouvé sur web-frontal-01 (site Alliance Boréale servi via edge, HTTPS
step-ca vérifié, CSP en place). NB : le chemin git-clone est codifié mais le
spike a servi via copie locale → à éprouver (pousser le site en Forgejo).
Les apps dynamiques (dorsal systemd) = rôle à venir. ansible-lint production: 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 18:12:19 -04:00
da4976aa98 serveur_collabora : rôle codifié depuis le spike (Docker, WOPI)
Conteneur collabora/code (restart always), publié sur localhost + IP LAN
(gotcha : bind localhost seul → 502 depuis l'edge), aliasgroup = domaine
Nextcloud, ssl.termination à l'edge, attente santé /hosting/capabilities.
meta/flux.yml (ingress 9980 depuis edge) alimente le registre des flux.

Docker (prouvé au spike) ; CODE natif = option future à spiker. Tag à épingler.
ansible-lint profil production : 0 échec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 15:03:07 -04:00
79d0529686 serveur_nextcloud : rôle codifié depuis le spike (13 gotchas encodés)
Maison numérique souveraine (offres maison-obnl + cabinet). Tâches découpées :
paquets → php (512M + TLS PG) → install (occ, PG verify-full) → exposition
(vhost .mjs) → configure (overwrite/redis/anti-SSRF/import CA) → OIDC user_oidc
→ Collabora richdocuments (WOPI split URL) → thème Alliance (ciel étoilé).

Chaque réglage encode un piège prouvé sur collab-01 : imagick Debian 13,
PGSSLMODE dans php-fpm, MIME .mjs, allow_local_remote_servers (SSRF), import
root step-ca, memory_limit 512M, public_wopi_url après activate-config…

Version épinglée (robustesse). ansible-lint profil production : 0 échec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 15:00:39 -04:00
e006dee693 Retirer 3 rôles legacy (serveur_sendmail, client_dns, client_ldap) + nettoyage
Supprimés (supersédés / hors-conception) : serveur_sendmail (→ Postfix),
client_dns (→ plancher + client_unbound), client_ldap (login LDAP OS, hors
design). Rôles + playbooks de groupe retirés.

Nettoyage des références :
- dependances-groupes.yml : entrées client_dns/client_ldap retirées + entrées
  mortes des scaffoldings (nextcloud/collabora/client_supervision) ; deps
  périmées corrigées (client_smtp → serveur_postfix ; serveur_keycloak →
  serveur_postgresql, la raison parlait à tort de Nextcloud).
- 6 modèles d'exemple : app mail serveur_sendmail → serveur_postfix.
- README, AGENTS : listes/glossaire nettoyés.
- catalogue-services : listes, tables, roadmap ; note « rôles retirés ».
- nomenclature-vm : infra-mail-01 → serveur_dovecot (était faux).
- courriel-conception, dns-interne (re-ciblé client_unbound), pouvoirs,
  intrants, READMEs (client_smtp/forgejo/openldap/unbound).

ansible-lint : 0 échec (366 fichiers). instancier OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 12:14:04 -04:00
7476a54f22 Sauvegardes applicatives (restic) : serveur_backup + client_backup — Tier 0 prouvé
Choix : sauvegarder la donnée d'état (non régénérable), pas les VM
(reconstructibles par le code). restic (chiffré, dédupliqué, rétention).
serveur_backup = cible SFTP (backup-01). client_backup = intégration par
nœud : restic + jobs déclaratifs + timer systemd + rétention, secrets voûte.

Prouvé de bout en bout sur le Tier 0 : infra-pki-01 → /etc/step-ca sauvegardé
hors-nœud vers backup-01, restauration byte-identique des clés CA.

Reste : jobs Tier 1 (pg_dump/slapcat/vmail/forgejo) + offsite (3-2-1).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 22:49:26 -04:00
3c1cd3e90e Consolider : retirer la cruft (8 dossiers-catégories + 5 échafaudages morts)
Supprimés : roles/{applications,backup,database,identity,monitoring,
proxmox,storage,web}/ (README seuls, taxonomie abandonnée — l'archi est
plate serveur_*/client_*) et les playbooks-échafaudages debug sans rôle
(nextcloud, collabora, client_supervision, web_frontal, web_dorsal).

Aucun host n'utilise ces groupes ; l'intention des capacités futures
reste documentée dans docs/catalogue-services.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 20:35:47 -04:00
b60c5dc963 serveur_oauth2_proxy : passerelle SSO OIDC générique + Icinga Web 2 au SSO
oauth2-proxy (v7.15.3) place Keycloak devant toute app sans OIDC natif
(auth external, utilisateur via en-tête). Rôle paramétrable, réutilisable.
Éprouvé devant icingaweb2 (backend=external, X-Forwarded-Preferred-Username).

Prouvé : testmail → oauth2-proxy → Keycloak → icingaweb2 /dashboard,
connecté. Ferme le gap LDAP-direct d'icingaweb2.

Réglages appris : insecure_oidc_allow_unverified_email (IdP interne) ;
reverse-proxy passe X-Forwarded-* pas X-Auth-Request-* ; handler nginx en
restart (pas reload) — un changement d'adresse d'écoute n'est pas pris par
un reload gracieux.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 19:05:04 -04:00
b3b972fb5e serveur_icingaweb2 : Icinga Web 2 (UI + module IcingaDB) — éprouvé
App PHP (php8.4-fpm) + nginx local, exposée par l'edge (auto-dérivé).
Config par fichiers .ini (config/resources/authentication/roles + module
icingadb), pas d'assistant. Base IcingaDB via resoudre_base. Auth LDAP
direct (client_pki sur sup-01) — pas d'OIDC natif (SSO-proxy = raffinement).

Prouvé : testmail (LDAP) se connecte (/dashboard), module IcingaDB affiche
la supervision (hôte icinga). Déploiement failed=0 (frictions dans le
simulateur curl, pas le rôle). Reste : module BPM.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:57:04 -04:00
fa945de5a7 client_unbound : résolveur local (DNS dynamique) — éprouvé sur un nœud
Unbound par nœud (127.0.0.1) : stub-zone vers PowerDNS (interne) + récursion
Internet (ou forward). Alternative dynamique au plancher /etc/hosts. Bascule
resolv.conf protégée (apply+confirm) ET validée avant (Unbound doit résoudre
interne + Internet, sinon pas de bascule → nœud jamais coupé). Sûr par défaut
(apply=false).

Prouvé sur data-sql-01 : dig @127.0.0.1 keycloak/id-sso-01 → PowerDNS,
deb.debian.org → récursion, apt OK. Rollout flotte = opt-in par nœud.

Note : OPNsense embarque Unbound → l'Unbound réseau pourra vivre sur
l'appliance de bordure (nœud public, Étape B) ; ce rôle reste complémentaire.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 14:35:00 -04:00
8df1db3b47 serveur_rspamd (rspamd 3.x) : antispam + DKIM en milter Postfix — prouvé
Rôle antispam sur edge-mta : Redis local, worker proxy en mode milter
auto-scan (:11332), signature DKIM sortante (clé générée idempotente,
enregistrement DNS affiché pour l'Étape B). Config par local.d/.
Postfix branché via smtpd_milters (option serveur_postfix_rspamd_milter,
milter_default_action=accept = tolérant si rspamd down).

Prouvé : courriel traversant le milter → scanné (rspamc stat: 1) +
signé DKIM (DKIM-Signature d=...), livré, lu en IMAP.
Étape A (courriel interne) complète : dovecot + postfix + rspamd.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 18:04:44 -04:00
9480e585a5 serveur_postfix (Postfix 3.x) : MTA edge-mta — cartes LDAP + LMTP + TLS step_ca
Réception :25, validation des boîtes par carte LDAP (attribut mail),
remise LMTP réseau vers le mail-store Dovecot (virtual_transport lmtp),
TLS via step_ca (pont de cert), aucune boîte locale. main.cf +
ldap-mailboxes.cf, validé par postfix check. Bind LDAP: vault_openldap_admin.

Validé statiquement (ansible-lint, syntax, rendu main.cf) ; déploiement à suivre.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 15:34:24 -04:00
7549c61e75 serveur_dovecot (Dovecot 2.4) : IMAP + auth LDAP + TLS step_ca — prouvé
Rôle mail : IMAP :993/:143 + LMTP, auth/annuaire LDAP (serveur_openldap),
stockage Maildir (user vmail), TLS via step_ca (pont de cert + resync au
renouvellement), auth système par défaut neutralisée. Config drop-in en
syntaxe Dovecot 2.4 (mail_driver, ssl_server_cert_file, passdb ldap),
validée par doveconf au déploiement. Sockets Postfix conditionnels à la
présence de l'utilisateur postfix (co-localisation).

Déployé et prouvé sur infra-mail-01 : doveadm auth test — bon mot de passe
accepté, mauvais refusé, cert IMAPS émis par step_ca. Format 2.4 validé
empiriquement avant l'écriture (leçon « éprouver l'outil »).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 15:09:37 -04:00
e01adac67b Courriel : pivot de Stalwart vers Postfix/Dovecot/rspamd
Stalwart trop jeune/volatil pour un pilier mail critique (config cassée
0.15→0.16, `config apply` annoncé non livré, API REST supprimée pour
JMAP, gros backlog). Pivot vers la stack mature Postfix/Dovecot/rspamd,
100 % configurable par fichiers (alignée au modèle déclaratif Set-OPS).

- Rôle serveur_stalwart retiré (Phase 1 prototypée ; git en garde la trace).
- docs/courriel-conception.md mis à jour ; vault_stalwart_admin retiré.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 12:52:49 -04:00
e3efbb5b1a serveur_stalwart : Phase 1 (install + démarrage), code prod
Stalwart Mail Server v0.16.11, binaire unique natif. Mécaniques réelles
validées empiriquement sur le binaire :
- config.json = objet typé {"@type":"RocksDb","path":…} (DataStore seul) ;
- démarrage IaC en mode récupération (STALWART_RECOVERY_MODE +
  STALWART_RECOVERY_ADMIN), admin depuis la voûte (vault_stalwart_admin).

Rôle : install version-épinglée, user système, unité systemd durcie
(CAP_NET_BIND_SERVICE, ProtectSystem), EnvironmentFile pour le secret.
Phase 2 (écouteurs/TLS step_ca/annuaire LDAP/DKIM via API d'admin) à venir.
Validé statiquement (ansible-lint, syntax, rendu config.json).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 10:24:50 -04:00
a9a1493440 Plancher de résolution /etc/hosts (indépendant du DNS)
Nouveau rôle de socle hosts_statiques (dans serveur_debian) : génère
/etc/hosts sur chaque VM depuis l'inventaire. L'écosystème se résout par
nom même DNS éteint, et le bootstrap ne dépend plus du DNS. client_dns
rendu tolérant (inerte sans DNS interne) ; dépendance client_dns→powerdns
passée molle. PowerDNS devient une commodité (zone/externe).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 18:05:42 -04:00
Alliance Boreale
3dd3f43ad8 Set-OPS — moteur d'ecosystemes numeriques souverains (Alliance Boreale) 2026-06-24 20:17:46 -04:00