Commit graph

34 commits

Author SHA1 Message Date
5340220192 vigie : vues métier par clientèle interne, dérivées du plan
- metier: sur chaque sonde (47) ; catalogue des vues et services dans
  serveur_icingaweb2 ; vues Mes outils / Services rendus / Exploitation
- contrôles calculés comme serveur_icinga (sauvegardes, socle, matériel,
  frontière) ; vue vide non posée ; ancien exemple supervision retiré
- CHANGELOG 71

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 02:26:11 -04:00
055aed665e grafana : la synthèse comme page d'accueil
- setops.conf : GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH vers setops-synthese.json
- CHANGELOG 70 complété

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 01:43:33 -04:00
05ec7a8743 grafana : un tableau de synthèse, au site et chez les locataires
- tableau-synthese : faut-il agir, marge, activité, où regarder ensuite ;
  hyperviseurs au site seulement ; chaque panneau dit quoi faire
- CHANGELOG 70

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 01:12:00 -04:00
b3debd6ca9 grafana : le tableau Matériel dit quoi faire
- materiel.py : textes accentués et champ action par mesure (seuils inchangés)
- tableau-materiel : mode d'emploi en tête ; descriptions en trois temps
  (ce que ça mesure, seuils, quoi faire)
- CHANGELOG 69

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 00:49:28 -04:00
b938897e17 sonde tableaux : la sante de chaque source de donnees de Grafana
Elle etait verte pendant que les tableaux etaient vides. Eprouvee avec une
source recreant le defaut du jour, puis retiree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 17:51:53 -04:00
8f699eb3ce grafana : l URL de Loki suit son TLS ; les tableaux des locataires se remplissent
Loki servait en HTTPS, Grafana lui parlait en clair : la variable host restait
vide et aucun panneau ne s affichait. URL derivee de serveur_loki_tls_actif.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 17:40:41 -04:00
49ceb81a4d materiel : un catalogue de capteurs, un tableau Grafana, un verdict Icinga
Les hyperviseurs exposaient temperatures, ventilateurs, SMART et usure NVMe sans que rien
les regarde. scripts/materiel.py porte capteurs et seuils ; Grafana en tire le tableau
Materiel, Icinga un service materiel par hyperviseur. Premier verdict : le disque sda de
gandalf (OSD Ceph) a 56 secteurs en attente, stables.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 10:13:43 -04:00
311f33d6f6 grafana : les panneaux declares deviennent des tableaux
La moitie qui manquait. Les roles declaraient leurs panneaux, Prometheus en
derivait ses cibles, les expressions repondaient, et rien ne les assemblait.

serveur_grafana lit les memes meta/metriques.yml que serveur_prometheus et en
assemble un tableau par role — la raison du panneau devient sa description dans
Grafana. Moisson des tableaux orphelins, prefixe setops-role- pour ne jamais
toucher un tableau ecrit a la main, JSON valide avant d etre pose (Grafana ne
tombe pas sur un tableau illisible : il le saute en silence).

client_metrique declare quatre panneaux sans exportateur — le cas symetrique.
Celui qui compte : la memoire disponible, depuis que le ballon est actif.

Eprouve sur le site : les deux tableaux charges dans le stockage unifie, un
temoin orphelin retire, les quatre panneaux de flotte a 10 series chacun.

Un panneau etait faux — /var/lib/lxcfs rapporte toujours zero octet libre et un
min() en meurt. Corrige en liste blanche : un montage inconnu manque au graphe,
ce qui se voit, au lieu de l ecraser.

P77 garde la table des unites : une unite inventee retombe sur short, lisible et
fausse. 76 OK.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-14 16:32:30 -04:00
5812e0c6ca depot de binaires : le site tient ce que les runners allaient chercher
Le cache du site couvrait apt ; quatre artefacts arrivaient autrement, parce qu ils
ne vivent dans aucun depot apt. Le controleur les tire puis les pousse par SSH.

