2026-06-24 20:17:46 -04:00
|
|
|
---
|
2026-08-09 14:05:25 -04:00
|
|
|
# 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.
|
2026-08-09 14:05:25 -04:00
|
|
|
- name: Cette ressource est-elle deja recuperee ? (Telecharger le trousseau de cles I)
|
|
|
|
|
ansible.builtin.stat:
|
|
|
|
|
path: "/tmp/icinga-archive-keyring.deb"
|
|
|
|
|
register: telecharger_le_trousseau_de_cles_icinga_present
|
|
|
|
|
|
2026-06-24 20:17:46 -04:00
|
|
|
- name: Telecharger le trousseau de cles Icinga
|
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_le_trousseau_de_cles_icinga_present.stat.exists and telecharger_le_trousseau_de_cles_icinga_present.stat.size | default(0) > 0)
|
2026-06-24 20:17:46 -04:00
|
|
|
ansible.builtin.get_url:
|
|
|
|
|
url: "{{ serveur_icinga_keyring_url }}"
|
|
|
|
|
dest: "/tmp/icinga-archive-keyring.deb"
|
|
|
|
|
mode: "0644"
|
2026-09-14 11:02:37 -04:00
|
|
|
# RECUPERER N'EST PAS INSTALLER, ET `--check` CASSAIT LA PAIRE (2026-09-14).
|
|
|
|
|
#
|
|
|
|
|
# Sans `check_mode: false`, ce telechargement est SIMULE en mode idempotent — et la
|
|
|
|
|
# tache qui suit cherche alors un fichier qui n'existe pas :
|
|
|
|
|
#
|
|
|
|
|
# Unable to install package: E:Could not open file
|
|
|
|
|
# /tmp/icinga-archive-keyring.deb - open (2: No such file or directory)
|
|
|
|
|
#
|
|
|
|
|
# Un essai a blanc rendait donc un echec sur la machine de supervision, alors que le
|
|
|
|
|
# deploiement reel passe. Le Makefile conseille ce mode : suivre le conseil fabriquait
|
|
|
|
|
# une fausse panne, et c'est la troisieme de cette famille dans le meme essai.
|
|
|
|
|
#
|
|
|
|
|
# Ce que ce `check_mode: false` autorise reellement : deposer un fichier dans `/tmp`.
|
|
|
|
|
# Rien du systeme gere n'en depend, et c'est ce qui permet a l'installation d'ETRE
|
|
|
|
|
# evaluee — donc au mode idempotent de dire ce qu'il promet.
|
|
|
|
|
check_mode: false
|
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: ""
|
2026-06-24 20:17:46 -04:00
|
|
|
|
|
|
|
|
- name: Installer le trousseau de cles Icinga
|
|
|
|
|
ansible.builtin.apt:
|
|
|
|
|
deb: "/tmp/icinga-archive-keyring.deb"
|
|
|
|
|
state: present
|
|
|
|
|
|
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: Retirer la forme HTTPS du depot (elle contournait le cache)
|
|
|
|
|
ansible.builtin.apt_repository:
|
|
|
|
|
repo: "{{ serveur_icinga_depot_source | replace('http://', 'https://') }}"
|
|
|
|
|
filename: icinga
|
|
|
|
|
state: absent
|
|
|
|
|
when: serveur_icinga_depot_schema == 'http'
|
|
|
|
|
|
2026-06-24 20:17:46 -04:00
|
|
|
- name: Ajouter le depot apt Icinga
|
|
|
|
|
ansible.builtin.apt_repository:
|
|
|
|
|
repo: "{{ serveur_icinga_depot_source }}"
|
|
|
|
|
filename: icinga
|
|
|
|
|
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_icinga_paquets }}"
|
|
|
|
|
|
2026-06-24 20:17:46 -04:00
|
|
|
- name: Installer Icinga 2, Icinga DB et Redis dedie
|
|
|
|
|
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_icinga_paquets | difference((paquets_tiers_disponibles | default({})).keys() | list) }}"
|
2026-06-24 20:17:46 -04:00
|
|
|
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_icinga_paquets
|
|
|
|
|
| difference((paquets_tiers_disponibles | default({})).keys() | list)) | length > 0
|
2026-07-03 15:57:06 -04:00
|
|
|
- name: Resoudre la base de donnees depuis le registre (role partage)
|
|
|
|
|
ansible.builtin.include_role:
|
|
|
|
|
name: resoudre_base
|
|
|
|
|
vars:
|
|
|
|
|
resoudre_base_groupe: "{{ serveur_icinga_groupe }}"
|
2026-06-24 20:17:46 -04:00
|
|
|
|
2026-07-03 15:57:06 -04:00
|
|
|
- name: Adopter les facts de base pour Icinga
|
2026-06-24 20:17:46 -04:00
|
|
|
ansible.builtin.set_fact:
|
2026-07-03 15:57:06 -04:00
|
|
|
serveur_icinga_entree: "{{ resoudre_base_entree }}"
|
|
|
|
|
serveur_icinga_db_password: "{{ resoudre_base_db_password }}"
|
|
|
|
|
serveur_icinga_db_host: "{{ resoudre_base_db_host }}"
|
2026-06-24 20:17:46 -04:00
|
|
|
no_log: true
|
|
|
|
|
|
reconstruction from-zero : sept defauts, tous invisibles sur une flotte debout
Chezlepro reconstruit depuis zero en 10.17.x.x. Sept defauts sont tombes, et
AUCUN n'etait detectable autrement — c'est tout l'argument de la reconstruction
comme preuve.
1. aucune route vers le tenant sur le poste (posee a la main, jamais persistee)
2. backup-01 exigeait l'AC d'Icinga — dependance non declaree
3. ma correction inversait les couches : REFUSEE PAR P08 avant d'entrer
4. base Forgejo a moitie initialisee (sequelle de l'arret du n°2)
5. /etc/hosts : nom court avant le FQDN -> hostname -f faux sur les 14 machines
6. API Icinga jamais activee (garde `creates:` d'api setup)
7. restic refuse tout le lot si un chemin declare manque
LE CINQUIEME DEPASSAIT ICINGA. hostname -f rend le PREMIER nom : toute la flotte
se croyait appelee « mon-01 ». Visible sur le certificat d'Icinga, mais le meme
piege attendait Postfix (myhostname), les journaux, les certificats. FQDN d'abord.
CE QU'ON NE CORRIGE PAS : icinga2 api setup REECRIT NodeName d'apres le nom court
et nomme ses certificats d'apres lui. Aligne avant, il est ecrase ; aligne apres,
les certificats portent le mauvais nom. On adopte sa convention : le depot appelle
l'API par le nom court, celui que le certificat porte.
serveur_icinga_node_name derive desormais de l'INVENTAIRE, pas d'ansible_fqdn —
un fait qui depend du resolveur et rendait « mon-01 » alors que le FQDN etait bon.
Le commentaire ecrit pour avertir qu'une sequence accolade-diese casse les
gabarits Jinja contenait cette sequence, et cassait le gabarit. Neuf hotes en
echec pour un avertissement mal redige.
Sept devis CONFORME, prouver 36/36, make test 0. Neuf sauvegardes reussies.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 03:36:56 -04:00
|
|
|
# --- Identite TLS de l'API (5665) ---
|
2026-08-13 08:49:12 -04:00
|
|
|
# ON NE TOUCHE PAS A `NodeName` — et il n'y a rien a corriger ici.
|
reconstruction from-zero : sept defauts, tous invisibles sur une flotte debout
Chezlepro reconstruit depuis zero en 10.17.x.x. Sept defauts sont tombes, et
AUCUN n'etait detectable autrement — c'est tout l'argument de la reconstruction
comme preuve.
1. aucune route vers le tenant sur le poste (posee a la main, jamais persistee)
2. backup-01 exigeait l'AC d'Icinga — dependance non declaree
3. ma correction inversait les couches : REFUSEE PAR P08 avant d'entrer
4. base Forgejo a moitie initialisee (sequelle de l'arret du n°2)
5. /etc/hosts : nom court avant le FQDN -> hostname -f faux sur les 14 machines
6. API Icinga jamais activee (garde `creates:` d'api setup)
7. restic refuse tout le lot si un chemin declare manque
LE CINQUIEME DEPASSAIT ICINGA. hostname -f rend le PREMIER nom : toute la flotte
se croyait appelee « mon-01 ». Visible sur le certificat d'Icinga, mais le meme
piege attendait Postfix (myhostname), les journaux, les certificats. FQDN d'abord.
CE QU'ON NE CORRIGE PAS : icinga2 api setup REECRIT NodeName d'apres le nom court
et nomme ses certificats d'apres lui. Aligne avant, il est ecrase ; aligne apres,
les certificats portent le mauvais nom. On adopte sa convention : le depot appelle
l'API par le nom court, celui que le certificat porte.
serveur_icinga_node_name derive desormais de l'INVENTAIRE, pas d'ansible_fqdn —
un fait qui depend du resolveur et rendait « mon-01 » alors que le FQDN etait bon.
Le commentaire ecrit pour avertir qu'une sequence accolade-diese casse les
gabarits Jinja contenait cette sequence, et cassait le gabarit. Neuf hotes en
echec pour un avertissement mal redige.
Sept devis CONFORME, prouver 36/36, make test 0. Neuf sauvegardes reussies.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 03:36:56 -04:00
|
|
|
#
|
2026-08-13 08:49:12 -04:00
|
|
|
# `icinga2 api setup` ECRIT lui-meme NodeName d'apres `hostname -f`, puis nomme ses
|
|
|
|
|
# certificats d'apres lui. Tant que `/etc/hosts` mettait le nom COURT en premier,
|
|
|
|
|
# `hostname -f` rendait « mon-01 » et le certificat devenait invérifiable en appelant par
|
|
|
|
|
# le nom complet. On a longuement tente d'aligner NodeName a la main, avant et apres
|
|
|
|
|
# `api setup` : efface a chaque fois.
|
|
|
|
|
#
|
|
|
|
|
# LA CAUSE ETAIT AILLEURS. Depuis que `hosts_statiques` place le FQDN en premier
|
|
|
|
|
# (2026-08-13), `hostname -f` rend le nom complet et Icinga s'emet spontanement un
|
|
|
|
|
# certificat CN et SAN = FQDN. Rien a forcer : il suffisait que la machine sache
|
|
|
|
|
# comment elle s'appelle.
|
2026-10-07 15:18:40 -04:00
|
|
|
# L'AC D'UNE INCARNATION PRECEDENTE REVIENT AVANT `api setup` (2026-10-07). Icinga 2 en
|
|
|
|
|
# derive l'environnement d'Icinga DB, donc l'identifiant de chaque hote, service et ligne
|
|
|
|
|
# d'historique. `api setup` la reutilise si elle est la (« Found CA, skipping and using the
|
|
|
|
|
# existing one », mesure sur mon-01) ; sinon il en fabrique une, et l'historique restaure
|
|
|
|
|
# par serveur_postgresql deviendrait orphelin. Aucun paquet n'en cree : c'est donc ICI.
|
|
|
|
|
- name: L'AC d'Icinga existe-t-elle deja ?
|
|
|
|
|
ansible.builtin.stat:
|
|
|
|
|
path: "{{ serveur_icinga_ca }}"
|
|
|
|
|
register: serveur_icinga_ca_presente
|
|
|
|
|
|
|
|
|
|
- name: Restauration — l'AC d'une incarnation precedente ?
|
|
|
|
|
ansible.builtin.include_role:
|
|
|
|
|
name: client_backup
|
|
|
|
|
tasks_from: restaurer.yml
|
|
|
|
|
vars:
|
|
|
|
|
client_backup_restaurer_jeu: serveur_icinga
|
|
|
|
|
client_backup_restaurer_vierge: "{{ not serveur_icinga_ca_presente.stat.exists }}"
|
|
|
|
|
|
|
|
|
|
- name: Restauration — remettre l'AC et l'environnement d'Icinga DB
|
|
|
|
|
changed_when: true
|
|
|
|
|
ansible.builtin.command:
|
|
|
|
|
argv: >-
|
|
|
|
|
{{ ['/usr/local/sbin/setops-restaurer', 'fichiers',
|
|
|
|
|
'--instantane', client_backup_restauration.instantane,
|
|
|
|
|
'--proprietaire', 'nagios:nagios'] + client_backup_restauration.chemins }}
|
|
|
|
|
when: client_backup_restauration.etat == 'a_restaurer'
|
|
|
|
|
|
|
|
|
|
- name: Restauration — acter l'AC remise
|
|
|
|
|
ansible.builtin.include_role:
|
|
|
|
|
name: client_backup
|
|
|
|
|
tasks_from: acter.yml
|
|
|
|
|
vars:
|
|
|
|
|
client_backup_acter_etat: restaure
|
|
|
|
|
when: client_backup_restauration.etat == 'a_restaurer'
|
|
|
|
|
|
2026-06-24 20:17:46 -04:00
|
|
|
- name: Configurer l'API Icinga 2
|
|
|
|
|
ansible.builtin.command:
|
|
|
|
|
cmd: icinga2 api setup
|
|
|
|
|
creates: /etc/icinga2/features-enabled/api.conf
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
|
|
|
|
- name: Activer la fonctionnalite icingadb dans Icinga 2
|
|
|
|
|
ansible.builtin.command:
|
|
|
|
|
cmd: icinga2 feature enable icingadb
|
|
|
|
|
creates: /etc/icinga2/features-enabled/icingadb.conf
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
|
|
|
|
- name: Activer et demarrer le Redis Icinga DB
|
2026-07-01 21:01:53 -04:00
|
|
|
when: not ansible_check_mode
|
2026-06-24 20:17:46 -04:00
|
|
|
ansible.builtin.systemd:
|
|
|
|
|
name: "{{ serveur_icinga_service_redis }}"
|
|
|
|
|
enabled: true
|
|
|
|
|
state: started
|
|
|
|
|
|
2026-10-07 15:18:40 -04:00
|
|
|
# SUR UNE BASE VIERGE SEULEMENT (2026-10-07). Le marqueur vit sur mon-01 : une machine
|
|
|
|
|
# reconstruite ne l'a plus, alors que la base, elle, revient restauree par serveur_postgresql
|
|
|
|
|
# (historique compris). Rejouer le schema par-dessus y ajouterait une version et des erreurs
|
|
|
|
|
# « already exists » que psql taisait. La base dit elle-meme si elle a deja son schema.
|
|
|
|
|
- name: Importer le schema Icinga DB dans PostgreSQL (une fois, base vierge)
|
2026-06-24 20:17:46 -04:00
|
|
|
ansible.builtin.shell:
|
|
|
|
|
cmd: >-
|
2026-10-07 15:18:40 -04:00
|
|
|
export PGPASSWORD='{{ serveur_icinga_db_password }}';
|
|
|
|
|
deja=$(psql -h {{ serveur_icinga_db_host }} -U {{ serveur_icinga_entree.proprietaire }}
|
|
|
|
|
-d {{ serveur_icinga_entree.base }} -tAX
|
|
|
|
|
-c "select to_regclass('public.icingadb_schema') is not null");
|
|
|
|
|
if [ "$deja" != t ]; then
|
2026-06-24 20:17:46 -04:00
|
|
|
psql -h {{ serveur_icinga_db_host }} -U {{ serveur_icinga_entree.proprietaire }}
|
2026-10-07 15:18:40 -04:00
|
|
|
-d {{ serveur_icinga_entree.base }} -f {{ serveur_icinga_schema }}; fi
|
2026-06-24 20:17:46 -04:00
|
|
|
&& touch /etc/icingadb/.schema-imported
|
|
|
|
|
creates: /etc/icingadb/.schema-imported
|
|
|
|
|
no_log: true
|
|
|
|
|
|
|
|
|
|
- name: Deployer la configuration Icinga DB
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: config.yml.j2
|
|
|
|
|
dest: "{{ serveur_icinga_config }}"
|
|
|
|
|
owner: root
|
|
|
|
|
group: icingadb
|
|
|
|
|
mode: "0640"
|
|
|
|
|
no_log: true
|
|
|
|
|
notify: Redemarrer icingadb
|
|
|
|
|
|
reconstruction from-zero : sept defauts, tous invisibles sur une flotte debout
Chezlepro reconstruit depuis zero en 10.17.x.x. Sept defauts sont tombes, et
AUCUN n'etait detectable autrement — c'est tout l'argument de la reconstruction
comme preuve.
1. aucune route vers le tenant sur le poste (posee a la main, jamais persistee)
2. backup-01 exigeait l'AC d'Icinga — dependance non declaree
3. ma correction inversait les couches : REFUSEE PAR P08 avant d'entrer
4. base Forgejo a moitie initialisee (sequelle de l'arret du n°2)
5. /etc/hosts : nom court avant le FQDN -> hostname -f faux sur les 14 machines
6. API Icinga jamais activee (garde `creates:` d'api setup)
7. restic refuse tout le lot si un chemin declare manque
LE CINQUIEME DEPASSAIT ICINGA. hostname -f rend le PREMIER nom : toute la flotte
se croyait appelee « mon-01 ». Visible sur le certificat d'Icinga, mais le meme
piege attendait Postfix (myhostname), les journaux, les certificats. FQDN d'abord.
CE QU'ON NE CORRIGE PAS : icinga2 api setup REECRIT NodeName d'apres le nom court
et nomme ses certificats d'apres lui. Aligne avant, il est ecrase ; aligne apres,
les certificats portent le mauvais nom. On adopte sa convention : le depot appelle
l'API par le nom court, celui que le certificat porte.
serveur_icinga_node_name derive desormais de l'INVENTAIRE, pas d'ansible_fqdn —
un fait qui depend du resolveur et rendait « mon-01 » alors que le FQDN etait bon.
Le commentaire ecrit pour avertir qu'une sequence accolade-diese casse les
gabarits Jinja contenait cette sequence, et cassait le gabarit. Neuf hotes en
echec pour un avertissement mal redige.
Sept devis CONFORME, prouver 36/36, make test 0. Neuf sauvegardes reussies.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 03:36:56 -04:00
|
|
|
# `icinga2 api setup` active la fonctionnalite EN MEME TEMPS qu'il pose les certificats,
|
|
|
|
|
# et sa garde `creates:` la saute des que le fichier existe. Consequence mesuree le
|
|
|
|
|
# 2026-08-12 : apres un nettoyage des certificats, l'API restait DESACTIVEE — icinga2
|
|
|
|
|
# demarrait, se declarait `active`, et n'ecoutait sur rien. Exiger l'activation
|
|
|
|
|
# separement rend l'etat independant de l'ordre des nettoyages.
|
|
|
|
|
- name: API — exiger que la fonctionnalite soit activee
|
|
|
|
|
ansible.builtin.command:
|
|
|
|
|
cmd: icinga2 feature enable api
|
|
|
|
|
creates: /etc/icinga2/features-enabled/api.conf
|
icinga : le pair est verifie — mais pas avec un certificat step-ca
Objectif : supprimer le `curl -k` du rapporteur. Fait, et la maniere a ete
imposee par la mesure.
SERVIR UN CERTIFICAT STEP-CA SUR L'API EST IMPOSSIBLE. Icinga le dit lui-meme :
« Our certificate will expire soon, but we own the CA. Renewing. » Il renouvelle
tout certificat expirant sous 30 jours ; les notres vivent 24 h ; possedant une
AC, il re-emet avec la sienne et ecrase le notre a chaque demarrage. Collision
entre deux politiques de PKI, et la notre n'est pas negociable.
Deux decouvertes en chemin, toutes deux par le garde-fou `icinga2 daemon -C`
ajoute au role, qui a ARRETE le deploiement avant de redemarrer la supervision :
- cert_path/key_path/ca_path sont DEPRECIES depuis 2.8 ; les poser reveille un
chemin de code herite qui exige en plus un objet Endpoint ;
- l'identite de l'API est le CN du certificat. NodeName valait « mon-01 », donc
le SAN aussi, alors qu'on appelle par le FQDN : aucune verification n'aurait
pu reussir. NodeName est desormais aligne sur le FQDN.
A LA PLACE : Icinga garde son AC (domaine de confiance FERME, legitime) et
backup-01 verifie le pair contre CETTE AC, recuperee depuis mon-01 au
deploiement. Le pair est authentifie ; seule la racine differe.
Controle negatif — une verification qu'on ne teste pas est un ornement : avec la
mauvaise AC (step-ca), curl refuse (« unable to get local issuer certificate ») ;
avec la bonne, les neuf rapports passent.
Sous-AC step-ca ecartee : elle poserait sur l'hote de supervision une cle capable
d'EMETTRE pour n'importe quel nom, alors qu'on a choisi le sens du flux pour que
compromettre mon-01 ne donne rien.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 08:33:50 -04:00
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
|
|
|
|
- name: API — durcir l'ApiListener (aucune config ni commande acceptee)
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: api.conf.j2
|
|
|
|
|
dest: /etc/icinga2/features-available/api.conf
|
|
|
|
|
owner: root
|
|
|
|
|
group: nagios
|
|
|
|
|
mode: "0640"
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
supervision : c'est le DEPOT qui dit ou en sont les sauvegardes
Icinga ne surveillait rien : aucun objet Host ni Service de Set-OPS, seulement
la config Debian d'origine sur localhost.
Superviser setops-sauvegarde.service aurait reproduit le defaut du jour meme :
l'unite etait VERTE sur onze noeuds pendant qu'elle n'emportait rien. Le noeud
sait qu'il a LANCE sa sauvegarde, pas qu'elle est ARRIVEE. backup-01 evalue donc
ses depots et pousse un resultat passif par noeud vers l'API Icinga.
Trois criteres, parce qu'un seul suffit a mentir : l'instantane existe, il est
recent (26 h / 50 h), il contient au moins un fichier.
Le sens du flux est delibere : le depot parle a la supervision, jamais l'inverse
— compromettre mon-01 ne donne aucun acces aux sauvegardes.
Le ttl de 6 h fait la fraicheur : si le rapporteur se tait, Icinga perime les
services tout seul. C'est le silence qui a laisse le defaut vivre un mois.
Deux erreurs corrigees par la mesure :
- --data-urlencode refuse en Bad Request (l'API veut du JSON) ; le flux, le TLS
et l'auth marchaient, seule la charge etait perdue.
- le seuil « vide » en octets signalait a tort idm-01 (2363 o) : un export LDIF
d'un annuaire a un compte pese cela. « Vide » se mesure en FICHIERS. Et le
verdict est un AVERTISSEMENT : la machine ne distingue pas « les donnees ont
disparu » de « il n'y en a pas encore ».
Reserve assumee : curl -k — l'API presente le cert de sa propre AC, pas step-ca.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 21:39:05 -04:00
|
|
|
# --- Supervision des sauvegardes ---
|
|
|
|
|
# La liste des detenteurs d'etat appartient a `client_backup`. On la LIT chez lui plutot
|
|
|
|
|
# que de la recopier : deux listes finissent toujours par diverger, et la divergence se
|
|
|
|
|
# lirait « tout va bien » des deux cotes.
|
|
|
|
|
- name: Lire la liste des detenteurs d'etat chez client_backup
|
|
|
|
|
ansible.builtin.include_vars:
|
|
|
|
|
file: "{{ role_path }}/../client_backup/vars/main.yml"
|
|
|
|
|
name: _catalogue_sauvegarde
|
|
|
|
|
|
|
|
|
|
- name: Adopter la liste des detenteurs d'etat
|
|
|
|
|
ansible.builtin.set_fact:
|
|
|
|
|
client_backup_groupes_etat: "{{ _catalogue_sauvegarde.client_backup_groupes_etat }}"
|
|
|
|
|
|
2026-09-02 18:53:44 -04:00
|
|
|
# UN ECOSYSTEME PEUT N'AVOIR AUCUN DEPOT A LUI, ET C'EST LE CAS NORMAL DEPUIS QU'ILS
|
|
|
|
|
# DEPOSENT CHEZ LEUR HEBERGEUR (2026-09-02).
|
|
|
|
|
#
|
|
|
|
|
# Cette assertion exigeait un hote `serveur_backup` dans l'ecosysteme. C'etait juste tant
|
|
|
|
|
# que le depot y vivait : il etait le seul a voir ce qui arrivait vraiment, et il
|
|
|
|
|
# rapportait pour tout le monde.
|
|
|
|
|
#
|
|
|
|
|
# Depuis la bascule vers le depot du SITE, l'ecosysteme n'en a plus. Le site, lui, ne
|
|
|
|
|
# peut pas ouvrir ces depots — restic chiffre chez le client. C'est donc chaque NOEUD qui
|
|
|
|
|
# verifie le sien (`client_backup/tasks/verifier.yml`) et rapporte ici. Ce qui reste
|
|
|
|
|
# exige, c'est le secret d'API : sans lui, personne ne peut rien rapporter.
|
|
|
|
|
- name: Exiger le secret d'API pour les rapports passifs (Vault)
|
supervision : c'est le DEPOT qui dit ou en sont les sauvegardes
Icinga ne surveillait rien : aucun objet Host ni Service de Set-OPS, seulement
la config Debian d'origine sur localhost.
Superviser setops-sauvegarde.service aurait reproduit le defaut du jour meme :
l'unite etait VERTE sur onze noeuds pendant qu'elle n'emportait rien. Le noeud
sait qu'il a LANCE sa sauvegarde, pas qu'elle est ARRIVEE. backup-01 evalue donc
ses depots et pousse un resultat passif par noeud vers l'API Icinga.
Trois criteres, parce qu'un seul suffit a mentir : l'instantane existe, il est
recent (26 h / 50 h), il contient au moins un fichier.
Le sens du flux est delibere : le depot parle a la supervision, jamais l'inverse
— compromettre mon-01 ne donne aucun acces aux sauvegardes.
Le ttl de 6 h fait la fraicheur : si le rapporteur se tait, Icinga perime les
services tout seul. C'est le silence qui a laisse le defaut vivre un mois.
Deux erreurs corrigees par la mesure :
- --data-urlencode refuse en Bad Request (l'API veut du JSON) ; le flux, le TLS
et l'auth marchaient, seule la charge etait perdue.
- le seuil « vide » en octets signalait a tort idm-01 (2363 o) : un export LDIF
d'un annuaire a un compte pese cela. « Vide » se mesure en FICHIERS. Et le
verdict est un AVERTISSEMENT : la machine ne distingue pas « les donnees ont
disparu » de « il n'y en a pas encore ».
Reserve assumee : curl -k — l'API presente le cert de sa propre AC, pas step-ca.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 21:39:05 -04:00
|
|
|
ansible.builtin.assert:
|
|
|
|
|
that:
|
|
|
|
|
- serveur_icinga_api_motdepasse | length > 0
|
|
|
|
|
fail_msg: >-
|
2026-09-02 18:53:44 -04:00
|
|
|
vault_icinga_api_depot requis : sans lui, ni le depot ni les noeuds ne peuvent
|
|
|
|
|
rapporter l'etat de leurs sauvegardes, et personne ne les surveille.
|
supervision : c'est le DEPOT qui dit ou en sont les sauvegardes
Icinga ne surveillait rien : aucun objet Host ni Service de Set-OPS, seulement
la config Debian d'origine sur localhost.
Superviser setops-sauvegarde.service aurait reproduit le defaut du jour meme :
l'unite etait VERTE sur onze noeuds pendant qu'elle n'emportait rien. Le noeud
sait qu'il a LANCE sa sauvegarde, pas qu'elle est ARRIVEE. backup-01 evalue donc
ses depots et pousse un resultat passif par noeud vers l'API Icinga.
Trois criteres, parce qu'un seul suffit a mentir : l'instantane existe, il est
recent (26 h / 50 h), il contient au moins un fichier.
Le sens du flux est delibere : le depot parle a la supervision, jamais l'inverse
— compromettre mon-01 ne donne aucun acces aux sauvegardes.
Le ttl de 6 h fait la fraicheur : si le rapporteur se tait, Icinga perime les
services tout seul. C'est le silence qui a laisse le defaut vivre un mois.
Deux erreurs corrigees par la mesure :
- --data-urlencode refuse en Bad Request (l'API veut du JSON) ; le flux, le TLS
et l'auth marchaient, seule la charge etait perdue.
- le seuil « vide » en octets signalait a tort idm-01 (2363 o) : un export LDIF
d'un annuaire a un compte pese cela. « Vide » se mesure en FICHIERS. Et le
verdict est un AVERTISSEMENT : la machine ne distingue pas « les donnees ont
disparu » de « il n'y en a pas encore ».
Reserve assumee : curl -k — l'API presente le cert de sa propre AC, pas step-ca.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 21:39:05 -04:00
|
|
|
|
supervision : la sonde se declare dans le role, comme le flux
LE CONSTAT. 39 roles declarent leurs flux, 32 leur empreinte, 32 leur
authentification — tous derives. Et 19 groupes sur 19 declaraient une
surveillance en prose que RIEN n executait ; Icinga en surveillait deux.
La carte disait ce qui etait surveille, et personne ne surveillait.
LE MECANISME. Un role declare ses sondes dans meta/supervision.yml et
depose lui-meme son script dans /usr/local/lib/setops/sondes/. Le porteur
client_sante les fait toutes tourner et pousse un resultat passif par
sonde, sans savoir ce qu elles mesurent. serveur_icinga derive les objets
Service ET le filtre de permission d API des memes declarations. Ajouter
une sonde ne demande de toucher ni au porteur ni a Icinga.
PREMIERE SONDE : client_pki/certificat. Heures restantes sur le certificat
reellement pose, chaine verifiee, et empreinte SERVIE comparee au disque
quand un service le consomme. 14/14 au tenant, 7/7 au site.
QUATRE OBSTACLES, ET TROIS SONT LA MEME LECON.
La sonde a rendu 14/14 en CRITIQUE sur une PKI saine : openssl verify
-CAfile racine ne trouve pas l intermediaire qui signe nos certificats.
step certificate verify, lui, repond VALIDE.
Deployee au site, elle a rendu 5/7 : le seuil d avertissement (12 h)
etait AU-DESSUS du point de renouvellement (8 h, le tiers restant). Elle
criait avant que le mecanisme ne soit cense agir. Seuils ramenes a 6 h et
3 h. Un seuil se DERIVE du moment ou le mecanisme surveille agit.
Une alarme toujours allumee ne vaut pas mieux qu une alarme jamais
allumee : elle apprend a ne plus regarder. Une sonde se prouve DEUX FOIS,
verte sur le sain et rouge sur le casse.
Le filtre d API etait ecrit avant la lecture des declarations : les
services auraient existe et Icinga aurait refuse leurs resultats.
Et mon controle negatif a casse un service reel : substituer le certificat
d hote a fait propager un cert sans sa clef vers node_exporter. Un controle
negatif se fait sur une COPIE.
P64 tient les deux bouts : declaree sans etre deposee, ou deposee sans
etre declaree. Trois controles negatifs rejoues.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-09 21:45:49 -04:00
|
|
|
# LU AVANT LE COMPTE D'API, ET CE N'EST PAS COSMETIQUE : le filtre de permission
|
|
|
|
|
# DERIVE de ces declarations. Releve apres, il aurait ete ecrit sans les noms des
|
|
|
|
|
# sondes — les services auraient existe, et Icinga aurait refuse leurs resultats
|
|
|
|
|
# avec un 404 « No objects found » sur des objets bien presents. Mesure du
|
|
|
|
|
# 2026-09-09 : `certificat` manquait au filtre pour cette seule raison.
|
|
|
|
|
- name: Relever les sondes que les roles declarent
|
|
|
|
|
ansible.builtin.find:
|
|
|
|
|
paths: "{{ role_path }}/.."
|
|
|
|
|
patterns: supervision.yml
|
|
|
|
|
recurse: true
|
|
|
|
|
depth: 3
|
|
|
|
|
delegate_to: localhost
|
|
|
|
|
become: false
|
|
|
|
|
register: serveur_icinga_metas_supervision
|
|
|
|
|
|
|
|
|
|
- name: Lire chaque declaration de supervision
|
|
|
|
|
ansible.builtin.slurp:
|
|
|
|
|
src: "{{ item.path }}"
|
|
|
|
|
delegate_to: localhost
|
|
|
|
|
become: false
|
|
|
|
|
loop: "{{ serveur_icinga_metas_supervision.files }}"
|
|
|
|
|
loop_control:
|
|
|
|
|
label: "{{ item.path | dirname | dirname | basename }}"
|
|
|
|
|
register: serveur_icinga_supervision_brute
|
|
|
|
|
|
|
|
|
|
- name: Assembler le registre des sondes (role -> sondes)
|
|
|
|
|
ansible.builtin.set_fact:
|
|
|
|
|
serveur_icinga_sondes: >-
|
|
|
|
|
{{ dict(serveur_icinga_supervision_brute.results
|
|
|
|
|
| map(attribute='item.path') | map('dirname') | map('dirname') | map('basename')
|
|
|
|
|
| zip(serveur_icinga_supervision_brute.results
|
|
|
|
|
| map(attribute='content') | map('b64decode') | map('from_yaml')
|
|
|
|
|
| map(attribute='sondes'))) }}
|
|
|
|
|
|
supervision : c'est le DEPOT qui dit ou en sont les sauvegardes
Icinga ne surveillait rien : aucun objet Host ni Service de Set-OPS, seulement
la config Debian d'origine sur localhost.
Superviser setops-sauvegarde.service aurait reproduit le defaut du jour meme :
l'unite etait VERTE sur onze noeuds pendant qu'elle n'emportait rien. Le noeud
sait qu'il a LANCE sa sauvegarde, pas qu'elle est ARRIVEE. backup-01 evalue donc
ses depots et pousse un resultat passif par noeud vers l'API Icinga.
Trois criteres, parce qu'un seul suffit a mentir : l'instantane existe, il est
recent (26 h / 50 h), il contient au moins un fichier.
Le sens du flux est delibere : le depot parle a la supervision, jamais l'inverse
— compromettre mon-01 ne donne aucun acces aux sauvegardes.
Le ttl de 6 h fait la fraicheur : si le rapporteur se tait, Icinga perime les
services tout seul. C'est le silence qui a laisse le defaut vivre un mois.
Deux erreurs corrigees par la mesure :
- --data-urlencode refuse en Bad Request (l'API veut du JSON) ; le flux, le TLS
et l'auth marchaient, seule la charge etait perdue.
- le seuil « vide » en octets signalait a tort idm-01 (2363 o) : un export LDIF
d'un annuaire a un compte pese cela. « Vide » se mesure en FICHIERS. Et le
verdict est un AVERTISSEMENT : la machine ne distingue pas « les donnees ont
disparu » de « il n'y en a pas encore ».
Reserve assumee : curl -k — l'API presente le cert de sa propre AC, pas step-ca.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 21:39:05 -04:00
|
|
|
- name: Deployer le compte d'API du depot de sauvegarde
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: setops-api-users.conf.j2
|
|
|
|
|
dest: "{{ serveur_icinga_api_conf }}"
|
|
|
|
|
owner: root
|
|
|
|
|
group: nagios
|
|
|
|
|
mode: "0640"
|
|
|
|
|
no_log: true
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
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
|
|
|
# LES HOTES D'ABORD : les fichiers de service s'y attachent, et Icinga refuse un service
|
|
|
|
|
# dont l'hote n'existe pas. L'ordre dans `conf.d` n'est pas garanti par le nom, mais
|
|
|
|
|
# Icinga charge tout le repertoire avant de resoudre — l'ordre de deploiement suffit.
|
icinga : l hote de supervision saturait par sa propre demonstration
« mon-01 tape dans l fond. » Il tapait : load 5,10 sur 4 coeurs, 8
processus check_disk a 70-99 % de CPU chacun, jusqu a 28 minutes de vie.
check_disk 2.4.0-3+deb13u1 ne rend jamais la main sur cet hote (etat R).
Icinga en relancait un a chaque intervalle pour le service `disk` de son
hote de DEMONSTRATION, et aucun ne mourait.
RETIRE : conf.d/hosts.conf, l hote NodeName livre par le paquet. Les apply
Service s y accrochaient — disk, http, swap, apt, load, procs, users — et
trois etaient rouges en permanence (swap sur une VM sans swap, http sur un
port ou rien n ecoute, apt pour un paquet). On retire l HOTE et non les
services : sans lui les apply ne s accrochent a rien, et on ne touche pas
a un fichier que le paquet remplacera. Ca garde ping4, qui vise nos hotes
et sert vraiment.
avant : load 5,10 — 8 check_disk — 3 alarmes rouges permanentes
apres : load 0,77 — 0 check_disk — certificat 14/14, sante 14/14, ping4 14/14
TROUVE EN VERIFIANT : l Icinga du SITE tenait 6 de ses 7 machines pour
MORTES (1/7 UP, contre 14/14 au tenant). hostalive est un ping, le site
est decoupe en zones, et l ICMP inter-zones n etait declare nulle part —
100 % de perte, mesure. Or Icinga SUPPRIME les notifications des services
d un hote DOWN : une supervision qui croit tout mort n alerte plus de
rien, tout en ayant l air de fonctionner.
Le flux est declare des DEUX cotes, et le registre a refuse la premiere
moitie seule — exactement sa raison d etre. CODES_ICMP apprend
echo-request. Regles d hote posees sur les 21 machines.
RESTE OUVERT : le generateur de la frontiere ne sait pas traduire un TYPE
ICMP pour un pair INTERNE — il le note et n emet rien. Le site reste a
1/7. Corriger devis_opnsense.py est le prochain geste.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-09 22:34:32 -04:00
|
|
|
# L'HOTE D'EXEMPLE LIVRE PAR ICINGA : RETIRE (mesure du 2026-09-09).
|
|
|
|
|
#
|
|
|
|
|
# `conf.d/hosts.conf` definit `object Host NodeName` — un `localhost` de demonstration
|
|
|
|
|
# avec `vars.disks`, `vars.http_vhosts`, `vars.os`. Les `apply Service` de
|
|
|
|
|
# `conf.d/services.conf` s'y accrochent : `disk`, `http`, `swap`, `apt`, `load`, `procs`,
|
|
|
|
|
# `users`. Aucun ne decrit cet ecosysteme, et trois etaient ROUGES EN PERMANENCE :
|
|
|
|
|
#
|
|
|
|
|
# swap : SWAP CRITICAL - 0% free (une VM sans swap)
|
|
|
|
|
# http : connect to 127.0.0.1:80 (rien n'ecoute la)
|
|
|
|
|
# apt : 1 package upgradable
|
|
|
|
|
#
|
|
|
|
|
# Trois alarmes qui ne peuvent que rester rouges, dans le seul endroit qui doit rester
|
|
|
|
|
# lisible. C'est deja une raison suffisante — une supervision creuse est pire qu'aucune.
|
|
|
|
|
#
|
|
|
|
|
# MAIS LE QUATRIEME NE FAISAIT PAS QUE MENTIR, IL NUISAIT. `check_disk`
|
|
|
|
|
# 2.4.0-3+deb13u1 ne rend jamais la main sur cet hote (etat `R`, boucle, quels que soient
|
|
|
|
|
# ses arguments). Icinga en relancait un a CHAQUE intervalle, et aucun ne mourait :
|
|
|
|
|
#
|
|
|
|
|
# 8 processus check_disk, 70 a 99 % de CPU chacun, jusqu'a 28 minutes de vie
|
|
|
|
|
# charge 5,10 sur 4 coeurs — l'hote de supervision sature par sa propre demonstration
|
|
|
|
|
#
|
|
|
|
|
# On retire l'HOTE plutot que les services : sans lui, les `apply` ne s'accrochent a rien,
|
|
|
|
|
# et on ne touche pas a un fichier que le paquet remplacera a la prochaine mise a jour.
|
|
|
|
|
# Les hotes de cet ecosysteme sont declares par `setops-hotes.conf`.
|
|
|
|
|
- name: Retirer l'hote de demonstration livre par Icinga
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: /etc/icinga2/conf.d/hosts.conf
|
|
|
|
|
state: absent
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
supervision : la sonde se declare dans le role, comme le flux
LE CONSTAT. 39 roles declarent leurs flux, 32 leur empreinte, 32 leur
authentification — tous derives. Et 19 groupes sur 19 declaraient une
surveillance en prose que RIEN n executait ; Icinga en surveillait deux.
La carte disait ce qui etait surveille, et personne ne surveillait.
LE MECANISME. Un role declare ses sondes dans meta/supervision.yml et
depose lui-meme son script dans /usr/local/lib/setops/sondes/. Le porteur
client_sante les fait toutes tourner et pousse un resultat passif par
sonde, sans savoir ce qu elles mesurent. serveur_icinga derive les objets
Service ET le filtre de permission d API des memes declarations. Ajouter
une sonde ne demande de toucher ni au porteur ni a Icinga.
PREMIERE SONDE : client_pki/certificat. Heures restantes sur le certificat
reellement pose, chaine verifiee, et empreinte SERVIE comparee au disque
quand un service le consomme. 14/14 au tenant, 7/7 au site.
QUATRE OBSTACLES, ET TROIS SONT LA MEME LECON.
La sonde a rendu 14/14 en CRITIQUE sur une PKI saine : openssl verify
-CAfile racine ne trouve pas l intermediaire qui signe nos certificats.
step certificate verify, lui, repond VALIDE.
Deployee au site, elle a rendu 5/7 : le seuil d avertissement (12 h)
etait AU-DESSUS du point de renouvellement (8 h, le tiers restant). Elle
criait avant que le mecanisme ne soit cense agir. Seuils ramenes a 6 h et
3 h. Un seuil se DERIVE du moment ou le mecanisme surveille agit.
Une alarme toujours allumee ne vaut pas mieux qu une alarme jamais
allumee : elle apprend a ne plus regarder. Une sonde se prouve DEUX FOIS,
verte sur le sain et rouge sur le casse.
Le filtre d API etait ecrit avant la lecture des declarations : les
services auraient existe et Icinga aurait refuse leurs resultats.
Et mon controle negatif a casse un service reel : substituer le certificat
d hote a fait propager un cert sans sa clef vers node_exporter. Un controle
negatif se fait sur une COPIE.
P64 tient les deux bouts : declaree sans etre deposee, ou deposee sans
etre declaree. Trois controles negatifs rejoues.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-09 21:45:49 -04:00
|
|
|
# LES SONDES DECLAREES PAR LES ROLES (docs/supervision-conception.md).
|
|
|
|
|
#
|
|
|
|
|
# On lit les `meta/supervision.yml` sur le CONTROLEUR, pas sur la cible : c'est le depot
|
|
|
|
|
# qui fait foi, et la cible n'a aucune raison de porter les declarations des autres.
|
|
|
|
|
#
|
|
|
|
|
# Lecture explicite plutot que dependance a l'ordre de chargement des roles : un
|
|
|
|
|
# `client_pki_*` visible ici parce qu'un autre role l'a charge avant serait un couplage
|
|
|
|
|
# invisible, et il se romprait le jour ou l'ordre change.
|
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
|
|
|
- name: Deployer les hotes supervises (definis une seule fois)
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: setops-hotes.conf.j2
|
|
|
|
|
dest: "{{ serveur_icinga_hotes_conf }}"
|
|
|
|
|
owner: root
|
|
|
|
|
group: nagios
|
|
|
|
|
mode: "0640"
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
supervision : c'est le DEPOT qui dit ou en sont les sauvegardes
Icinga ne surveillait rien : aucun objet Host ni Service de Set-OPS, seulement
la config Debian d'origine sur localhost.
Superviser setops-sauvegarde.service aurait reproduit le defaut du jour meme :
l'unite etait VERTE sur onze noeuds pendant qu'elle n'emportait rien. Le noeud
sait qu'il a LANCE sa sauvegarde, pas qu'elle est ARRIVEE. backup-01 evalue donc
ses depots et pousse un resultat passif par noeud vers l'API Icinga.
Trois criteres, parce qu'un seul suffit a mentir : l'instantane existe, il est
recent (26 h / 50 h), il contient au moins un fichier.
Le sens du flux est delibere : le depot parle a la supervision, jamais l'inverse
— compromettre mon-01 ne donne aucun acces aux sauvegardes.
Le ttl de 6 h fait la fraicheur : si le rapporteur se tait, Icinga perime les
services tout seul. C'est le silence qui a laisse le defaut vivre un mois.
Deux erreurs corrigees par la mesure :
- --data-urlencode refuse en Bad Request (l'API veut du JSON) ; le flux, le TLS
et l'auth marchaient, seule la charge etait perdue.
- le seuil « vide » en octets signalait a tort idm-01 (2363 o) : un export LDIF
d'un annuaire a un compte pese cela. « Vide » se mesure en FICHIERS. Et le
verdict est un AVERTISSEMENT : la machine ne distingue pas « les donnees ont
disparu » de « il n'y en a pas encore ».
Reserve assumee : curl -k — l'API presente le cert de sa propre AC, pas step-ca.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 21:39:05 -04:00
|
|
|
- name: Deployer les objets de supervision des sauvegardes
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: setops-sauvegardes.conf.j2
|
|
|
|
|
dest: "{{ serveur_icinga_setops_conf }}"
|
|
|
|
|
owner: root
|
|
|
|
|
group: nagios
|
|
|
|
|
mode: "0640"
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
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
|
|
|
- name: Deployer les objets de supervision de la sante des noeuds
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: setops-sante.conf.j2
|
|
|
|
|
dest: "{{ serveur_icinga_sante_conf }}"
|
|
|
|
|
owner: root
|
|
|
|
|
group: nagios
|
|
|
|
|
mode: "0640"
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
supervision : la sonde se declare dans le role, comme le flux
LE CONSTAT. 39 roles declarent leurs flux, 32 leur empreinte, 32 leur
authentification — tous derives. Et 19 groupes sur 19 declaraient une
surveillance en prose que RIEN n executait ; Icinga en surveillait deux.
La carte disait ce qui etait surveille, et personne ne surveillait.
LE MECANISME. Un role declare ses sondes dans meta/supervision.yml et
depose lui-meme son script dans /usr/local/lib/setops/sondes/. Le porteur
client_sante les fait toutes tourner et pousse un resultat passif par
sonde, sans savoir ce qu elles mesurent. serveur_icinga derive les objets
Service ET le filtre de permission d API des memes declarations. Ajouter
une sonde ne demande de toucher ni au porteur ni a Icinga.
PREMIERE SONDE : client_pki/certificat. Heures restantes sur le certificat
reellement pose, chaine verifiee, et empreinte SERVIE comparee au disque
quand un service le consomme. 14/14 au tenant, 7/7 au site.
QUATRE OBSTACLES, ET TROIS SONT LA MEME LECON.
La sonde a rendu 14/14 en CRITIQUE sur une PKI saine : openssl verify
-CAfile racine ne trouve pas l intermediaire qui signe nos certificats.
step certificate verify, lui, repond VALIDE.
Deployee au site, elle a rendu 5/7 : le seuil d avertissement (12 h)
etait AU-DESSUS du point de renouvellement (8 h, le tiers restant). Elle
criait avant que le mecanisme ne soit cense agir. Seuils ramenes a 6 h et
3 h. Un seuil se DERIVE du moment ou le mecanisme surveille agit.
Une alarme toujours allumee ne vaut pas mieux qu une alarme jamais
allumee : elle apprend a ne plus regarder. Une sonde se prouve DEUX FOIS,
verte sur le sain et rouge sur le casse.
Le filtre d API etait ecrit avant la lecture des declarations : les
services auraient existe et Icinga aurait refuse leurs resultats.
Et mon controle negatif a casse un service reel : substituer le certificat
d hote a fait propager un cert sans sa clef vers node_exporter. Un controle
negatif se fait sur une COPIE.
P64 tient les deux bouts : declaree sans etre deposee, ou deposee sans
etre declaree. Trois controles negatifs rejoues.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-09 21:45:49 -04:00
|
|
|
- name: Deployer les objets de supervision declares par les roles
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: setops-sondes.conf.j2
|
|
|
|
|
dest: "{{ serveur_icinga_sondes_conf }}"
|
|
|
|
|
owner: root
|
|
|
|
|
group: nagios
|
|
|
|
|
mode: "0640"
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
2026-09-17 10:13:43 -04:00
|
|
|
# --- LE MATERIEL (2026-09-17) ------------------------------------------------------------
|
|
|
|
|
# Hyperviseurs et frontiere : Icinga juge ce que Prometheus a tire, avec le catalogue du
|
|
|
|
|
# tableau Grafana. Voir `scripts/materiel.py`.
|
|
|
|
|
- name: Assurer le repertoire des controles actifs Set-OPS
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: "{{ serveur_icinga_materiel_sonde | dirname }}"
|
|
|
|
|
state: directory
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0755"
|
|
|
|
|
when: setops_materiel_hotes is defined
|
|
|
|
|
|
|
|
|
|
- name: Deposer le controle du materiel
|
|
|
|
|
ansible.builtin.copy:
|
|
|
|
|
src: check_materiel.py
|
|
|
|
|
dest: "{{ serveur_icinga_materiel_sonde }}"
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0755"
|
|
|
|
|
when: setops_materiel_hotes is defined
|
|
|
|
|
|
|
|
|
|
- name: Deposer le catalogue des capteurs
|
|
|
|
|
ansible.builtin.copy:
|
|
|
|
|
content: "{{ setops_materiel | to_nice_json }}\n"
|
|
|
|
|
dest: "{{ serveur_icinga_materiel_catalogue }}"
|
|
|
|
|
owner: root
|
|
|
|
|
group: nagios
|
|
|
|
|
mode: "0640"
|
|
|
|
|
validate: "python3 -c \"import json,sys; json.load(open(sys.argv[1]))\" %s"
|
|
|
|
|
when: setops_materiel_hotes is defined
|
|
|
|
|
|
|
|
|
|
- name: Deployer les objets de supervision du materiel
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: setops-materiel.conf.j2
|
|
|
|
|
dest: "{{ serveur_icinga_materiel_conf }}"
|
|
|
|
|
owner: root
|
|
|
|
|
group: nagios
|
|
|
|
|
mode: "0640"
|
|
|
|
|
when: setops_materiel_hotes is defined
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
supervision : c'est le DEPOT qui dit ou en sont les sauvegardes
Icinga ne surveillait rien : aucun objet Host ni Service de Set-OPS, seulement
la config Debian d'origine sur localhost.
Superviser setops-sauvegarde.service aurait reproduit le defaut du jour meme :
l'unite etait VERTE sur onze noeuds pendant qu'elle n'emportait rien. Le noeud
sait qu'il a LANCE sa sauvegarde, pas qu'elle est ARRIVEE. backup-01 evalue donc
ses depots et pousse un resultat passif par noeud vers l'API Icinga.
Trois criteres, parce qu'un seul suffit a mentir : l'instantane existe, il est
recent (26 h / 50 h), il contient au moins un fichier.
Le sens du flux est delibere : le depot parle a la supervision, jamais l'inverse
— compromettre mon-01 ne donne aucun acces aux sauvegardes.
Le ttl de 6 h fait la fraicheur : si le rapporteur se tait, Icinga perime les
services tout seul. C'est le silence qui a laisse le defaut vivre un mois.
Deux erreurs corrigees par la mesure :
- --data-urlencode refuse en Bad Request (l'API veut du JSON) ; le flux, le TLS
et l'auth marchaient, seule la charge etait perdue.
- le seuil « vide » en octets signalait a tort idm-01 (2363 o) : un export LDIF
d'un annuaire a un compte pese cela. « Vide » se mesure en FICHIERS. Et le
verdict est un AVERTISSEMENT : la machine ne distingue pas « les donnees ont
disparu » de « il n'y en a pas encore ».
Reserve assumee : curl -k — l'API presente le cert de sa propre AC, pas step-ca.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 21:39:05 -04:00
|
|
|
- name: Valider la configuration Icinga 2 avant de la rendre vivante
|
|
|
|
|
ansible.builtin.command:
|
|
|
|
|
cmd: icinga2 daemon -C
|
|
|
|
|
changed_when: false
|
|
|
|
|
|
2026-06-24 20:17:46 -04:00
|
|
|
- name: Activer et demarrer Icinga 2 et Icinga DB
|
2026-07-01 21:01:53 -04:00
|
|
|
when: not ansible_check_mode
|
2026-06-24 20:17:46 -04:00
|
|
|
ansible.builtin.systemd:
|
|
|
|
|
name: "{{ item }}"
|
|
|
|
|
enabled: true
|
|
|
|
|
state: started
|
|
|
|
|
loop:
|
|
|
|
|
- "{{ serveur_icinga_service_icinga2 }}"
|
|
|
|
|
- "{{ serveur_icinga_service_icingadb }}"
|
reconstruction from-zero : sept defauts, tous invisibles sur une flotte debout
Chezlepro reconstruit depuis zero en 10.17.x.x. Sept defauts sont tombes, et
AUCUN n'etait detectable autrement — c'est tout l'argument de la reconstruction
comme preuve.
1. aucune route vers le tenant sur le poste (posee a la main, jamais persistee)
2. backup-01 exigeait l'AC d'Icinga — dependance non declaree
3. ma correction inversait les couches : REFUSEE PAR P08 avant d'entrer
4. base Forgejo a moitie initialisee (sequelle de l'arret du n°2)
5. /etc/hosts : nom court avant le FQDN -> hostname -f faux sur les 14 machines
6. API Icinga jamais activee (garde `creates:` d'api setup)
7. restic refuse tout le lot si un chemin declare manque
LE CINQUIEME DEPASSAIT ICINGA. hostname -f rend le PREMIER nom : toute la flotte
se croyait appelee « mon-01 ». Visible sur le certificat d'Icinga, mais le meme
piege attendait Postfix (myhostname), les journaux, les certificats. FQDN d'abord.
CE QU'ON NE CORRIGE PAS : icinga2 api setup REECRIT NodeName d'apres le nom court
et nomme ses certificats d'apres lui. Aligne avant, il est ecrase ; aligne apres,
les certificats portent le mauvais nom. On adopte sa convention : le depot appelle
l'API par le nom court, celui que le certificat porte.
serveur_icinga_node_name derive desormais de l'INVENTAIRE, pas d'ansible_fqdn —
un fait qui depend du resolveur et rendait « mon-01 » alors que le FQDN etait bon.
Le commentaire ecrit pour avertir qu'une sequence accolade-diese casse les
gabarits Jinja contenait cette sequence, et cassait le gabarit. Neuf hotes en
echec pour un avertissement mal redige.
Sept devis CONFORME, prouver 36/36, make test 0. Neuf sauvegardes reussies.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 03:36:56 -04:00
|
|
|
|
|
|
|
|
# --- Publier l'AC vers le depot de sauvegarde ---
|
|
|
|
|
# Le depot rapporte l'etat des instantanes a cette API et doit VERIFIER le pair. Il lui
|
|
|
|
|
# faut donc cette AC — mais lui est un SERVICE et nous une APPLICATION : il se deploie
|
|
|
|
|
# AVANT nous, et exiger son attente inverserait le graphe des couches (refuse par P08 le
|
|
|
|
|
# 2026-08-12). C'est donc a NOUS de la lui porter, une fois que `icinga2 api setup` l'a
|
|
|
|
|
# creee. Sens correct : l'application rejoint le service, jamais l'inverse.
|
|
|
|
|
- name: Publier l'AC d'Icinga vers le depot de sauvegarde
|
|
|
|
|
when: groups['serveur_backup'] | default([]) | length > 0
|
|
|
|
|
ansible.builtin.slurp:
|
|
|
|
|
src: "{{ serveur_icinga_ca }}"
|
|
|
|
|
register: serveur_icinga_ca_contenu
|
|
|
|
|
|
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
|
|
|
# LE REPERTOIRE N'EXISTE PAS AU PREMIER JOUR (2026-09-12). `/etc/setops` est cree par
|
|
|
|
|
# `client_sante`, qui vit dans une couche POSTERIEURE. Sur une machine deja construite il
|
|
|
|
|
# est la ; a froid, non — et `copy` ne cree pas ses parents :
|
|
|
|
|
#
|
|
|
|
|
# Destination directory /etc/setops does not exist
|
|
|
|
|
#
|
|
|
|
|
# On le pose donc ici, avec les memes droits que `client_sante` lui donnerait. Deux roles
|
|
|
|
|
# qui creent le meme repertoire ne se genent pas ; un role qui suppose qu'un autre est
|
|
|
|
|
# deja passe, si.
|
|
|
|
|
- name: Assurer le repertoire d'accueil sur le depot de sauvegarde
|
|
|
|
|
when: groups['serveur_backup'] | default([]) | length > 0
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: "{{ serveur_icinga_ca_destination_depot | dirname }}"
|
|
|
|
|
state: directory
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
2026-10-01 14:01:54 -04:00
|
|
|
mode: "0700" # comme client_sante et client_backup (test_repertoires_partages.py)
|
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
|
|
|
delegate_to: "{{ groups['serveur_backup'] | first }}"
|
|
|
|
|
|
reconstruction from-zero : sept defauts, tous invisibles sur une flotte debout
Chezlepro reconstruit depuis zero en 10.17.x.x. Sept defauts sont tombes, et
AUCUN n'etait detectable autrement — c'est tout l'argument de la reconstruction
comme preuve.
1. aucune route vers le tenant sur le poste (posee a la main, jamais persistee)
2. backup-01 exigeait l'AC d'Icinga — dependance non declaree
3. ma correction inversait les couches : REFUSEE PAR P08 avant d'entrer
4. base Forgejo a moitie initialisee (sequelle de l'arret du n°2)
5. /etc/hosts : nom court avant le FQDN -> hostname -f faux sur les 14 machines
6. API Icinga jamais activee (garde `creates:` d'api setup)
7. restic refuse tout le lot si un chemin declare manque
LE CINQUIEME DEPASSAIT ICINGA. hostname -f rend le PREMIER nom : toute la flotte
se croyait appelee « mon-01 ». Visible sur le certificat d'Icinga, mais le meme
piege attendait Postfix (myhostname), les journaux, les certificats. FQDN d'abord.
CE QU'ON NE CORRIGE PAS : icinga2 api setup REECRIT NodeName d'apres le nom court
et nomme ses certificats d'apres lui. Aligne avant, il est ecrase ; aligne apres,
les certificats portent le mauvais nom. On adopte sa convention : le depot appelle
l'API par le nom court, celui que le certificat porte.
serveur_icinga_node_name derive desormais de l'INVENTAIRE, pas d'ansible_fqdn —
un fait qui depend du resolveur et rendait « mon-01 » alors que le FQDN etait bon.
Le commentaire ecrit pour avertir qu'une sequence accolade-diese casse les
gabarits Jinja contenait cette sequence, et cassait le gabarit. Neuf hotes en
echec pour un avertissement mal redige.
Sept devis CONFORME, prouver 36/36, make test 0. Neuf sauvegardes reussies.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 03:36:56 -04:00
|
|
|
- name: Deposer l'AC sur le depot de sauvegarde
|
|
|
|
|
when: groups['serveur_backup'] | default([]) | length > 0
|
|
|
|
|
ansible.builtin.copy:
|
|
|
|
|
content: "{{ serveur_icinga_ca_contenu.content | b64decode }}"
|
|
|
|
|
dest: "{{ serveur_icinga_ca_destination_depot }}"
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0644"
|
|
|
|
|
delegate_to: "{{ groups['serveur_backup'] | first }}"
|
2026-09-02 17:48:19 -04:00
|
|
|
|
|
|
|
|
# --- A QUI PARLER -------------------------------------------------------------
|
|
|
|
|
- name: Déclarer le destinataire des alertes
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: setops-users.conf.j2
|
|
|
|
|
dest: /etc/icinga2/conf.d/setops-users.conf
|
|
|
|
|
owner: root
|
|
|
|
|
group: nagios
|
|
|
|
|
mode: "0640"
|
|
|
|
|
when: serveur_icinga_destinataire | length > 0
|
|
|
|
|
notify: Redemarrer icinga2
|
|
|
|
|
|
|
|
|
|
# DIRE CE QU'ON NE FAIT PAS. Sans destinataire, Icinga notifie `root@localhost` — une
|
|
|
|
|
# adresse que personne ne lit. Le silence alerterait alors dans le vide.
|
|
|
|
|
- name: Dire que personne ne recevra les alertes
|
|
|
|
|
ansible.builtin.debug:
|
|
|
|
|
msg: >-
|
|
|
|
|
`serveur_icinga_destinataire` n'est pas renseigne : les notifications iront a
|
|
|
|
|
`root@localhost`, que personne ne lit. La supervision VERRA les defauts sans
|
|
|
|
|
pouvoir les dire. Declarer l'adresse au plan.
|
|
|
|
|
when: serveur_icinga_destinataire | length == 0
|
sondes : quatorze, une par role, derivees en objets Icinga
boites (dovecot) · cache-apt (artefacts) · certificat (client_pki, 14/14)
collaboration (nextcloud) · collecte (prometheus) · file-courriel (postfix)
forge (forgejo) · identite (keycloak) · ingestion (loki) · moteur (icinga)
resolution (resolveur) · runner (serveur_ops) · tableaux (grafana)
voute (ops_tenant) — toutes vertes, sans une ligne ecrite dans Icinga.
DEUX PRINCIPES QUE LA PREMIERE SONDE A IMPOSES.
Une sonde doit pouvoir etre mise en defaut PAR PARAMETRE : cible et seuils
sont des variables du role, on prouve le rouge avec un port ferme ou un
seuil impossible, sans rien casser. Et la sonde vit LA OU VIT LA VERITE :
« ce noeud est-il collecte ? » appartient a prometheus, pas au client —
une seule y voit les N noeuds, et surtout elle voit le cas SILENCIEUX.
ON DEMANDE AU SERVICE CE QU IL PENSE DE LUI-MEME quand il sait le dire
(healthz, /ready, status.php, decouverte OIDC). Quand il ne sait pas, on
va chercher la verite de terrain : « moteur » ne regarde ni le service ni
le port, il demande a la base depuis combien de temps elle n a pas ete
rafraichie — la lecon des sauvegardes appliquee a la supervision.
QUATRE FOIS J AI ECRIT LA SONDE AVANT DE MESURER, QUATRE FOIS ELLE A EU
TORT. La forge : port et chemin des depots inventes, elle ecoute en 3000
derriere l edge et n a legitimement aucun depot. Loki : « panne
persistante » conclue sur deux lectures a quelques secondes d intervalle
juste apres un redemarrage — deux mesures rapprochees ne distinguent pas
un etat d un instant. Keycloak : vise en 8443, il ecoute en 8080. Le
runner : git en root refuse un depot d un autre proprietaire. A chaque
fois le remede est le meme — lire la verite du role, ne pas la supposer.
Et le meme piege Jinja qu avec client_sante : ${#tableau[@]} contient {#.
Le remede etait deja au depot ; je l ai reecrit au lieu de le chercher.
RESTE : client_smtp, client_artefacts, client_journal, icingaweb2 et
ops_site. Ce sont des chemins de report, dont la panne se voit deja par le
silence des sondes qu ils portent.
make prouver : CONFORME, 64 OK, 0 echec, 0 saute (P64 : 14 sondes).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-10 03:00:21 -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 « moteur »
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: sonde-moteur.sh.j2
|
|
|
|
|
dest: /usr/local/lib/setops/sondes/moteur.sh
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0750"
|