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
264 lines
10 KiB
YAML
264 lines
10 KiB
YAML
---
|
|
- 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 (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
|
|
|
|
# ... 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
|
|
when: not (telecharger_la_cle_de_signature_grafana_present.stat.exists and telecharger_la_cle_de_signature_grafana_present.stat.size | default(0) > 0)
|
|
ansible.builtin.get_url:
|
|
url: "{{ serveur_loki_depot_cle_url }}"
|
|
dest: "{{ serveur_loki_depot_cle_fichier }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
# 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: ""
|
|
|
|
# `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_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
|
|
|
|
# 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:
|
|
# 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
|
|
|
|
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
|
|
|
|
# --- 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"
|