Mesure du 2026-09-12 : le cache du runner du site est ABSENT. Un second locataire
monte depuis lui sortait chercher 570 Mo sur codeberg.org, github.com et
download.nextcloud.com, alors que le meme ecosysteme ne demandait plus un seul
paquet a Debian. Le poste du mainteneur les a depuis toujours : personne ne l avait vu.

Pas de relais transparent, et la mesure tranche : github.com redirige vers une URL
signee valable une heure, differente a chaque requete. Un cache qui la prend pour
cle ne fait jamais mouche. Le relais marcherait pour deux amonts sur quatre.

Donc un vrai depot, dans le service qui existe deja. LocalDirs d apt-cacher-ng publie
un repertoire du disque sous un prefixe, eprouve AVANT d ecrire le role. Aucun service,
aucun port, aucun certificat, aucun flux nouveaux : l ingress 3142 pair flotte couvre
exactement ce chemin.

Les versions ne sont pas recopiees : le role lit les defauts des quatre consommateurs.
Les quatre roles recoivent une tache AJOUTEE, placee avant leur stat de cache — si le
depot sert, le stat le voit et la tache amont se saute d elle-meme. Aucune tache
existante n a change.

P70 exige que tout dest ecrit sous un cache_local figure au depot. Une liste qui suit
une autre prend du retard ; celle-ci est nee avec sa garde.

Deux marches payees en chemin :
- failed_when: false REECRIT le verdict, donc la premiere garde de signature ne
  gardait rien. Elles mesurent le fichier desormais.
- file: state=directory cree les parents en 0750 : apt-cacher-ng, qui ne tourne pas
  en root, rendait 403 sur chaque fichier. Un chemin se traverse en entier.

Verifie sur l infrastructure : 6/6 artefacts servis (200/206) depuis le runner du site
ET depuis une machine du locataire a travers la frontiere ; les 6 empreintes SHA-256
sont identiques a celles qui ont construit Chezlepro ; second passage changed=0.

make prouver : 69 OK, 0 echec, 1 saute. ansible-lint : 0 failure, profil production.

Inclut aussi force: true sur cinq telechargements de cles : une reprise conditionnelle
ne reprend rien (304 Not Modified, size 0, attempts 5).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-12 23:45:00 -04:00
1b89e83b0c reconstruction a froid : les noms derives naissent justes, et une cle vide tombe
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
2026-09-11 07:57:24 -04:00
0778979b89 une source vide n est pas « tout le monde »
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
2026-09-10 19:14:23 -04:00
a60b69f072 un fichier vide existe, et une sonde pour les correctifs
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
2026-09-10 17:26:35 -04:00
1410fe41ec les cles de signature passent aussi par le cache
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
2026-09-10 15:41:56 -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
f2c580235d observabilite : le site cesse de ne rien voir de lui-meme
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
2026-09-10 04:43:01 -04:00
1832530f29 sondes : les six premieres, et le patron qui les rend eprouvables
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
2026-09-10 02:48:55 -04:00
42becd0c02 paquets tiers : passer par le cache du controleur, plus par Internet
Some checks are pending
verifier / verifier (push) Waiting to run
Trois depots tiers etaient en HTTPS, et client_artefacts pose
Acquire::https::Proxy DIRECT — sans quoi le cache du site refuse les tunnels et
aucun depot tiers n est joignable. La ligne est juste ; sa consequence ne l avait
pas ete vue : ces trois depots CONTOURNENT le cache, et chaque VM neuve allait
les chercher sur Internet a sa naissance.

step-cli et alloy sont poses par des integrations UNIVERSELLES. Sans lien, une
machine neuve n obtenait ni son client d autorite ni ses metriques — elle n
entrait dans aucun flux chiffre. Dernier obstacle a une reconstruction hors
ligne, et il tenait dans un mot.

