2026-08-23 14:41:56 -04:00
|
|
|
---
|
|
|
|
|
# LE CACHE NE DOIT PAS DÉPENDRE DE LUI-MÊME POUR SE RÉPARER.
|
|
|
|
|
#
|
|
|
|
|
# La première version faisait `update_cache: true` à chaque passage. Sur l'hôte qui PORTE
|
|
|
|
|
# le cache, cet `apt update` passe par le cache lui-même — et en mode hors ligne, il est
|
|
|
|
|
# refusé. Le rôle qui devait remettre le service en ligne ne pouvait donc plus s'exécuter :
|
|
|
|
|
#
|
|
|
|
|
# « Failed to update apt cache after 5 retries » (mesuré le 2026-08-23, après
|
|
|
|
|
# l'épreuve hors ligne : il a fallu réparer la machine à la main)
|
|
|
|
|
#
|
|
|
|
|
# Un service dont la remise en route exige qu'il fonctionne déjà est un piège. On ne
|
|
|
|
|
# rafraîchit donc l'index qu'à la PREMIÈRE installation, quand aucun cache n'existe encore
|
|
|
|
|
# et qu'`apt` va forcément à l'amont.
|
|
|
|
|
- name: Le cache est-il déjà installé ?
|
|
|
|
|
ansible.builtin.stat:
|
|
|
|
|
path: /usr/sbin/apt-cacher-ng
|
|
|
|
|
register: serveur_artefacts_present
|
|
|
|
|
|
|
|
|
|
- name: Installer le cache d'artefacts
|
|
|
|
|
ansible.builtin.apt:
|
|
|
|
|
name: "{{ serveur_artefacts_paquets }}"
|
|
|
|
|
state: present
|
|
|
|
|
update_cache: "{{ not serveur_artefacts_present.stat.exists }}"
|
|
|
|
|
when: not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
- name: Assurer le répertoire de cache
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: "{{ serveur_artefacts_cache }}"
|
|
|
|
|
state: directory
|
|
|
|
|
owner: apt-cacher-ng
|
|
|
|
|
group: apt-cacher-ng
|
|
|
|
|
mode: "0755"
|
|
|
|
|
when: not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
# apt-cacher-ng lit TOUS les `*.conf` de son répertoire, par ordre alphabétique, et le
|
|
|
|
|
# dernier lu gagne. Le préfixe `zzz-` place donc notre configuration après celle du
|
|
|
|
|
# paquet Debian et celle de debconf, sans avoir à les éditer — on ajoute, on ne remplace
|
|
|
|
|
# pas. Une valeur posée ici l'emporte, et `apt purge` rend la machine à son état d'origine.
|
artefacts : deux filets — un cache mort ne doit plus rendre un tenant irreparable
CE CACHE EST UN MAILLON DONT DEPEND SA PROPRE RECONSTRUCTION. Toute la flotte y
prend ses paquets. S il pointe vers un amont mort, apt echoue sur les quinze
machines, donc le socle echoue, donc le deploiement n atteint jamais la couche qui
poserait le bon amont. LE CORRECTIF SE RETROUVE DANS LA COUCHE QUE LA PANNE EMPECHE
D ATTEINDRE, et il faut une main pour en sortir.
C est arrive le 2026-08-31 : l amont pointait sur le cache de patient 0, eteint la
veille pour liberer de la RAM. apt rendait « 503 Connection timeout » EN CITANT
L ADRESSE DU CACHE LOCAL, jamais celle de l amont manquant — la panne accusait le
maillon visible.
DEUX FILETS, SYMETRIQUES.
serveur_artefacts sonde l amont AVANT d ecrire, et refuse s il est muet : mieux
vaut un cache qui garde sa configuration precedente qu un cache qu on vient de
rendre inutilisable pour toute la flotte.
client_artefacts sonde la source AVANT de detourner apt vers elle. Ce fichier
ECRASE le plancher d amorcage pose par le socle — le poser sur un cache mort prive
la machine du cache du SITE, qui lui fonctionnait. En refusant, le plancher reste :
la flotte est degradee mais debout, et REPARABLE PAR UN DEPLOIEMENT.
`ignore_errors` ET NON `failed_when: false` — la difference est toute la garde.
failed_when: false REECRIT le verdict : la tache n est plus jamais failed, donc
`is not failed` est toujours vrai, donc l assertion ne peut pas tirer. Ecrite ainsi,
ma premiere version a declare « joignable » un amont mesure MUET la seconde d avant.
Une garde qui ne peut pas echouer ne garde rien.
Deux controles verifies sur la machine : amont eteint -> refuse ; amont reel -> pose.
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 18:31:21 -04:00
|
|
|
# --- LE FILET : NE PAS POSER UN AMONT INJOIGNABLE ----------------------------
|
|
|
|
|
#
|
|
|
|
|
# CE CACHE EST UN MAILLON DONT DEPEND SA PROPRE RECONSTRUCTION (mesure du 2026-08-31).
|
|
|
|
|
#
|
|
|
|
|
# Toute la flotte du tenant prend ses paquets ici. Si ce cache pointe vers un amont mort,
|
|
|
|
|
# `apt` echoue sur les QUINZE machines — donc le socle echoue, donc le deploiement
|
|
|
|
|
# n'atteint jamais la couche qui poserait le bon amont. Le correctif se retrouve dans la
|
|
|
|
|
# couche que la panne empeche d'atteindre, et il faut une main pour en sortir.
|
|
|
|
|
#
|
2026-09-27 21:53:36 -04:00
|
|
|
# C'est exactement ce qui est arrive : l'amont pointait sur le cache d'un autre ecosysteme, eteint
|
artefacts : deux filets — un cache mort ne doit plus rendre un tenant irreparable
CE CACHE EST UN MAILLON DONT DEPEND SA PROPRE RECONSTRUCTION. Toute la flotte y
prend ses paquets. S il pointe vers un amont mort, apt echoue sur les quinze
machines, donc le socle echoue, donc le deploiement n atteint jamais la couche qui
poserait le bon amont. LE CORRECTIF SE RETROUVE DANS LA COUCHE QUE LA PANNE EMPECHE
D ATTEINDRE, et il faut une main pour en sortir.
C est arrive le 2026-08-31 : l amont pointait sur le cache de patient 0, eteint la
veille pour liberer de la RAM. apt rendait « 503 Connection timeout » EN CITANT
L ADRESSE DU CACHE LOCAL, jamais celle de l amont manquant — la panne accusait le
maillon visible.
DEUX FILETS, SYMETRIQUES.
serveur_artefacts sonde l amont AVANT d ecrire, et refuse s il est muet : mieux
vaut un cache qui garde sa configuration precedente qu un cache qu on vient de
rendre inutilisable pour toute la flotte.
client_artefacts sonde la source AVANT de detourner apt vers elle. Ce fichier
ECRASE le plancher d amorcage pose par le socle — le poser sur un cache mort prive
la machine du cache du SITE, qui lui fonctionnait. En refusant, le plancher reste :
la flotte est degradee mais debout, et REPARABLE PAR UN DEPLOIEMENT.
`ignore_errors` ET NON `failed_when: false` — la difference est toute la garde.
failed_when: false REECRIT le verdict : la tache n est plus jamais failed, donc
`is not failed` est toujours vrai, donc l assertion ne peut pas tirer. Ecrite ainsi,
ma premiere version a declare « joignable » un amont mesure MUET la seconde d avant.
Une garde qui ne peut pas echouer ne garde rien.
Deux controles verifies sur la machine : amont eteint -> refuse ; amont reel -> pose.
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 18:31:21 -04:00
|
|
|
# la veille pour liberer de la RAM. `apt` rendait `503 Connection timeout` EN CITANT
|
|
|
|
|
# L'ADRESSE DU CACHE LOCAL, jamais celle de l'amont manquant — la panne accusait le
|
|
|
|
|
# maillon visible.
|
|
|
|
|
#
|
|
|
|
|
# On mesure donc AVANT d'ecrire. Un amont injoignable est refuse : mieux vaut un cache
|
|
|
|
|
# qui garde sa configuration precedente et un message clair, qu'un cache qu'on vient de
|
|
|
|
|
# rendre inutilisable pour toute la flotte.
|
|
|
|
|
- name: L'amont declare repond-il ?
|
|
|
|
|
ansible.builtin.wait_for:
|
|
|
|
|
host: "{{ serveur_artefacts_amont | urlsplit('hostname') }}"
|
|
|
|
|
port: "{{ serveur_artefacts_amont | urlsplit('port') | default(3142, true) | int }}"
|
|
|
|
|
timeout: 10
|
|
|
|
|
register: serveur_artefacts_amont_sonde
|
|
|
|
|
changed_when: false
|
|
|
|
|
# `ignore_errors` ET NON `failed_when: false` — LA DIFFERENCE EST TOUTE LA GARDE.
|
|
|
|
|
#
|
|
|
|
|
# `failed_when: false` REECRIT le verdict : la tache n'est plus jamais `failed`, donc
|
|
|
|
|
# `is not failed` est toujours vrai, donc l'assertion qui suit ne peut PAS tirer. Ecrite
|
|
|
|
|
# ainsi, elle a declare « joignable » un amont mesure MUET la seconde d'avant
|
|
|
|
|
# (2026-08-31). Une garde qui ne peut pas echouer ne garde rien.
|
|
|
|
|
#
|
|
|
|
|
# `ignore_errors` laisse le verdict intact et se contente de ne pas arreter le play :
|
|
|
|
|
# c'est ce qu'il faut pour SONDER puis DECIDER.
|
|
|
|
|
ignore_errors: true
|
|
|
|
|
when:
|
|
|
|
|
- serveur_artefacts_amont | length > 0
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
- name: Refuser un amont injoignable plutot que de rendre ce cache inutilisable
|
|
|
|
|
ansible.builtin.assert:
|
|
|
|
|
that:
|
|
|
|
|
- serveur_artefacts_amont_sonde is not failed
|
|
|
|
|
fail_msg: >-
|
|
|
|
|
L'amont declare ({{ serveur_artefacts_amont }}) ne repond pas. Le poser rendrait ce
|
|
|
|
|
cache — et donc `apt` sur TOUTE la flotte de cet ecosysteme — inutilisable, et le
|
|
|
|
|
deploiement ne pourrait plus atteindre la couche qui le corrigerait.
|
|
|
|
|
Verifier que la machine d'amont tourne, ou vider `serveur_artefacts_amont` pour
|
|
|
|
|
aller directement chez Debian (c'est une emancipation : voir
|
|
|
|
|
docs/filiation-emancipation.md).
|
|
|
|
|
success_msg: "Amont {{ serveur_artefacts_amont }} joignable."
|
|
|
|
|
when:
|
|
|
|
|
- serveur_artefacts_amont | length > 0
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
|
depot de binaires : le site tient ce que les runners allaient chercher
Le cache du site couvrait apt ; quatre artefacts arrivaient autrement, parce qu ils
ne vivent dans aucun depot apt. Le controleur les tire puis les pousse par SSH.
Mesure du 2026-09-12 : le cache du runner du site est ABSENT. Un second locataire
monte depuis lui sortait chercher 570 Mo sur codeberg.org, github.com et
download.nextcloud.com, alors que le meme ecosysteme ne demandait plus un seul
paquet a Debian. Le poste du mainteneur les a depuis toujours : personne ne l avait vu.
Pas de relais transparent, et la mesure tranche : github.com redirige vers une URL
signee valable une heure, differente a chaque requete. Un cache qui la prend pour
cle ne fait jamais mouche. Le relais marcherait pour deux amonts sur quatre.
Donc un vrai depot, dans le service qui existe deja. LocalDirs d apt-cacher-ng publie
un repertoire du disque sous un prefixe, eprouve AVANT d ecrire le role. Aucun service,
aucun port, aucun certificat, aucun flux nouveaux : l ingress 3142 pair flotte couvre
exactement ce chemin.
Les versions ne sont pas recopiees : le role lit les defauts des quatre consommateurs.
Les quatre roles recoivent une tache AJOUTEE, placee avant leur stat de cache — si le
depot sert, le stat le voit et la tache amont se saute d elle-meme. Aucune tache
existante n a change.
P70 exige que tout dest ecrit sous un cache_local figure au depot. Une liste qui suit
une autre prend du retard ; celle-ci est nee avec sa garde.
Deux marches payees en chemin :
- failed_when: false REECRIT le verdict, donc la premiere garde de signature ne
gardait rien. Elles mesurent le fichier desormais.
- file: state=directory cree les parents en 0750 : apt-cacher-ng, qui ne tourne pas
en root, rendait 403 sur chaque fichier. Un chemin se traverse en entier.
Verifie sur l infrastructure : 6/6 artefacts servis (200/206) depuis le runner du site
ET depuis une machine du locataire a travers la frontiere ; les 6 empreintes SHA-256
sont identiques a celles qui ont construit Chezlepro ; second passage changed=0.
make prouver : 69 OK, 0 echec, 1 saute. ansible-lint : 0 failure, profil production.
Inclut aussi force: true sur cinq telechargements de cles : une reprise conditionnelle
ne reprend rien (304 Not Modified, size 0, attempts 5).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-12 23:45:00 -04:00
|
|
|
# LE REPERTOIRE AVANT LA DIRECTIVE QUI LE PUBLIE. `LocalDirs` pointant sur un chemin
|
|
|
|
|
# absent, apt-cacher-ng ne refuse pas de demarrer : il rend 503 sur ce prefixe, et le
|
|
|
|
|
# message parle de « File or directory not found » — ce qui accuse le fichier demande,
|
|
|
|
|
# pas la racine manquante.
|
|
|
|
|
# LE PARENT AUSSI, ET C'EST LUI QUI A MORDU (mesure du 2026-09-12).
|
|
|
|
|
#
|
|
|
|
|
# `file: state=directory` cree les parents manquants avec les droits par defaut — ici
|
|
|
|
|
# `0750 root:root`. apt-cacher-ng ne tourne PAS en root : il n'a pas pu traverser
|
|
|
|
|
# `/var/lib/setops` et rendait 403 sur chaque fichier du depot, alors que le repertoire
|
|
|
|
|
# final etait bien en 0755 et les fichiers bien la.
|
|
|
|
|
#
|
|
|
|
|
# 403 ACCUSE LE FICHIER DEMANDE, pas le repertoire qui le contient — et encore moins le
|
|
|
|
|
# GRAND-PARENT. On a donc cherche du cote des motifs de fichiers d'apt-cacher-ng, qui
|
|
|
|
|
# n'y etaient pour rien. Un chemin se traverse en entier ; un droit se verifie de meme.
|
|
|
|
|
- name: Assurer la racine d'état de Set-OPS, traversable par les services
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: "{{ serveur_artefacts_directs_dir | dirname }}"
|
|
|
|
|
state: directory
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0755"
|
|
|
|
|
when: serveur_artefacts_directs_actif | bool
|
|
|
|
|
|
|
|
|
|
- name: Assurer le répertoire du dépôt de binaires directs
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: "{{ serveur_artefacts_directs_dir }}"
|
|
|
|
|
state: directory
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0755"
|
|
|
|
|
when: serveur_artefacts_directs_actif | bool
|
|
|
|
|
|
2026-08-23 14:41:56 -04:00
|
|
|
- name: Déployer la configuration Set-OPS
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: zzz-setops.conf.j2
|
|
|
|
|
dest: /etc/apt-cacher-ng/zzz-setops.conf
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0644"
|
|
|
|
|
notify: Redémarrer le cache d'artefacts
|
|
|
|
|
|
|
|
|
|
- name: Activer et démarrer le cache d'artefacts
|
|
|
|
|
ansible.builtin.systemd:
|
|
|
|
|
name: "{{ serveur_artefacts_service }}"
|
|
|
|
|
enabled: true
|
|
|
|
|
state: started
|
|
|
|
|
when: not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
- name: Appliquer les redémarrages avant de vérifier
|
|
|
|
|
ansible.builtin.meta: flush_handlers
|
|
|
|
|
|
|
|
|
|
# ÉCRIRE, PUIS RELIRE (D-68). Un service « active » qui n'écoute pas sur le port attendu
|
|
|
|
|
# est un vert sur un périmètre vide : les clients le découvriraient à leur premier
|
|
|
|
|
# `apt update`, c'est-à-dire au pire moment.
|
|
|
|
|
- name: Le cache écoute-t-il vraiment ?
|
|
|
|
|
ansible.builtin.wait_for:
|
|
|
|
|
host: "127.0.0.1"
|
|
|
|
|
port: "{{ serveur_artefacts_port }}"
|
|
|
|
|
timeout: 30
|
|
|
|
|
when: not ansible_check_mode
|
sondes : les six premieres, et le patron qui les rend eprouvables
Ajout de meta/supervision.yml a six roles, chacun deposant sa propre sonde
selon le contrat des greffons Nagios.
DEUX PRINCIPES POSES AU DOCUMENT DE CONCEPTION, parce que la premiere
sonde les a imposes :
1. UNE SONDE DOIT POUVOIR ETRE MISE EN DEFAUT PAR PARAMETRE. Cible et
seuils sont des variables du role : on la prouve rouge avec un port ferme
ou un seuil impossible, sur une machine reelle, sans rien casser, et
aussi souvent qu on veut. Une sonde qu on ne peut prouver qu en cassant un
service ne sera prouvee qu une fois.
2. LA SONDE VIT LA OU VIT LA VERITE. « Ce noeud est-il collecte ? » est
une sonde de serveur_prometheus, pas de client_metrique : une seule y voit
les N noeuds, et surtout elle voit le cas SILENCIEUX — celui qui a cesse d
etre collecte ne peut pas s en plaindre.
LES SIX : cache-apt (artefacts, repond + place), resolution (resolveur,
zone interne ET Internet — deux chemins distincts), forge (forgejo, son
propre /api/healthz), collecte (prometheus, 15/15 cibles), tableaux
(grafana, base ok), ingestion (loki, PRET a ingerer, pas seulement en
ecoute).
TROIS FOIS J AI ECRIT LA SONDE AVANT DE MESURER, ET TROIS FOIS ELLE A EU
TORT. La forge : port 443 et chemin des depots INVENTES — elle ecoute en
3000 derriere l edge et n a legitimement aucun depot. Loki : j ai conclu
« panne persistante » sur deux lectures prises a quelques secondes d
intervalle, juste apres un redemarrage ; l anneau etait ACTIVE et la
reponse est passee a ready moins d une minute plus tard. Le delai de
stabilisation est desormais un AVERTISSEMENT nomme, pas une panne.
On demande au service ce qu il pense de lui-meme quand il sait le dire
(healthz, /ready, /api/health) plutot que d inventer un critere de l
exterieur.
make prouver : CONFORME.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-10 02:48:55 -04:00
|
|
|
|
|
|
|
|
# --- Sonde de supervision (docs/supervision-conception.md) --------------------------
|
|
|
|
|
# Le role qui possede la verite depose sa propre sonde ; le porteur (`client_sante`) la
|
|
|
|
|
# fait tourner et pousse le verdict, sans savoir ce qu'elle mesure.
|
|
|
|
|
- name: Assurer le repertoire des sondes de supervision
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: /usr/local/lib/setops/sondes
|
|
|
|
|
state: directory
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0755"
|
|
|
|
|
|
|
|
|
|
- name: Deposer la sonde « cache-apt »
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: sonde-cache-apt.sh.j2
|
|
|
|
|
dest: /usr/local/lib/setops/sondes/cache-apt.sh
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0750"
|
cache-apt scindee — et la scission a revele que moteur aurait alarme a tort
LA SCISSION. cache-apt fondait deux causes aux DELAIS differents : « ne
repond pas » arrete tout apt de l ecosysteme, on agit dans la minute ;
« volume a 90 % » est un billet pour demain. Les fondre obligeait soit a
reveiller quelqu un pour un disque, soit a traiter une panne comme un
billet. Deux sondes, chacune avec son etat, son historique, son
acquittement — et prouvees INDEPENDANTES :
port ferme -> cache-apt CRITIQUE, cache-apt-volume OK
seuil impossible -> cache-apt OK, cache-apt-volume AVERTISSEMENT
CE QUE LA VERIFICATION A REVELE. Un resultat pousse et accepte (code 200)
n apparaissait pas en base. Hypothese testee et confirmee : IcingaDB n
ECRIT service_state QUE SUR CHANGEMENT D ETAT. Un OK identique repete ne
produit aucune ecriture ; un AVERTISSEMENT pousse ensuite est ecrit en 13 s.
Or la sonde moteur, ecrite quelques heures plus tot, lisait exactement
max(last_update) de service_state pour juger de la fraicheur. Elle
mesurait le CHANGEMENT. Sur un ecosysteme parfaitement STABLE — celui
qu on veut — plus rien ne change, last_update vieillit, et elle serait
passee en avertissement a 15 min puis en critique a 90. Une alarme qui se
declenche PARCE QUE tout va bien, avec un delai qui l aurait rendue
difficile a rattacher a sa cause.
La bonne source existait : icingadb_instance porte le battement du
synchroniseur, ecrit en continu. Releve a 1 s sur un systeme sain. Seuils
ramenes de 15/90 min a 1/5 min. Controle negatif rejoue.
Dix-huit services, tous verts sauf sauvegarde 7/9 (deja connu).
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-10 03:27:52 -04:00
|
|
|
|
|
|
|
|
- name: Deposer la sonde « cache-apt-volume »
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: sonde-cache-apt-volume.sh.j2
|
|
|
|
|
dest: /usr/local/lib/setops/sondes/cache-apt-volume.sh
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0750"
|
depot de binaires : le site tient ce que les runners allaient chercher
Le cache du site couvrait apt ; quatre artefacts arrivaient autrement, parce qu ils
ne vivent dans aucun depot apt. Le controleur les tire puis les pousse par SSH.
Mesure du 2026-09-12 : le cache du runner du site est ABSENT. Un second locataire
monte depuis lui sortait chercher 570 Mo sur codeberg.org, github.com et
download.nextcloud.com, alors que le meme ecosysteme ne demandait plus un seul
paquet a Debian. Le poste du mainteneur les a depuis toujours : personne ne l avait vu.
Pas de relais transparent, et la mesure tranche : github.com redirige vers une URL
signee valable une heure, differente a chaque requete. Un cache qui la prend pour
cle ne fait jamais mouche. Le relais marcherait pour deux amonts sur quatre.
Donc un vrai depot, dans le service qui existe deja. LocalDirs d apt-cacher-ng publie
un repertoire du disque sous un prefixe, eprouve AVANT d ecrire le role. Aucun service,
aucun port, aucun certificat, aucun flux nouveaux : l ingress 3142 pair flotte couvre
exactement ce chemin.
Les versions ne sont pas recopiees : le role lit les defauts des quatre consommateurs.
Les quatre roles recoivent une tache AJOUTEE, placee avant leur stat de cache — si le
depot sert, le stat le voit et la tache amont se saute d elle-meme. Aucune tache
existante n a change.
P70 exige que tout dest ecrit sous un cache_local figure au depot. Une liste qui suit
une autre prend du retard ; celle-ci est nee avec sa garde.
Deux marches payees en chemin :
- failed_when: false REECRIT le verdict, donc la premiere garde de signature ne
gardait rien. Elles mesurent le fichier desormais.
- file: state=directory cree les parents en 0750 : apt-cacher-ng, qui ne tourne pas
en root, rendait 403 sur chaque fichier. Un chemin se traverse en entier.
Verifie sur l infrastructure : 6/6 artefacts servis (200/206) depuis le runner du site
ET depuis une machine du locataire a travers la frontiere ; les 6 empreintes SHA-256
sont identiques a celles qui ont construit Chezlepro ; second passage changed=0.
make prouver : 69 OK, 0 echec, 1 saute. ansible-lint : 0 failure, profil production.
Inclut aussi force: true sur cinq telechargements de cles : une reprise conditionnelle
ne reprend rien (304 Not Modified, size 0, attempts 5).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-12 23:45:00 -04:00
|
|
|
|
|
|
|
|
# --- REMPLIR LE DEPOT DE BINAIRES DIRECTS --------------------------------------------
|
|
|
|
|
#
|
|
|
|
|
# CETTE MACHINE EST LA SEULE A SORTIR, et c'est le meme principe que pour apt : un seul
|
|
|
|
|
# telechargement pour tout le site, y compris pour les ecosystemes qui naitront demain.
|
|
|
|
|
#
|
|
|
|
|
# ON LIT LES DEFAUTS DES ROLES CONSOMMATEURS, on ne recopie pas leurs versions. Sans ca,
|
|
|
|
|
# la version vivrait a deux endroits et le depot finirait par servir, en silence, un
|
|
|
|
|
# artefact que plus personne ne demande.
|
|
|
|
|
#
|
|
|
|
|
# `include_vars` SANS `name:` — DELIBEREMENT. Enfermees dans un dictionnaire, les valeurs
|
|
|
|
|
# qui se citent entre elles ne se resolvent plus : `serveur_forgejo_url` reference
|
|
|
|
|
# `serveur_forgejo_version`. Le depot connait deja cette marche, payee sur le devis des
|
|
|
|
|
# certificats ; on ne la repaye pas.
|
|
|
|
|
- name: Lire ce que les rôles consommateurs déclarent télécharger
|
|
|
|
|
ansible.builtin.include_vars:
|
|
|
|
|
dir: "{{ role_path }}/../{{ item }}/defaults"
|
|
|
|
|
loop: "{{ serveur_artefacts_directs_roles }}"
|
|
|
|
|
loop_control:
|
|
|
|
|
label: "{{ item }}"
|
|
|
|
|
when: serveur_artefacts_directs_actif | bool
|
|
|
|
|
|
|
|
|
|
# `force: false` ET UN `dest` NOMME PAR LA VERSION : une publication ne change pas sous
|
|
|
|
|
# le meme nom, donc un fichier deja present est le bon. Une nouvelle version porte un
|
|
|
|
|
# autre nom et se telecharge d'elle-meme — le depot se met a jour en suivant les roles,
|
|
|
|
|
# sans qu'on ait rien a purger.
|
|
|
|
|
#
|
|
|
|
|
# LES REPRISES SONT OBLIGATOIRES, PAS PRUDENTIELLES. `packages.smallstep.com` a deja fait
|
|
|
|
|
# echouer un deploiement de quarante minutes en pendant au premier essai et en repondant
|
|
|
|
|
# en 0,48 s au second ; codeberg.org n'a aucune raison d'etre plus fiable.
|
|
|
|
|
- name: Tenir les binaires directs à la disposition des écosystèmes
|
|
|
|
|
ansible.builtin.get_url:
|
|
|
|
|
url: "{{ item.url }}"
|
|
|
|
|
dest: "{{ serveur_artefacts_directs_dir }}/{{ item.nom }}"
|
|
|
|
|
mode: "0644"
|
|
|
|
|
force: false
|
|
|
|
|
timeout: 60
|
|
|
|
|
loop: "{{ serveur_artefacts_directs }}"
|
|
|
|
|
loop_control:
|
|
|
|
|
label: "{{ item.nom }}"
|
|
|
|
|
register: serveur_artefacts_directs_tires
|
|
|
|
|
retries: 5
|
|
|
|
|
delay: 6
|
|
|
|
|
until: serveur_artefacts_directs_tires is succeeded
|
|
|
|
|
# UN AMONT MUET NE DOIT PAS ARRETER LE SITE. Ce depot est une COMMODITE : sans lui,
|
|
|
|
|
# chaque runner sort lui-meme, comme avant. Le faire echouer rendrait le site
|
|
|
|
|
# indeployable le jour ou codeberg.org tousse — on aurait echange une sortie Internet
|
|
|
|
|
# contre une dependance a Internet, ce qui est exactement l'inverse du but.
|
|
|
|
|
failed_when: false
|
|
|
|
|
when:
|
|
|
|
|
- serveur_artefacts_directs_actif | bool
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
# ON LE DIT, FORT. Un depot a moitie rempli sert a moitie, et le runner qui complete en
|
|
|
|
|
# sortant sur Internet le fait sans que rien ne le signale.
|
|
|
|
|
- name: Dire ce que le dépôt de binaires ne tient PAS
|
|
|
|
|
ansible.builtin.debug:
|
|
|
|
|
msg: >-
|
|
|
|
|
{{ (serveur_artefacts_directs_tires.results | default([])
|
|
|
|
|
| selectattr('failed', 'defined') | selectattr('failed')
|
|
|
|
|
| map(attribute='item.nom') | list) | join(', ') }}
|
|
|
|
|
— absent(s) du depot. Les runners qui en ont besoin sortiront sur Internet.
|
|
|
|
|
when:
|
|
|
|
|
- serveur_artefacts_directs_actif | bool
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
- (serveur_artefacts_directs_tires.results | default([])
|
|
|
|
|
| selectattr('failed', 'defined') | selectattr('failed') | list | length) > 0
|