2026-06-24 20:17:46 -04:00
|
|
|
---
|
2026-08-07 09:30:48 -04:00
|
|
|
# `lock_timeout` sur CHAQUE tache apt : au premier demarrage, l'image Debian lance ses
|
|
|
|
|
# propres mises a jour (apt-daily, unattended-upgrades) et tient le verrou dpkg par
|
|
|
|
|
# vagues. Sans attente, la premiere tache echoue sur un verrou — pas sur une vraie
|
|
|
|
|
# erreur — et le deploiement d'une VM neuve devient un tirage au sort.
|
|
|
|
|
#
|
|
|
|
|
# Attendre ici plutot que seulement avant le playbook : le verrou peut etre repris
|
|
|
|
|
# ENTRE deux taches, ce qu'une verification ponctuelle en amont ne peut pas empecher.
|
proxmox : le pare-feu ne s'arme que dans le SDN — et 45e preuve
Le decoupage du site en quatre zones a revele un defaut qui dormait dans le
moteur. `firewall=1` sur l'interface d'une VM fait passer tout le trafic ponte
par conntrack. Sur un VNet SDN c'est sans consequence : en EVPN le routage
inter-VNet se fait dans le VRF, SUR LE NOEUD, et le flux ne quitte jamais
l'hyperviseur. Sur un pont classique route par une frontiere externe, deux VM du
MEME noeud dans deux VLAN differents ne se parlent qu'en EPINGLE : la trame sort
par le lien physique, la frontiere la route, elle revient sur le meme pont. La
meme table conntrack voit alors les deux moities de la connexion, classe le
retour INVALID, et PVEFW-FORWARD le jette.
La mesure a tranche :
ops(asgard) -> pki(asgard) 0/8 dns(gandalf) -> cache(gandalf) 0/8
ops(asgard) -> forge(vishnu) 6/8 dns(gandalf) -> pki(asgard) 6/8
ops(asgard) -> cache(gandalf) 8/8 dns(gandalf) -> forge(vishnu) 8/8
Toutes les paires intra-noeud echouent, toutes les paires inter-noeuds passent.
Douze tentatives faisaient monter le compteur `ctstate INVALID` de +112 sur
asgard et +116 sur gandalf ; `firewall=0` pose, il ne bouge plus — 0 sur les
deux, pour le meme trafic.
Le defaut se deguise en panne reseau : la poignee TCP ABOUTIT, et ce sont les
paquets de DONNEES qui disparaissent. L'AC le disait dans son propre journal
(`TLS handshake error ... i/o timeout` : elle accepte et attend un ClientHello
qui n'arrive jamais). Ecartes un par un, par la mesure : regles identiques champ
par champ, alias corrects, assignation des interfaces confirmee, ARP et routes
saines, IPS desactive, shaper vide, NAT source limite a `wan`, MTU a 1500 de
bout en bout — et la taille sans effet, 100 octets se perdant comme 1460.
L'INTENTION DECLAREE NE SUFFIT PAS : un tenant declare
`proxmox_clone_parefeu_interface: true` avec `proxmox_clone_pont: vmbr1` comme
valeur PAR DEFAUT, chaque hote la remplacant par son VNet derive. L'hote qui
retombe sur `vmbr1` naitrait arme sur un pont classique. `cloner_vm_debian.yml`
croise donc l'intention avec le pont REELLEMENT utilise, et le dit quand il
desarme — un desarmement muet serait le meme piege, en silence.
P45 EVALUE l'expression du playbook sur quatre cas plutot que d'en lire le
texte, dont un qui DOIT rendre vrai : sans lui, une expression constamment
fausse passerait la preuve sans rien garantir. Controle negatif verifie — le
drapeau remis a plat fait echouer la preuve.
Ce commit emporte aussi le desarmement d'`unattended-upgrades` dans
`common_packages`, jusqu'ici applique sur les machines mais pas versionne : le
verrou dpkg tenu 48 minutes par une vague de maj automatiques a coute deux
deploiements.
Le site a revele ce defaut parce qu'il a ete le premier a porter plusieurs
zones. Ce n'est pas une particularite du site : un tenant derive les siennes du
meme principe.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 19:50:53 -04:00
|
|
|
# DÉSARMER AVANT TOUTE OPÉRATION APT, ET NON APRÈS.
|
|
|
|
|
#
|
|
|
|
|
# Une tâche apt placée avant celle-ci attendrait le verrou que celle-ci doit justement
|
|
|
|
|
# libérer — l'ordre n'est pas cosmétique. `state: stopped` en plus de `masked` : masquer
|
|
|
|
|
# empêche un démarrage futur, pas celui qui est déjà en cours.
|
|
|
|
|
- name: Désarmer les mises à jour automatiques de Debian (Set-OPS les applique lui-même)
|
|
|
|
|
ansible.builtin.systemd_service:
|
|
|
|
|
name: "{{ item }}"
|
|
|
|
|
state: stopped
|
|
|
|
|
enabled: false
|
|
|
|
|
masked: true
|
|
|
|
|
loop: "{{ common_packages_unites_maj_auto }}"
|
|
|
|
|
when: common_packages_desarmer_maj_auto | bool
|
|
|
|
|
failed_when: false # une unite absente n'est pas une faute : elle est desarmee
|
|
|
|
|
|
audit + timers : deux services en echec sur les quinze machines, muets depuis toujours
`make prouver` disait 15/15 a failed=0. Les machines, elles, portaient chacune trois
unites systemd en echec. Le rapport d Ansible n est pas l etat d une machine.
AUDITD : ONZE REGLES ARMEES, PERSONNE POUR COLLECTER.
Deux fichiers de regles identiques cohabitaient — 99-chezlepro.rules et
99-setops.rules, vestige du renommage du role. augenrules CONCATENE rules.d/ :
Error sending add rule data request (Rule exists)
There was an error in line 16 of /etc/audit/audit.rules
audit-rules echoue, et auditd ne demarre pas — c est sa dependance. Resultat :
auditctl -l affiche onze regles, ce qui donne toutes les apparences d un audit qui
fonctionne, et rien ne les enregistre.
Meme mue que ssh_baseline, meme registre : auditd_fichiers_perimes. On n y ajoute
que des noms qu on a REELLEMENT deposes un jour.
Et `failed_when: false` cachait la panne : quinze machines a failed=0 avec auditd
mort sur les quinze. Un service de securite qui ne demarre pas doit se VOIR.
TIMERS APT-DAILY : UN ETAT D ECHEC RESIDUEL.
Masquer le service pendant que son timer tourne lui fait perdre sa cible ; systemd
le note et le GARDE (Unit to trigger vanished). `state: stopped` n efface pas un
etat failed — seul reset-failed le fait.
Ce n est pas cosmetique : une supervision qui compte les unites en echec compte ces
deux-la pour toujours, et la vraie panne s y noiera. Meme defaut que le journal de
la frontiere noye sous 982 000 entrees.
DIAGNOSTIC FAUX, CORRIGE : j avais lu « masked enabled » dans list-unit-files comme
un etat contradictoire, et construit une reparation pour le defaire. Ces colonnes
sont ETAT puis PRESET — masque avec un prereglage constructeur active est normal.
La reparation a ete annulee avant d etre livree.
make verifier : vert. make prouver : CONFORME, 55 OK, 0 echec, 0 saute.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-08-31 16:16:13 -04:00
|
|
|
# EFFACER LA TRACE QUE LE DESARMEMENT LAISSE (mesure du 2026-08-30).
|
|
|
|
|
#
|
|
|
|
|
# Masquer le service pendant que son timer TOURNE lui fait perdre sa cible. systemd le
|
|
|
|
|
# note, et le garde :
|
|
|
|
|
#
|
|
|
|
|
# apt-daily.timer: Unit to trigger vanished.
|
|
|
|
|
# apt-daily.timer: Failed with result 'resources'.
|
|
|
|
|
#
|
|
|
|
|
# `state: stopped` n'efface pas un etat `failed` — seul `reset-failed` le fait. Sans lui,
|
|
|
|
|
# CHAQUE machine porte deux unites en echec permanent. Constate sur les quinze de
|
|
|
|
|
# Chezlepro : `systemctl list-units --state=failed` en rend deux partout.
|
|
|
|
|
#
|
|
|
|
|
# CE N'EST PAS COSMETIQUE. Une supervision qui compte les unites en echec compte ces
|
|
|
|
|
# deux-la pour toujours — et le jour ou une VRAIE panne s'ajoute, elle se noie dans un
|
|
|
|
|
# bruit qu'on a appris a ignorer. C'est le meme defaut que le journal de la frontiere
|
|
|
|
|
# noye sous 982 000 entrees : ce qui ment le plus n'est pas ce qui se tait, c'est ce qui
|
|
|
|
|
# crie sans raison.
|
|
|
|
|
- name: Effacer l'etat d'echec laisse par le desarmement
|
|
|
|
|
ansible.builtin.command:
|
|
|
|
|
argv: ["systemctl", "reset-failed", "{{ item }}"]
|
|
|
|
|
loop: "{{ common_packages_unites_maj_auto }}"
|
|
|
|
|
register: common_packages_reset
|
|
|
|
|
changed_when: false
|
|
|
|
|
failed_when: false # rien a effacer n'est pas une faute
|
|
|
|
|
when: common_packages_desarmer_maj_auto | bool
|
|
|
|
|
|
les correctifs de securite reviennent au quotidien, sans personne
Decision de l exploitant, et elle corrige un mauvais jugement de ma part :
j avais decrit la situation correctement — la seule operation de la flotte
qui exige un humain — puis propose un minuteur maison plutot que le mecanisme
que Debian fournit exactement pour ca.
Le desarmement d aout avait un motif reel (48 minutes de verrou dpkg apres un
rattrapage) mais une contrepartie ecrite sans etre mesuree. Ce qui rend la
coexistence tenable existe maintenant : _attendre-hote attend apt-daily et le
verrou, lock_timeout est pose partout, unattended-upgrades ne traite que
l origine -security, et Automatic-Reboot reste false.
Rearmer ne se deduit pas de ne plus desarmer : passer le drapeau a false
saute la tache, il ne demasque rien. Une tache de rearmement explicite est
donc posee le jour meme ou la decision s inverse.
ET LA PREMIERE VERSION A REJOUE LA COURSE. state: started sur les trois
unites lance le rattrapage en plein deploiement : dix machines sur vingt et
une, avec l erreur meme qui avait motive le masquage. Le travail quotidien ne
passe pas par ce service — le timer appelle apt.systemd.daily directement. On
ARME sans declencher : les minuteurs demarres, le service seulement active.
21 machines, minuteurs armes, prochain passage demain vers 06h, zero unite en
echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-11 19:02:10 -04:00
|
|
|
# REARMER NE SE DEDUIT PAS DE NE PLUS DESARMER (2026-09-11).
|
|
|
|
|
#
|
|
|
|
|
# Passer `common_packages_desarmer_maj_auto` a `false` SAUTE la tache de desarmement —
|
|
|
|
|
# il ne defait rien. Une machine deja masquee le resterait pour toujours, et le drapeau
|
|
|
|
|
# dirait le contraire de l'etat reel. Le desarmement laisse une trace ; il faut donc une
|
|
|
|
|
# tache qui la retire, et elle doit exister le jour meme ou l'on inverse la decision.
|
|
|
|
|
#
|
|
|
|
|
# L'ORDRE COMPTE, COMME POUR LE DESARMEMENT : on reamorce AVANT les operations apt de ce
|
|
|
|
|
# role. Un demarrage d'`apt-daily` declenche pendant nos propres taches se disputerait le
|
|
|
|
|
# verrou au pire moment ; declenche avant, il est attendu par `lock_timeout`.
|
|
|
|
|
# ON ARME, ON NE DECLENCHE PAS — ET LA NUANCE A COUTE DIX MACHINES (2026-09-11).
|
|
|
|
|
#
|
|
|
|
|
# La premiere version faisait `state: started` sur les trois unites. Demarrer
|
|
|
|
|
# `unattended-upgrades.service` apres des semaines de masquage lance son RATTRAPAGE
|
|
|
|
|
# immediatement — en plein deploiement. Il a pris le verrou dpkg et l'a garde plus
|
|
|
|
|
# longtemps que `lock_timeout` (300 s) :
|
|
|
|
|
#
|
|
|
|
|
# 'apt-get autoremove' failed: E: Could not get lock /var/lib/dpkg/lock-frontend.
|
|
|
|
|
# It is held by process 185135 (unattended-upgr)
|
|
|
|
|
#
|
|
|
|
|
# Exactement la course qui avait motive le desarmement en aout, rejouee par la tache
|
|
|
|
|
# censee le defaire. Dix machines sur vingt et une.
|
|
|
|
|
#
|
|
|
|
|
# LE TRAVAIL QUOTIDIEN NE PASSE PAS PAR CE SERVICE : `apt-daily-upgrade.timer` appelle
|
|
|
|
|
# `apt.systemd.daily`, qui invoque `unattended-upgrade` lui-meme. Le `.service` ne sert
|
|
|
|
|
# qu'aux passages de demarrage et d'extinction. L'ACTIVER suffit donc — il partira au
|
|
|
|
|
# prochain redemarrage, sur une machine au repos, et non pendant qu'Ansible tient apt.
|
|
|
|
|
#
|
|
|
|
|
# Demarrer les MINUTEURS, en revanche, est sans danger : armer un minuteur ne declenche
|
|
|
|
|
# pas sa cible, il la programme.
|
|
|
|
|
- name: Réarmer les mises à jour automatiques de Debian (sans les déclencher)
|
|
|
|
|
ansible.builtin.systemd_service:
|
|
|
|
|
name: "{{ item }}"
|
|
|
|
|
masked: false
|
|
|
|
|
enabled: true
|
|
|
|
|
state: "{{ 'started' if item.endswith('.timer') else omit }}"
|
|
|
|
|
loop: "{{ common_packages_unites_maj_auto }}"
|
|
|
|
|
when: not (common_packages_desarmer_maj_auto | bool)
|
|
|
|
|
failed_when: false # une unite absente sur cette image n'est pas une faute
|
|
|
|
|
|
2026-06-24 20:17:46 -04:00
|
|
|
- name: Mettre à jour le cache APT
|
|
|
|
|
ansible.builtin.apt:
|
|
|
|
|
update_cache: true
|
|
|
|
|
cache_valid_time: 3600
|
2026-08-07 09:30:48 -04:00
|
|
|
lock_timeout: "{{ common_packages_lock_timeout }}"
|
2026-06-24 20:17:46 -04:00
|
|
|
|
|
|
|
|
- name: Appliquer les mises à jour disponibles
|
|
|
|
|
ansible.builtin.apt:
|
|
|
|
|
upgrade: full
|
2026-08-07 09:30:48 -04:00
|
|
|
lock_timeout: "{{ common_packages_lock_timeout }}"
|
2026-06-24 20:17:46 -04:00
|
|
|
|
|
|
|
|
- name: Installer les paquets communs
|
|
|
|
|
ansible.builtin.apt:
|
|
|
|
|
name: "{{ common_packages_list }}"
|
|
|
|
|
state: present
|
2026-08-07 09:30:48 -04:00
|
|
|
lock_timeout: "{{ common_packages_lock_timeout }}"
|
2026-06-24 20:17:46 -04:00
|
|
|
|
|
|
|
|
- name: Supprimer les dépendances devenues inutiles
|
|
|
|
|
ansible.builtin.apt:
|
|
|
|
|
autoremove: true
|
2026-08-07 09:30:48 -04:00
|
|
|
lock_timeout: "{{ common_packages_lock_timeout }}"
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
# LA SONDE SE DEPOSE ICI, ELLE SE DECLARE AILLEURS (`roles/serveur_debian/meta/`).
|
|
|
|
|
# Ce role est celui qui APPLIQUE les mises a jour ; il est donc le bon porteur. Mais la
|
|
|
|
|
# derivation des services d'Icinga croise les GROUPES, et `common_packages` n'en est pas
|
|
|
|
|
# un — d'ou la separation, expliquee dans la declaration.
|
|
|
|
|
- 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: Assurer le repertoire d etat des sondes
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: /var/lib/setops
|
|
|
|
|
state: directory
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0750"
|
|
|
|
|
|
|
|
|
|
- name: Deposer la sonde des correctifs de securite
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: sonde-correctifs.sh.j2
|
|
|
|
|
dest: /usr/local/lib/setops/sondes/correctifs.sh
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0750"
|