make cacher-paquets tire les 21 deb aux versions epinglees, empreinte SHA256
verifiee depuis l index du depot. Le role partage paquets_tiers les depose et les
installe EN UN SEUL appel a apt — il sait resoudre un ensemble de fichiers locaux
qui se dependent, la ou paquet par paquet echouerait sur l ordre (Icinga en
apporte dix-sept). Six roles branches ; chacun retombe sur le depot distant pour
ce que le cache n a PAS fourni, et rien d autre.

Eprouve pour de vrai : packages.smallstep.com renvoye vers 127.0.0.1, step-cli
desinstalle, cache local efface. Le role rejoue installe 0.30.6-1 depuis le cache
et la machine obtient ses certificats. Zero echec.

Deux defauts de mon propre outil, trouves en le construisant : Smallstep sert son
index NON COMPRESSE (404 sur .gz) donc step-cli n etait jamais mis en cache ; et
un depot injoignable faisait continue AVANT d incrementer le total, si bien que
le script rapportait 20 sur 20 alors qu il en manquait un. Une garde qui ne peut
pas echouer ne garde rien — troisieme fois cette semaine. Corrige puis eprouve en
le faisant echouer.

Reste hors ligne : NTP externe, et l expedition des alertes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-05 08:22:14 -04:00
19871894ed keycloak : un jeton frais la ou on s'en sert ; grafana : un echec lisible
Technolibre remonte depuis zero une seconde fois — 14 hotes, 2588 taches ok,
0 failed. Deux defauts trouves en chemin.

LE JETON KEYCLOAK VIVAIT 60 SECONDES. Il etait pris dans politique-mdp.yml —
le 2e des neuf fichiers du role — et reutilise jusqu'au 8e. Entre les deux,
six fichiers de travail dont groupes-ldap.yml et ses reprises espacees de
15 s. Sur une construction NEUVE le temps depasse la minute : 401. Sur un
REJEU tout est converge, ca va vite, ca passe.

D'ou les deux echecs du matin, chaque fois suivis d'un succes au rejeu, qui
donnaient l'illusion d'une course au demarrage de Keycloak. J'avais ecrit
alors ne pas avoir de mesure qui le prouve — c'etait juste, et la cause etait
l'AGE du jeton. jeton-admin.yml en prend un frais la ou on s'en sert.

GRAFANA : UN ECHEC TRANSITOIRE RENDU ILLISIBLE. Premier demarrage, apres 67 s
de migrations : « failed to create admin user: no such column: uid », alors
que la migration qui ajoute cette colonne etait journalisee comme reussie.
Base neuve : tout remigre, service actif, colonne presente. L'incident ne
s'est pas reproduit et Chezlepro ne l'a jamais eu — je n'ai donc PAS corrige
la cause, faute de l'avoir reproduite. J'ai corrige ce qui la rendait
indechiffrable :

- Restart=on-failure venait du paquet SANS RestartSec, donc 100 ms : six
  relances en une seconde, chacune rejouant les migrations sur la meme base
  SQLite. Un echec unique se presentait comme un desastre. RestartSec=10 ;
- la rotation du compte de secours echouait cinq fois sous no_log en
  annoncant « the output has been hidden », alors que la vraie cause etait
  ailleurs et lisible : le serveur ne demarrait pas. Une attente explicite sur
  le port precede desormais la CLI, avec un message qui renvoie a la PREMIERE
  erreur du journal.

Troisieme fois dans la journee que no_log masque la cause au moment ou elle
sert : une garde qui protege un secret ne doit pas emporter le diagnostic.

Verifie : 7 devis sur Technolibre — MTU, identite, certificats, PostgreSQL,
courriel, frontiere CONFORME ; prouver.py 35 OK ; ansible-lint production.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 20:19:50 -04:00
a0dc3da4a6 get_url : plus aucun sans garde — la dependance externe tombe a zero
Arbitrage de l'exploitant : garder aussi les cles de signature. Zero get_url
sans garde dans le depot, contre neuf ce matin.

