Set-OPS-Public/roles/serveur_loki/tasks/main.yml

322 lines
13 KiB
YAML
Raw Normal View History

---
- name: Assurer le repertoire des trousseaux apt
ansible.builtin.file:
path: /etc/apt/keyrings
state: directory
owner: root
group: root
mode: "0755"
# Recuperee UNE FOIS. Sans garde, chaque deploiement recontactait le serveur du
# fournisseur : cinq cles x quatorze hotes = soixante-dix allers-retours externes pour
# des cles deja installees, et autant d'occasions qu'un tiers lent fasse tomber le
# deploiement. Arbitrage rendu le 2026-08-09 : une plateforme souveraine ne depend pas
# de six serveurs etrangers pour redeployer ce qu'elle possede deja.
#
# CONSEQUENCE ASSUMEE : une rotation de cle amont n'est plus recuperee toute seule. Elle
# ne passe pas inapercue pour autant — `apt` refuse alors le depot, bruyamment. Pour
# forcer le rafraichissement : supprimer le fichier et rejouer le role.
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
# UN FICHIER VIDE EXISTE (mesure du 2026-09-10).
#
# Cette garde demandait « ce fichier est-il la ? ». Un telechargement interrompu — un 503,
# un delai depasse, une coupure — laisse un fichier de ZERO octet, qui existe. La tache
# est donc sautee a tous les passages suivants, et la machine garde une ressource morte
# pour toujours, en silence.
#
# CE QUE CA A COUTE : `infra-mail-01` a garde une cle smallstep de 0 octet apres une
# epreuve hors ligne. Treize machines portaient 1022 octets, elle portait le vide :
#
# E: Le depot http://packages.smallstep.com/... n'est pas signe.
#
# Le meme jour, l'index `dists/trixie` du cache du site etait tombe de 140 416 a 4 332
# octets — meme famille, autre endroit. Un telechargement partiel ne se signale pas : il
# se fait passer pour un succes.
#
# On demande donc « est-il ENTIER ? » — a defaut de pouvoir demander « est-il JUSTE ? »,
# ce qui exigerait une empreinte de reference que l'amont ne publie pas toujours.
- name: Cette ressource est-elle deja recuperee ? (Telecharger la cle de signature Gr)
ansible.builtin.stat:
path: "{{ serveur_loki_depot_cle_fichier }}"
register: telecharger_la_cle_de_signature_grafana_present
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
# ... ET IL FAUT LE RETIRER, PAS SEULEMENT LE REDEMANDER (mesure du 2026-09-10).
#
# Laisser la garde autoriser la tache ne suffit PAS. `get_url` sur une destination qui
# existe emet une requete CONDITIONNELLE : l'amont repond « non modifie », le module rend
# `ok`, et le fichier corrompu reste en place. Mesure : la tache s'executait bien
# (`ok: [infra-mail-01]`), et la cle faisait toujours 0 octet au passage suivant. Un
# `force: yes` manuel l'a reparee en une seconde.
#
# On efface donc la ruine avant de reconstruire. `state: absent` ne mord que sur un
# fichier vide : une cle valide n'est jamais retiree, et la doctrine « on ne retelecharge
# pas ce qu'on possede deja » reste intacte.
- name: Retirer une ressource VIDE avant de la redemander
ansible.builtin.file:
path: "{{ serveur_loki_depot_cle_fichier }}"
state: absent
when:
- telecharger_la_cle_de_signature_grafana_present.stat.exists
- (telecharger_la_cle_de_signature_grafana_present.stat.size | default(0)) == 0
- name: Telecharger la cle de signature Grafana
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
when: not (telecharger_la_cle_de_signature_grafana_present.stat.exists and telecharger_la_cle_de_signature_grafana_present.stat.size | default(0) > 0)
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
# `force` PARCE QU'UNE REPRISE CONDITIONNELLE NE REPREND RIEN (2026-09-12).
#
# Sans lui, `get_url` envoie un `If-Modified-Since` des que le fichier existe. Le cache
# repond `304 Not Modified`, la tache reussit sans rien ecrire, et la boucle `until`
# — qui exige une taille non nulle — retente cinq fois contre un serveur qui repondra
# toujours 304 :
#
# HTTP Error 304: Not Modified size: 0 attempts: 5
#
# C'est la boucle de reprise qui se bat contre elle-meme. Le `when:` ci-dessus garantit
# deja qu'on ne retelecharge pas une cle valide ; `force` ne concerne donc que le cas
# ou l'on a DECIDE d'aller chercher.
ansible.builtin.get_url:
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
force: true
url: "{{ serveur_loki_depot_cle_url }}"
dest: "{{ serveur_loki_depot_cle_fichier }}"
owner: root
group: root
mode: "0644"
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
# LA CLE PASSE PAR LE CACHE, ELLE AUSSI (mesure du 2026-09-10).
#
# `get_url` ignore la configuration d'apt : le mandataire pose dans
# `/etc/apt/apt.conf.d/` ne vaut que pour apt. Les cles de signature sortaient donc
# TOUJOURS en direct, meme apres que tous les depots soient passes par le cache — un
# trou reste ouvert derriere une porte qu'on croyait fermee.
#
# Et ce n'est pas theorique : depuis `collab-01`, la route directe vers
# `www.collaboraoffice.com` EXPIRE, quand le cache l'atteint sans peine.
#
# en direct grafana 200 collabora TIMEOUT
# via le cache collabora 200
#
# Le meme geste corrige donc les deux : plus rien ne sort, et la machine qui n'avait
# pas de route en trouve une.
#
# DEGRADE, JAMAIS DEVINE : sans cache d'amorcage declare, la valeur est VIDE et
# `get_url` sort en direct comme avant. On n'invente pas un mandataire.
environment:
http_proxy: >-
{{ ('http://' ~ artefacts_amorcage) if (artefacts_amorcage | default('') | string | length > 0) else '' }}
https_proxy: ""
register: serveur_loki_cle_depot
retries: 5
delay: 6
until: serveur_loki_cle_depot is succeeded and (serveur_loki_cle_depot.size | default(0)) > 0
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
# `apt_repository` AJOUTE, IL NE REMPLACE PAS (mesure du 2026-09-10).
#
# Passer une source de `https://` a `http://` y ecrit une SECONDE ligne au lieu de
# corriger la premiere. apt interroge alors les deux — et l'ancienne continue de sortir
# en direct sur Internet, ce que le passage au cache visait justement a supprimer. Le
# symptome le disait, sur les quatorze machines :
#
# W: La cible Packages est specifiee plusieurs fois dans grafana.list:1 et :2
#
# On retire donc explicitement la forme precedente. `state: absent` ne mord que si la
# ligne existe : sur une machine neuve, cette tache ne fait rien.
- name: Mesurer la cle de signature Grafana qui vient d'etre posee
ansible.builtin.stat:
path: "{{ serveur_loki_depot_cle_fichier }}"
register: cle_grafana_posee
- name: Exiger une cle NON VIDE avant de s'en servir
# UNE REUSSITE N'EST PAS UN CONTENU (mesure du 2026-09-11). Sur une reconstruction a
# froid, `get_url` a rendu 0 octet sans erreur sur UNE machine des quatorze : le cache
# a servi un 200 au corps vide. La garde « retirer une ressource VIDE » ne mord qu'au
# passage SUIVANT, quand le fichier existe deja — au premier, elle n'a rien a retirer.
#
# Le defaut ne se lisait pas ici. Il se lisait deux cents lignes plus loin, dans un
# `apt` qui accusait la SIGNATURE : « Missing key ..., which is needed to verify
# signature ». Un message qui envoie chercher une cle revoquee chez le fournisseur,
# alors que le fichier local fait zero octet.
ansible.builtin.assert:
that:
- (cle_grafana_posee.stat.size | default(0)) > 0
fail_msg: >-
La cle de signature Grafana ({{ serveur_loki_depot_cle_fichier }}) fait 0 octet.
Le depot a repondu sans corps — cache vide, ou amont injoignable. apt echouera
plus loin en accusant la signature : c'est ICI qu'il faut regarder.
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
- name: Retirer la forme HTTPS du depot (elle contournait le cache)
ansible.builtin.apt_repository:
repo: "{{ serveur_loki_depot_source | replace('http://', 'https://') }}"
filename: grafana
state: absent
when: serveur_loki_depot_schema == 'http'
- name: Ajouter le depot apt Grafana
ansible.builtin.apt_repository:
repo: "{{ serveur_loki_depot_source }}"
filename: grafana
state: present
paquets tiers : passer par le cache du controleur, plus par Internet 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
# LE CACHE DU CONTROLEUR D'ABORD, LE DEPOT DISTANT POUR LE RESTE (2026-09-03).
#
# Les depots tiers sont en HTTPS, et `client_artefacts` pose
# `Acquire::https::Proxy "DIRECT"` — ils CONTOURNENT donc le cache du site et sortent sur
# Internet a chaque construction de VM. `make cacher-paquets` les tire une fois, versions
# epinglees et empreintes verifiees ; ce role les depose depuis ce cache.
- name: Poser les paquets tiers depuis le cache du controleur
ansible.builtin.include_role:
name: paquets_tiers
vars:
paquets_tiers_noms: "{{ serveur_loki_paquets }}"
- name: Installer Loki
ansible.builtin.apt:
paquets tiers : passer par le cache du controleur, plus par Internet 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
# CE QUE LE CACHE N'A PAS FOURNI, ET RIEN D'AUTRE. Les dependances Debian passent
# par le cache du site en HTTP ; seuls les paquets tiers non caches exigent Internet.
# Reinstaller ce que le cache vient de poser ferait un `update_cache` inutile — et
# hors ligne, il echouerait APRES un travail deja fait.
name: "{{ serveur_loki_paquets | difference((paquets_tiers_disponibles | default({})).keys() | list) }}"
state: present
update_cache: true
paquets tiers : passer par le cache du controleur, plus par Internet 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
when: (serveur_loki_paquets
| difference((paquets_tiers_disponibles | default({})).keys() | list)) | length > 0
- name: Assurer le groupe loki (le paquet cree l'utilisateur en nogroup)
ansible.builtin.group:
name: loki
system: true
- name: Rattacher l'utilisateur loki a son groupe
ansible.builtin.user:
name: loki
group: loki
- name: Assurer le repertoire de donnees Loki
ansible.builtin.file:
path: "{{ serveur_loki_chemin }}"
state: directory
owner: loki
group: loki
mode: "0750"
# --- TLS : synchroniser le cert step_ca AVANT d'activer http_tls_config ---
- name: TLS — repertoire des certificats (loki)
ansible.builtin.file:
path: "{{ serveur_loki_tls_dir }}"
state: directory
owner: loki
group: loki
mode: "0700"
when: serveur_loki_tls_actif | bool
- name: TLS — script de synchronisation du certificat
ansible.builtin.template:
src: setops-loki-cert-sync.sh.j2
dest: /usr/local/sbin/setops-loki-cert-sync
owner: root
group: root
mode: "0755"
when: serveur_loki_tls_actif | bool
- name: TLS — unites de synchronisation (service + path)
ansible.builtin.template:
src: "{{ item.s }}"
dest: "{{ item.d }}"
owner: root
group: root
mode: "0644"
loop:
- { s: "setops-loki-cert-sync.service.j2", d: "/etc/systemd/system/setops-loki-cert-sync.service" }
- { s: "setops-loki-cert-sync.path.j2", d: "/etc/systemd/system/setops-loki-cert-sync.path" }
loop_control:
label: "{{ item.d | basename }}"
when: serveur_loki_tls_actif | bool
- name: TLS — activer la surveillance du certificat (path)
ansible.builtin.systemd:
name: setops-loki-cert-sync.path
enabled: true
state: started
daemon_reload: true
when:
- serveur_loki_tls_actif | bool
- not ansible_check_mode
- name: TLS — synchroniser le certificat maintenant
ansible.builtin.command: /usr/local/sbin/setops-loki-cert-sync
changed_when: false
when:
- serveur_loki_tls_actif | bool
- not ansible_check_mode
- name: TLS — verifier la presence du certificat synchronise
ansible.builtin.stat:
path: "{{ serveur_loki_tls_dir }}/{{ item }}"
register: serveur_loki_tls_stat
loop:
- loki.crt
- loki.key
when:
- serveur_loki_tls_actif | bool
- not ansible_check_mode
- name: TLS — garde-fou, ne pas activer sans certificat en place
ansible.builtin.assert:
that:
- item.stat.exists
fail_msg: "Cert Loki absent ({{ item.item }}) — TLS non active."
loop: "{{ serveur_loki_tls_stat.results | default([]) }}"
loop_control:
label: "{{ item.item }}"
when:
- serveur_loki_tls_actif | bool
- not ansible_check_mode
- name: Deployer la configuration Loki
ansible.builtin.template:
src: config.yml.j2
dest: "{{ serveur_loki_config }}"
owner: root
group: loki
mode: "0640"
notify: Redemarrer loki
- name: Activer et demarrer Loki
when: not ansible_check_mode
ansible.builtin.systemd:
name: "{{ serveur_loki_service }}"
enabled: true
state: started
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
# --- Sonde de supervision (docs/supervision-conception.md) --------------------------
# Le role qui possede la verite depose sa propre sonde ; le porteur (`client_sante`) la
# fait tourner et pousse le verdict, sans savoir ce qu'elle mesure.
- name: Assurer le repertoire des sondes de supervision
ansible.builtin.file:
path: /usr/local/lib/setops/sondes
state: directory
owner: root
group: root
mode: "0755"
- name: Deposer la sonde « ingestion »
ansible.builtin.template:
src: sonde-ingestion.sh.j2
dest: /usr/local/lib/setops/sondes/ingestion.sh
owner: root
group: root
mode: "0750"
la frontiere journalise a nouveau, et une garde veille cette fois 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
2026-09-10 19:38:19 -04:00
# LA SONDE DE LA FRONTIERE N'EXISTE QUE LA OU ELLE EST ECOUTEE. Un tenant n'a pas de
# frontiere a lui : sans etiquette declaree, rien n'est depose et rien n'est attendu.
- name: Deposer la sonde des journaux de la frontiere
ansible.builtin.template:
src: sonde-frontiere.sh.j2
dest: /usr/local/lib/setops/sondes/journaux-frontiere.sh
owner: root
group: root
mode: "0750"
when: serveur_loki_sonde_frontiere_etiquette | length > 0
- name: Retirer la sonde de frontiere la ou aucune n'est ecoutee
ansible.builtin.file:
path: /usr/local/lib/setops/sondes/journaux-frontiere.sh
state: absent
when: not (serveur_loki_sonde_frontiere_etiquette | length > 0)