Avant : 6 serveurs tiers x 14 hotes recontactes a chaque deploiement. Apres :
zero. Un deploiement de flotte ne depend plus d'aucun serveur etranger pour ce
que la machine possede deja.

Consequence assumee et ecrite dans chaque role : une rotation de cle amont
n'est plus recuperee seule. Elle ne passe pas inapercue pour autant — apt
refuse le depot, bruyamment — et le remede tient en une ligne. C'est un defaut
SONORE, pas silencieux ; toute la journee a consiste a transformer les seconds
en premiers.

Verifie sur backup-01 : changed=0, trois taches sautees. Reste a eprouver sur
un hote neuf, ou la garde doit laisser passer le telechargement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 14:05:25 -04:00
043ca6480f grafana : rendre patiente la pose du mot de passe de secours
Cinquieme arret de la reconstruction from-zero, meme classe que le quatrieme :
une COURSE de premier demarrage. La commande suit de peu le premier demarrage
de grafana-server, qui cree encore sa base ; la CLI echoue sur une base absente
ou verrouillee. Rejouee seule quelques minutes plus tard, elle passe.

retries/until, comme pour l'ecriture Keycloak qui suit la synchro LDAP : on
attend une condition, pas une duree.

Note : la sonde de diagnostic a change le mot de passe admin. Verifie avant de
poursuivre que le marqueur d'empreinte etait ABSENT — la tache se rejoue donc
et repose la valeur de la voute. Aucune trace laissee.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 23:47:34 -04:00
91d3a736e7 rotation : les comptes de secours peuvent enfin changer de mot de passe
Le runbook promettait cette rotation ; le code ne savait pas la faire. Les trois
roles ne posaient le mot de passe qu'a la CREATION — regenerer la voute aurait
produit le mensonge silencieux corrige toute la journee.

Chaque role sait desormais CHANGER un mot de passe existant, idempotent par
empreinte du secret applique. Pour Nextcloud le secret passe par l'environnement,
pas par la ligne de commande ou il serait visible dans la table des processus.

`grafana-cli` ecrivait dans une base FANTOME en annoncant « changed successfully »
a chaque fois : il prend `paths.data` a `<homepath>/data`, le paquet Debian range
la base dans /var/lib/grafana. Demasque par le champ `updated` du compte, reste a
l'heure du deploiement initial malgre quatre reinitialisations « reussies ». Un
message de succes n'est pas une preuve ; l'etat l'est.

Verifie par authentification reelle : Grafana 200, Nextcloud 200. Forgejo ferme
l'API par doctrine (D-41) — seule preuve disponible : le retour de la commande.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 21:10:47 -04:00
6699935dc7 resoudre_idp : le nom invente etait dans QUATRE roles
`forge-01` a echoue sur une URL de decouverte pointant
`https://keycloak.<domaine>` — le nom que rien ne publie. J'avais corrige
exactement ca dans `serveur_oauth2_proxy` quelques heures plus tot, en croyant
regler un cas isole.

Il etait dans quatre roles : forgejo, grafana, nextcloud, oauth2-proxy. Chacun
fabriquait le meme nom par la meme convention. Une cinquieme correction a la main
aurait diverge comme les quatre autres.

`roles/resoudre_idp` lit l'exposition declaree au plan et rend hote, base et
discovery. Les roles n'en gardent qu'un REPLI nomme, jamais la valeur de travail.

Verifie en base sur forge-01 : discovery = auth.chezlepro.internal,
GroupClaimName = groups, AdminGroup = sysadmin.

Meme lecon que `resoudre_annuaire` hier : corriger la valeur la ou elle echoue ne
corrige que la. Ce sont les copies silencieuses qui coutent la journee suivante.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 15:33:32 -04:00
6f2acafdb6 acces : les cinq meta/acces.yml, et le mecanisme qui manque a chacun
Chaque role web declare le GROUPE qu'il reconnait et ce qu'il lui accorde. Un
troisieme champ s'est impose en ecrivant : `porte_par` — le mecanisme qui
transporte reellement l'habilitation. Sans lui, les declarations auraient decrit
une chaine inexistante.

Etat mesure : grafana `role-realm` (reel) ; forgejo, nextcloud et keycloak
`aucun` ; icingaweb2 `liste-uid` — il NOMME DES PERSONNES, ce que D-66 interdit.

Le maillon manquant est chez Keycloak : `role_assignments` assigne un role a un
UTILISATEUR, et son propre commentaire l'admettait (« en prod, preferer
l'assignation via groupe d'annuaire »). Sans group-ldap-mapper, les groupes LDAP
n'atteignent jamais les services. Sa meta a donc une autre forme,
`acces_projection` : Keycloak projette au lieu de consommer (D-65).

Defaut corrige : `serveur_icingaweb2_admins` valait "testmail", un compte de
test code en dur dans le moteur qu'aucune instance ne surchargeait — le seul
administrateur declare de la supervision etait un utilisateur inexistant. Il
suit desormais l'uid d'amorcage. Verifie sur mon-01 : users = "sysadmin".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 13:59:33 -04:00
22ef279464 authentification : chaque rôle déclare sa position, gardé par P29
Une règle qu'aucune garde ne vérifie finit par ne plus être vraie — c'est ce qui
était arrivé aux 28 lignes d'intégration recopiées. Chaque rôle serveur_* porte
un meta/authentification.yml, confronté à son code par P29.

web-sso 5, socle-identite 2 (keycloak/openldap : ils SONT la chaîne d'identité),
ldap-direct 2, interne-sans-auth 2, sans-auth-humaine 12.

La preuve refuse l'oubli ET le mensonge. Éprouvée par sabotage sur sept cas :
déclaration supprimée, portée inventée, secours retiré, posture de formulaire
retirée, raison retirée, ldap-direct mensonger, réglage retiré des defaults.

Les deux derniers passaient dans la première version :

- le mensonge passait à cause d'un commentaire. Je cherchais le mot « ldap » dans
  le rôle, et serveur_grafana/defaults/main.yml contient « désactiver quelqu'un
  dans LDAP » : de la prose validait une déclaration fausse. La preuve exige
  maintenant un indice nommé — variable <rôle>_oidc / <rôle>_ldap, ou URI ldap://
- le réglage retiré passait parce que le gabarit citait encore la variable alors
  que plus rien ne lui donnait de valeur. La preuve lit defaults/main.yml en YAML
  et exige que la clé y soit définie, pas mentionnée.

Elle a aussi forcé une valeur : oauth2-proxy était déclaré « formulaire local
fermé » alors qu'il n'a aucun compte local. D'où formulaire_local: aucun, qui
distingue « il n'y en a jamais eu » de « il y en a un, il est fermé ».

Correction d'une note de la veille : Prometheus et Loki ne sont PAS exposés
publiquement (aucun expose au plan). Seuls six groupes le sont. Le risque est
intra-tenant, pas frontalier. Les deux lacunes sont comptées à chaque exécution,
pas masquées.

AFF-111, D-42. 29 preuves OK, ansible-lint (production) sur 375 fichiers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 17:05:43 -04:00
6a62f0a4c7 authentification : SSO Keycloak devant, secours par sudo, formulaire local fermé
Directive : toute authentification web passe par Keycloak, LDAP est la source
unique des comptes, chaque service garde un accès de secours par sudo sur
l'hôte. Les trois sont indissociables — la chaîne service → Keycloak → LDAP est
en série, donc sans secours une panne exclut tout le monde, y compris pour
réparer. Portée : le web seulement ; IMAP/SMTP se lient à LDAP directement et
SSH est en clé seule.

Posture <rôle>_connexion_locale, false par défaut. Le compte local existe — il
ne peut pas dépendre de Keycloak — mais son formulaire n'est plus proposé au
repos : ouvert en permanence, il contourne la politique de mot de passe, le MFA
et surtout la révocation centrale.

Vérifié auprès de l'amont, puis par rendu réel des gabarits dans les deux
postures :
- Grafana  GF_AUTH_DISABLE_LOGIN_FORM  → ferme ;
- Forgejo  ENABLE_INTERNAL_SIGNIN + ENABLE_BASIC_AUTHENTICATION → ferme, API
  Basic comprise. N'existe que depuis la v10 (ticket amont 7476) ; le rôle
  épingle 10.0.0 et un assert refuse la fermeture en deçà, car le réglage serait
  ignoré sans erreur ;
- Nextcloud hide_login_form → MASQUE seulement : ?direct=1 reste le chemin de
  secours documenté par l'amont. Écrit comme tel, sans prétendre à l'équivalence.

Défaut attrapé par le rendu : la condition Forgejo sans `| bool` n'émettait rien
dans aucune posture — une valeur en chaîne est vraie au sens Jinja, la connexion
locale serait restée ouverte en silence.

docs/authentification.md, décisions D-38 à D-41. ansible-lint (production) sans
échec, 28 preuves OK.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 16:50:36 -04:00
f05f505b88 Reconstruction propre : orchestrateur ordonné, registre des flux + pare-feu
Rend l'écosystème reconstructible en une commande (create+deploy idempotent) et
ajoute la couche « accès » (nftables least-privilege) au zéro-confiance.

Orchestrateur (phase 2) :
- docs/couches-deploiement.yml : registre des couches (socle → pki → services → apps → agents)
- scripts/orchestrer.py : tri par couche + topo intra-couche (graphe) → playbooks/site.yml ordonné
- Makefile : site / deployer-tout / flotte-creer / reconstruire / myDay (+ gardes CONFIRMER)
- docs/dependances-groupes.yml : graphe complété (keycloak→openldap, dovecot, postfix, icingaweb2, nextcloud)

Audit codé-en-dur (phase 1b) : labels/slug OIDC dérivés de l'intrant `organisation`
(serveur_forgejo/grafana/nextcloud) — le moteur ne porte plus de nom de tenant.

Registre des flux réseau (phase 0) :
- meta/flux.yml pour tous les rôles (29 rôles, 63 flux ; schéma + matrice validés)
- scripts/resoudre_flux.py : matrice d'audit (docs/registre-flux.md) + rulesets nftables résolus par hôte
- roles/nftables_baseline : déploie le ruleset résolu (moindre-privilège) quand activé, sinon repli

Correctifs : détection du coffre Vault (chemin production → inventaire réellement résolu).
Outillage : make wiki-publier (publication du wiki pédagogique dans Forgejo).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 03:08:09 -04:00
867e2f8cdc Découplage instance : realm centralisé + vars génériques
Fin des dernières poches de 'codé en dur' liées à l'instance d'origine :
- realm SSO centralisé sur l'intrant identite_realm (defaut chezlepro,
  retro-compatible) ; les 4 rôles (keycloak/forgejo/grafana/oauth2_proxy)
  en dérivent. Expose dans la GUI (panneau Intrants).
- vars brandees renommees generiques : chezlepro_timezone -> fuseau_horaire,
  chezlepro_organisation -> organisation (chrony, openldap, GUI, docs).

Aucune reference fonctionnelle aux anciens noms. Le moteur ne porte plus le
nom d'un tenant. Technolibre a son propre realm (technolibre).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 00:47:44 -04:00
c5df8fac4a RBAC via SSO : rôle de realm Keycloak → niveau Grafana (authZ)
Machinerie additive/idempotente dans serveur_keycloak (rbac-oidc.yml) :
rôles de realm + mapper 'roles' sur les clients choisis + assignations
rôle→utilisateur. kcadm à chaud (zéro coupure SSO). Grafana :
role_attribute_path (grafana-admin→Admin, grafana-editor→Editor, sinon
Viewer). Prouvé sur id-sso-01 (idempotence) : testmail = grafana-editor.

Complète le dashboard logs (Viewer-friendly) : les deux volets de la
question « testmail peut-il voir les logs ? ».

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 16:58:15 -04:00
4887d2aee8 Grafana : dashboard provisionné « Journaux de la flotte » (Loki, Viewer-friendly)
Provisioning de dashboards (provider + JSON) : un dashboard logs avec
sélecteur d'hôte + filtre regex + panneau logs + débit. Référence Loki par
une VARIABLE de datasource (ds_loki), pas un UID codé en dur.

Leçon : ajouter un uid explicite à une datasource déjà provisionnée casse
le démarrage de Grafana (« data source not found ») → variable de datasource.

Permet aux Viewers (dont testmail) de voir les logs sans accès Explore.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 16:10:59 -04:00
67699e7841 Grafana branché au SSO OIDC (« Se connecter avec Chezlepro ») — prouvé
serveur_grafana : config OIDC via GF_AUTH_GENERIC_OAUTH_* (client grafana,
realm chezlepro, secret vault_grafana_oidc). serveur_loki/prometheus/grafana
déployés sur obs-01. Fix serveur_loki : créer le groupe loki (paquet crée
l'user en nogroup).

Prouvé (flux authorization code headless via l'edge) : testmail (LDAP) se
connecte à Grafana par le SSO ; /api/user renvoie login/email/name fédérés
depuis LDAP. Chaîne LDAP → Keycloak → Grafana.

Gaps notés : enregistrement du client OIDC dans Keycloak fait via kcadm à la
main (à codifier) ; résolution keycloak→edge sur obs-01 = /etc/hosts manuel
(PowerDNS devrait porter les A d'exposition) ; mapping de rôles Grafana.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 13:15:52 -04:00
bbcf087904 Câbler les secrets des rôles à leur variable de voûte (vault_*)
Les rôles à secrets déclaraient serveur_X_password: "" avec la variable
de voûte seulement en commentaire — aucun mapping réel. Remplir la voûte
ne branchait donc rien (secret vide → assertion échoue).

Les 12 secrets des 8 rôles pointent maintenant vers leur source :
  serveur_X_password: "{{ vault_X | default('') }}"
Comportement inchangé si la voûte est vide ; branché dès qu'elle a le
secret. Prouvé : assertion step_ca passe avec vault_step_ca_password.
Chaque instance remplit ses vault_* ; aucun mapping par instance.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:29:18 -04:00
f82630de6c Rendre le dry-run (--check) fiable sur les rôles applicatifs
« Vérifier » échouait faussement sur un hôte frais : les tâches
« démarrer service » et les handlers restart/reload/validate touchent
un paquet que --check n'installe pas vraiment → service/fichier absent
→ faux fatal, qui bloquait le déploiement (le dry-run doit passer pour
débloquer « Déployer »).

Ajout de « when: not ansible_check_mode » sur ces tâches + handlers des
13 rôles serveur_* (29 gardes). Sautées en dry-run, inchangées en réel.
Validé : powerdns dry-run failed=0 ; ansible-lint 0 échec ; 19 playbooks
syntax-OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:01:53 -04:00
5d30a3a608 Dimensionner les ressources VM depuis les logiciels hébergés
Les cœurs/RAM/disque d'une VM sont estimés depuis l'empreinte des rôles
hébergés (roles/<rôle>/meta/empreinte.yml) sommée au socle SE, au lieu
d'hériter des specs du golden template. Le générateur écrit
proxmox_coeurs/memoire/disque_taille ; le clonage les passe à Proxmox
(omit si absent → aucune régression). Override par hôte dans le plan.

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