serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
---
|
site : le runner travaille, et le genome remonte chez lui
`serveur_ops` et `serveur_ops_site` sont deployes sur `site-ops-01` : le moteur,
les plans des trois tenants, les collections hors ligne, et la voute de
l'underlay deposee CHIFFREE. Le site a son runner.
DEUX FORMES DE RUNNER, ET UNE SEULE ETAIT PREVUE.
`serveur_ops` exigeait un depot `role: instance` et un `serveur_ops_instance` —
la forme d'un runner de TENANT, qui pilote un ecosysteme, monte son plan par le
lien `instance`, detient sa voute.
Un runner de SITE ne pilote rien : il MATERIALISE le terrain que d'autres
occuperont, et son inventaire est dynamique. Son plan declarait donc ses depots
de tenants en `role: tenant`, a dessein et avec ses raisons ecrites — et le role
le refusait au nom d'une exigence qui ne le concernait pas. Il exige desormais
que le runner pilote QUELQUE CHOSE, sans prescrire quoi.
Et il posait le lien quand meme : `serveur_ops_instance: ""` donnait
`instance -> /opt/setops/`, un repertoire qui n'est l'ecosysteme de personne. Un
lien qui existe et ne designe rien est pire qu'un lien absent : tout ce qui le
suit croit avoir trouve une instance.
LE CERTIFICAT COUVRE LES NOMS DU SERVICE.
`client_pki` ne mettait dans ses SAN que le FQDN, le nom court et l'IP. Le
clonage du genome a bute dessus : « certificate subject name
(site-forge-01.genese.internal) does not match target hostname
'forge.genese.internal' ». Le nom declare `expose:` etait publie partout —
plancher, zone DNS — et couvert nulle part.
Les expositions que cet hote SERT REELLEMENT entrent maintenant dans le
certificat. Un certificat qui revendiquerait le nom d'un service rendu ailleurs
serait une usurpation, pas une commodite.
`make genome-pousser` — LE RUNNER POUSSE, LE POSTE NE ROUTE PAS.
La forge du genome vit DANS le site, sur un reseau que le poste de l'exploitant
ne route pas. On ne perce pas un chemin pour lui : on lui retire le role. Le
poste emballe les commits dans un `git bundle` — un fichier, verifiable, qui ne
demande aucun reseau — et le runner verifie, avance EN AVANCE RAPIDE SEULEMENT,
puis pousse avec SA cle, autorisee en ecriture sur ces depots-la seulement.
Ce qui est pousse se DERIVE de `serveur_ops_depots`. `DEPOT=<nom>` en cible un
seul.
Trois pieges rencontres, tous inscrits dans le code : l'outil ne peut pas etre
supposé present sur le runner (il ne recevrait cette version qu'APRES la poussee
qu'elle sert a faire — le controleur le porte) ; la branche n'est pas toujours
`main` (deux depots vivent sur `master`, et le plan le declarait deja) ; le
dossier des depots freres contient un espace, d'ou `argv` et non `cmd`.
Le juge n'est pas le journal du playbook mais LA FORGE : on demande a son API ce
qu'elle porte, et on refuse si ca differe de ce que porte le runner. Six depots
verifies.
Pourquoi ca comptait : la forge du site etait restee quatre commits derriere le
poste, sans que rien ne le signale — dont le correctif qui desarme le pare-feu
Proxmox. Un ecosysteme qui se reproduit depuis une forge en retard reproduit ses
defauts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 08:52:37 -04:00
|
|
|
# UN POSTE QUI NE SAIT PAS SUR QUOI IL TRAVAILLE N'A RIEN À PILOTER.
|
2026-08-24 11:42:32 -04:00
|
|
|
#
|
site : le runner travaille, et le genome remonte chez lui
`serveur_ops` et `serveur_ops_site` sont deployes sur `site-ops-01` : le moteur,
les plans des trois tenants, les collections hors ligne, et la voute de
l'underlay deposee CHIFFREE. Le site a son runner.
DEUX FORMES DE RUNNER, ET UNE SEULE ETAIT PREVUE.
`serveur_ops` exigeait un depot `role: instance` et un `serveur_ops_instance` —
la forme d'un runner de TENANT, qui pilote un ecosysteme, monte son plan par le
lien `instance`, detient sa voute.
Un runner de SITE ne pilote rien : il MATERIALISE le terrain que d'autres
occuperont, et son inventaire est dynamique. Son plan declarait donc ses depots
de tenants en `role: tenant`, a dessein et avec ses raisons ecrites — et le role
le refusait au nom d'une exigence qui ne le concernait pas. Il exige desormais
que le runner pilote QUELQUE CHOSE, sans prescrire quoi.
Et il posait le lien quand meme : `serveur_ops_instance: ""` donnait
`instance -> /opt/setops/`, un repertoire qui n'est l'ecosysteme de personne. Un
lien qui existe et ne designe rien est pire qu'un lien absent : tout ce qui le
suit croit avoir trouve une instance.
LE CERTIFICAT COUVRE LES NOMS DU SERVICE.
`client_pki` ne mettait dans ses SAN que le FQDN, le nom court et l'IP. Le
clonage du genome a bute dessus : « certificate subject name
(site-forge-01.genese.internal) does not match target hostname
'forge.genese.internal' ». Le nom declare `expose:` etait publie partout —
plancher, zone DNS — et couvert nulle part.
Les expositions que cet hote SERT REELLEMENT entrent maintenant dans le
certificat. Un certificat qui revendiquerait le nom d'un service rendu ailleurs
serait une usurpation, pas une commodite.
`make genome-pousser` — LE RUNNER POUSSE, LE POSTE NE ROUTE PAS.
La forge du genome vit DANS le site, sur un reseau que le poste de l'exploitant
ne route pas. On ne perce pas un chemin pour lui : on lui retire le role. Le
poste emballe les commits dans un `git bundle` — un fichier, verifiable, qui ne
demande aucun reseau — et le runner verifie, avance EN AVANCE RAPIDE SEULEMENT,
puis pousse avec SA cle, autorisee en ecriture sur ces depots-la seulement.
Ce qui est pousse se DERIVE de `serveur_ops_depots`. `DEPOT=<nom>` en cible un
seul.
Trois pieges rencontres, tous inscrits dans le code : l'outil ne peut pas etre
supposé present sur le runner (il ne recevrait cette version qu'APRES la poussee
qu'elle sert a faire — le controleur le porte) ; la branche n'est pas toujours
`main` (deux depots vivent sur `master`, et le plan le declarait deja) ; le
dossier des depots freres contient un espace, d'ou `argv` et non `cmd`.
Le juge n'est pas le journal du playbook mais LA FORGE : on demande a son API ce
qu'elle porte, et on refuse si ca differe de ce que porte le runner. Six depots
verifies.
Pourquoi ca comptait : la forge du site etait restee quatre commits derriere le
poste, sans que rien ne le signale — dont le correctif qui desarme le pare-feu
Proxmox. Un ecosysteme qui se reproduit depuis une forge en retard reproduit ses
defauts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 08:52:37 -04:00
|
|
|
# On exige explicitement ce qu'il pilote, plutôt que de retomber sur un défaut : le
|
2026-08-24 11:42:32 -04:00
|
|
|
# défaut nommait patient 0, et un écosystème distrait aurait cloné le génome d'un autre
|
|
|
|
|
# sans qu'aucune erreur ne le signale.
|
site : le runner travaille, et le genome remonte chez lui
`serveur_ops` et `serveur_ops_site` sont deployes sur `site-ops-01` : le moteur,
les plans des trois tenants, les collections hors ligne, et la voute de
l'underlay deposee CHIFFREE. Le site a son runner.
DEUX FORMES DE RUNNER, ET UNE SEULE ETAIT PREVUE.
`serveur_ops` exigeait un depot `role: instance` et un `serveur_ops_instance` —
la forme d'un runner de TENANT, qui pilote un ecosysteme, monte son plan par le
lien `instance`, detient sa voute.
Un runner de SITE ne pilote rien : il MATERIALISE le terrain que d'autres
occuperont, et son inventaire est dynamique. Son plan declarait donc ses depots
de tenants en `role: tenant`, a dessein et avec ses raisons ecrites — et le role
le refusait au nom d'une exigence qui ne le concernait pas. Il exige desormais
que le runner pilote QUELQUE CHOSE, sans prescrire quoi.
Et il posait le lien quand meme : `serveur_ops_instance: ""` donnait
`instance -> /opt/setops/`, un repertoire qui n'est l'ecosysteme de personne. Un
lien qui existe et ne designe rien est pire qu'un lien absent : tout ce qui le
suit croit avoir trouve une instance.
LE CERTIFICAT COUVRE LES NOMS DU SERVICE.
`client_pki` ne mettait dans ses SAN que le FQDN, le nom court et l'IP. Le
clonage du genome a bute dessus : « certificate subject name
(site-forge-01.genese.internal) does not match target hostname
'forge.genese.internal' ». Le nom declare `expose:` etait publie partout —
plancher, zone DNS — et couvert nulle part.
Les expositions que cet hote SERT REELLEMENT entrent maintenant dans le
certificat. Un certificat qui revendiquerait le nom d'un service rendu ailleurs
serait une usurpation, pas une commodite.
`make genome-pousser` — LE RUNNER POUSSE, LE POSTE NE ROUTE PAS.
La forge du genome vit DANS le site, sur un reseau que le poste de l'exploitant
ne route pas. On ne perce pas un chemin pour lui : on lui retire le role. Le
poste emballe les commits dans un `git bundle` — un fichier, verifiable, qui ne
demande aucun reseau — et le runner verifie, avance EN AVANCE RAPIDE SEULEMENT,
puis pousse avec SA cle, autorisee en ecriture sur ces depots-la seulement.
Ce qui est pousse se DERIVE de `serveur_ops_depots`. `DEPOT=<nom>` en cible un
seul.
Trois pieges rencontres, tous inscrits dans le code : l'outil ne peut pas etre
supposé present sur le runner (il ne recevrait cette version qu'APRES la poussee
qu'elle sert a faire — le controleur le porte) ; la branche n'est pas toujours
`main` (deux depots vivent sur `master`, et le plan le declarait deja) ; le
dossier des depots freres contient un espace, d'ou `argv` et non `cmd`.
Le juge n'est pas le journal du playbook mais LA FORGE : on demande a son API ce
qu'elle porte, et on refuse si ca differe de ce que porte le runner. Six depots
verifies.
Pourquoi ca comptait : la forge du site etait restee quatre commits derriere le
poste, sans que rien ne le signale — dont le correctif qui desarme le pare-feu
Proxmox. Un ecosysteme qui se reproduit depuis une forge en retard reproduit ses
defauts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 08:52:37 -04:00
|
|
|
#
|
|
|
|
|
# DEUX FORMES DE RUNNER, ET UNE SEULE ÉTAIT PRÉVUE (2026-08-25).
|
|
|
|
|
#
|
|
|
|
|
# Un runner de TENANT pilote un écosystème : il monte son plan par le lien `instance`,
|
|
|
|
|
# détient sa voûte, et configure ses services. Il lui faut donc un dépôt `role: instance`
|
|
|
|
|
# et `serveur_ops_instance`.
|
|
|
|
|
#
|
|
|
|
|
# Un runner de SITE ne pilote aucun écosystème — il MATÉRIALISE le terrain que d'autres
|
|
|
|
|
# occuperont : VNets, VM, routes, flux. Son propre inventaire est DYNAMIQUE
|
|
|
|
|
# (`site_inventaire.py`), il n'a pas de lien `instance` à monter, et les dépôts de
|
|
|
|
|
# tenants qu'il porte sont marqués `role: tenant` précisément pour dire qu'il ne les
|
|
|
|
|
# pilote pas. Ce qu'il pilote, c'est la CARTE de l'hébergeur : `role: hebergeur` et
|
|
|
|
|
# `serveur_ops_underlay`.
|
|
|
|
|
#
|
|
|
|
|
# L'assertion n'admettait que la première forme. Le plan du site déclarait pourtant tout
|
|
|
|
|
# ce qu'il fallait, correctement et avec ses raisons écrites — et le rôle le refusait au
|
|
|
|
|
# nom d'une exigence qui ne le concernait pas.
|
|
|
|
|
#
|
|
|
|
|
# On exige donc que le runner pilote QUELQUE CHOSE, sans prescrire quoi.
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
- name: Exiger les intrants du poste d'exploitation
|
|
|
|
|
ansible.builtin.assert:
|
|
|
|
|
that:
|
|
|
|
|
- domaine_interne | default('') | length > 0
|
2026-08-24 11:42:32 -04:00
|
|
|
- (serveur_ops_depots | selectattr('role', 'eq', 'moteur') | list | length) == 1
|
site : le runner travaille, et le genome remonte chez lui
`serveur_ops` et `serveur_ops_site` sont deployes sur `site-ops-01` : le moteur,
les plans des trois tenants, les collections hors ligne, et la voute de
l'underlay deposee CHIFFREE. Le site a son runner.
DEUX FORMES DE RUNNER, ET UNE SEULE ETAIT PREVUE.
`serveur_ops` exigeait un depot `role: instance` et un `serveur_ops_instance` —
la forme d'un runner de TENANT, qui pilote un ecosysteme, monte son plan par le
lien `instance`, detient sa voute.
Un runner de SITE ne pilote rien : il MATERIALISE le terrain que d'autres
occuperont, et son inventaire est dynamique. Son plan declarait donc ses depots
de tenants en `role: tenant`, a dessein et avec ses raisons ecrites — et le role
le refusait au nom d'une exigence qui ne le concernait pas. Il exige desormais
que le runner pilote QUELQUE CHOSE, sans prescrire quoi.
Et il posait le lien quand meme : `serveur_ops_instance: ""` donnait
`instance -> /opt/setops/`, un repertoire qui n'est l'ecosysteme de personne. Un
lien qui existe et ne designe rien est pire qu'un lien absent : tout ce qui le
suit croit avoir trouve une instance.
LE CERTIFICAT COUVRE LES NOMS DU SERVICE.
`client_pki` ne mettait dans ses SAN que le FQDN, le nom court et l'IP. Le
clonage du genome a bute dessus : « certificate subject name
(site-forge-01.genese.internal) does not match target hostname
'forge.genese.internal' ». Le nom declare `expose:` etait publie partout —
plancher, zone DNS — et couvert nulle part.
Les expositions que cet hote SERT REELLEMENT entrent maintenant dans le
certificat. Un certificat qui revendiquerait le nom d'un service rendu ailleurs
serait une usurpation, pas une commodite.
`make genome-pousser` — LE RUNNER POUSSE, LE POSTE NE ROUTE PAS.
La forge du genome vit DANS le site, sur un reseau que le poste de l'exploitant
ne route pas. On ne perce pas un chemin pour lui : on lui retire le role. Le
poste emballe les commits dans un `git bundle` — un fichier, verifiable, qui ne
demande aucun reseau — et le runner verifie, avance EN AVANCE RAPIDE SEULEMENT,
puis pousse avec SA cle, autorisee en ecriture sur ces depots-la seulement.
Ce qui est pousse se DERIVE de `serveur_ops_depots`. `DEPOT=<nom>` en cible un
seul.
Trois pieges rencontres, tous inscrits dans le code : l'outil ne peut pas etre
supposé present sur le runner (il ne recevrait cette version qu'APRES la poussee
qu'elle sert a faire — le controleur le porte) ; la branche n'est pas toujours
`main` (deux depots vivent sur `master`, et le plan le declarait deja) ; le
dossier des depots freres contient un espace, d'ou `argv` et non `cmd`.
Le juge n'est pas le journal du playbook mais LA FORGE : on demande a son API ce
qu'elle porte, et on refuse si ca differe de ce que porte le runner. Six depots
verifies.
Pourquoi ca comptait : la forge du site etait restee quatre commits derriere le
poste, sans que rien ne le signale — dont le correctif qui desarme le pare-feu
Proxmox. Un ecosysteme qui se reproduit depuis une forge en retard reproduit ses
defauts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 08:52:37 -04:00
|
|
|
- >-
|
|
|
|
|
((serveur_ops_depots | selectattr('role', 'eq', 'instance') | list | length) >= 1
|
|
|
|
|
and serveur_ops_instance | default('') | length > 0)
|
|
|
|
|
or
|
|
|
|
|
((serveur_ops_depots | selectattr('role', 'eq', 'hebergeur') | list | length) >= 1
|
|
|
|
|
and serveur_ops_underlay | default('') | length > 0)
|
2026-08-24 14:10:10 -04:00
|
|
|
- not (serveur_ops_forge_externe | bool) or (serveur_ops_forge_amont | length > 0)
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
fail_msg: >-
|
site : le runner travaille, et le genome remonte chez lui
`serveur_ops` et `serveur_ops_site` sont deployes sur `site-ops-01` : le moteur,
les plans des trois tenants, les collections hors ligne, et la voute de
l'underlay deposee CHIFFREE. Le site a son runner.
DEUX FORMES DE RUNNER, ET UNE SEULE ETAIT PREVUE.
`serveur_ops` exigeait un depot `role: instance` et un `serveur_ops_instance` —
la forme d'un runner de TENANT, qui pilote un ecosysteme, monte son plan par le
lien `instance`, detient sa voute.
Un runner de SITE ne pilote rien : il MATERIALISE le terrain que d'autres
occuperont, et son inventaire est dynamique. Son plan declarait donc ses depots
de tenants en `role: tenant`, a dessein et avec ses raisons ecrites — et le role
le refusait au nom d'une exigence qui ne le concernait pas. Il exige desormais
que le runner pilote QUELQUE CHOSE, sans prescrire quoi.
Et il posait le lien quand meme : `serveur_ops_instance: ""` donnait
`instance -> /opt/setops/`, un repertoire qui n'est l'ecosysteme de personne. Un
lien qui existe et ne designe rien est pire qu'un lien absent : tout ce qui le
suit croit avoir trouve une instance.
LE CERTIFICAT COUVRE LES NOMS DU SERVICE.
`client_pki` ne mettait dans ses SAN que le FQDN, le nom court et l'IP. Le
clonage du genome a bute dessus : « certificate subject name
(site-forge-01.genese.internal) does not match target hostname
'forge.genese.internal' ». Le nom declare `expose:` etait publie partout —
plancher, zone DNS — et couvert nulle part.
Les expositions que cet hote SERT REELLEMENT entrent maintenant dans le
certificat. Un certificat qui revendiquerait le nom d'un service rendu ailleurs
serait une usurpation, pas une commodite.
`make genome-pousser` — LE RUNNER POUSSE, LE POSTE NE ROUTE PAS.
La forge du genome vit DANS le site, sur un reseau que le poste de l'exploitant
ne route pas. On ne perce pas un chemin pour lui : on lui retire le role. Le
poste emballe les commits dans un `git bundle` — un fichier, verifiable, qui ne
demande aucun reseau — et le runner verifie, avance EN AVANCE RAPIDE SEULEMENT,
puis pousse avec SA cle, autorisee en ecriture sur ces depots-la seulement.
Ce qui est pousse se DERIVE de `serveur_ops_depots`. `DEPOT=<nom>` en cible un
seul.
Trois pieges rencontres, tous inscrits dans le code : l'outil ne peut pas etre
supposé present sur le runner (il ne recevrait cette version qu'APRES la poussee
qu'elle sert a faire — le controleur le porte) ; la branche n'est pas toujours
`main` (deux depots vivent sur `master`, et le plan le declarait deja) ; le
dossier des depots freres contient un espace, d'ou `argv` et non `cmd`.
Le juge n'est pas le journal du playbook mais LA FORGE : on demande a son API ce
qu'elle porte, et on refuse si ca differe de ce que porte le runner. Six depots
verifies.
Pourquoi ca comptait : la forge du site etait restee quatre commits derriere le
poste, sans que rien ne le signale — dont le correctif qui desarme le pare-feu
Proxmox. Un ecosysteme qui se reproduit depuis une forge en retard reproduit ses
defauts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 08:52:37 -04:00
|
|
|
serveur_ops exige `domaine_interne`, exactement un dépôt `role: moteur`, et de
|
|
|
|
|
savoir sur quoi il travaille — SOIT un dépôt `role: instance` avec
|
|
|
|
|
`serveur_ops_instance` (runner de TENANT : il pilote un écosystème), SOIT un dépôt
|
|
|
|
|
`role: hebergeur` avec `serveur_ops_underlay` (runner de SITE : il matérialise le
|
|
|
|
|
terrain, et son inventaire est dynamique). Et si `serveur_ops_forge_externe` est
|
|
|
|
|
levé — écosystème au premier âge, qui lit son génome chez son hôte —
|
|
|
|
|
`serveur_ops_forge_amont` doit nommer cette forge.
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
|
|
|
|
|
- name: Installer l'outillage du poste
|
|
|
|
|
ansible.builtin.apt:
|
|
|
|
|
name: "{{ serveur_ops_paquets }}"
|
|
|
|
|
state: present
|
|
|
|
|
update_cache: true
|
|
|
|
|
when: not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
- name: Créer l'utilisateur d'exploitation
|
|
|
|
|
ansible.builtin.user:
|
|
|
|
|
name: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
home: "{{ serveur_ops_racine }}"
|
|
|
|
|
shell: /bin/bash
|
|
|
|
|
create_home: true
|
|
|
|
|
system: false
|
|
|
|
|
|
|
|
|
|
- name: Poser les droits de la racine d'exploitation
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: "{{ serveur_ops_racine }}"
|
|
|
|
|
state: directory
|
|
|
|
|
owner: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
group: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
mode: "0750"
|
|
|
|
|
|
|
|
|
|
# L'ENVIRONNEMENT PYTHON EST ISOLÉ, PAS SYSTÈME. Debian gère ansible en paquet, mais la
|
|
|
|
|
# version qu'il propose suit son propre calendrier : reconstruire un écosystème avec un
|
|
|
|
|
# ansible plus récent que celui qui l'a construit, c'est changer la recette sans le dire.
|
|
|
|
|
# Le venv permet d'épingler exactement la famille utilisée par le mainteneur.
|
|
|
|
|
- name: Créer l'environnement Python isolé
|
|
|
|
|
ansible.builtin.command:
|
|
|
|
|
cmd: "python3 -m venv {{ serveur_ops_venv }}"
|
|
|
|
|
creates: "{{ serveur_ops_venv }}/bin/python"
|
|
|
|
|
become: true
|
|
|
|
|
become_user: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
|
portabilite : declarer ce dont le moteur depend — quatre defauts reveles par le runner
Premiere materialisation d'une VM de tenant depuis le runner du SITE. Elle a
echoue quatre fois d'affilee, sur quatre dependances que le moteur ne declarait
nulle part. Chacune fonctionnait chez le mainteneur pour une raison DIFFERENTE,
et aucune de ces raisons n'existe sur une autre machine.
1. VERSIONS DES COLLECTIONS. `requirements.yml` les nommait sans les epingler. Le
runner a recu `community.general` 13.3.0 quand le poste porte la 10.3.0 — et la
11 a retire les modules Proxmox de cette collection.
ERROR! couldn't resolve module/action 'community.general.proxmox_pool'
2. INSTALLATION EN AVANT. `ansible-galaxy` ne retrograde pas : declarer la 10.3.0
ne suffisait pas a defaire une 13.3.0 deja posee. `--force`.
3. EMPLACEMENT. Le `Makefile` pose `ANSIBLE_HOME ?= $(CURDIR)/.ansible` : sous
`make`, Ansible ne lit QUE `<moteur>/.ansible/collections`. Le role deposait
dans `<racine>/.ansible/collections` — a cote, jamais lu. Invisible chez le
mainteneur, ou les collections viennent du paquet systeme, toujours dans le
chemin quel que soit ANSIBLE_HOME. Et le garde-fou d'installation suivait le
DEPOT des archives : changer la destination ne le declenchait pas. Il mesure
desormais la destination — meme piege qu'en 2026-08-24, deplace d'un cran.
4. BIBLIOTHEQUES PYTHON. Le venv recevait `ansible-core` et `pyyaml`, ecrits en
dur. Les modules Proxmox tournent `delegate_to: localhost` et exigent
`proxmoxer` SUR LE CONTROLEUR.
La bibliotheque Python proxmoxer est absente
Ne d'ici : `requirements-python.txt`, avec sa frontiere ecrite — il ne declare
QUE ce qui tourne sur le controleur. `python-ldap` et `psycopg2` s'executent
sur leurs cibles ; le poste du mainteneur ne les a pas et la flotte se deploie,
ce qui prouve que la ligne est au bon endroit.
P51 garde les trois faiblesses de cette famille : une dependance utilisee sans
etre declaree (le defaut du 2026-08-24, `ansible.posix`), une dependance declaree
sans version, et `proxmoxer` absent alors que des playbooks Proxmox existent.
Quatre controles negatifs verifies.
RESULTAT : ops-01 materialisee par le runner du site. L'agent invite rapporte
`eth0 10.17.19.41/24`, Debian 13 trixie — l'adressage derive du plan, applique.
Un seul executant masque ces ecarts indefiniment ; un second les revele tous en
une soiree. Meme mecanique que le second tenant en aout.
make prouver : CONFORME, 51 OK, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 22:38:35 -04:00
|
|
|
# LES BIBLIOTHEQUES DU CONTROLEUR SE DECLARENT, ELLES AUSSI (2026-08-27). Cette liste
|
|
|
|
|
# etait ecrite en dur — `ansible-core` et `pyyaml`, rien de plus — alors que les modules
|
|
|
|
|
# Proxmox du moteur exigent `proxmoxer` sur la machine qui les execute. Le runner du SITE
|
|
|
|
|
# a donc echoue a sa premiere materialisation de VM, sur une bibliotheque que le poste du
|
|
|
|
|
# mainteneur possedait par son paquet systeme sans que personne ne l'ait declaree.
|
|
|
|
|
# `requirements-python.txt` est desormais la source, au meme titre que `requirements.yml`
|
|
|
|
|
# pour les collections. Voir la preuve P51.
|
|
|
|
|
- name: Deposer la liste des bibliotheques Python du controleur
|
|
|
|
|
ansible.builtin.copy:
|
|
|
|
|
src: "{{ playbook_dir }}/../../requirements-python.txt"
|
|
|
|
|
dest: "{{ serveur_ops_racine }}/requirements-python.txt"
|
|
|
|
|
owner: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
group: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
mode: "0644"
|
|
|
|
|
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
- name: Installer Ansible dans l'environnement isolé
|
|
|
|
|
ansible.builtin.pip:
|
|
|
|
|
name:
|
|
|
|
|
- "{{ serveur_ops_ansible }}"
|
|
|
|
|
- "pyyaml"
|
|
|
|
|
virtualenv: "{{ serveur_ops_venv }}"
|
|
|
|
|
state: present
|
|
|
|
|
become: true
|
|
|
|
|
become_user: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
when: not ansible_check_mode
|
|
|
|
|
register: serveur_ops_pip
|
|
|
|
|
retries: 3
|
|
|
|
|
delay: 6
|
|
|
|
|
until: serveur_ops_pip is succeeded
|
|
|
|
|
|
portabilite : declarer ce dont le moteur depend — quatre defauts reveles par le runner
Premiere materialisation d'une VM de tenant depuis le runner du SITE. Elle a
echoue quatre fois d'affilee, sur quatre dependances que le moteur ne declarait
nulle part. Chacune fonctionnait chez le mainteneur pour une raison DIFFERENTE,
et aucune de ces raisons n'existe sur une autre machine.
1. VERSIONS DES COLLECTIONS. `requirements.yml` les nommait sans les epingler. Le
runner a recu `community.general` 13.3.0 quand le poste porte la 10.3.0 — et la
11 a retire les modules Proxmox de cette collection.
ERROR! couldn't resolve module/action 'community.general.proxmox_pool'
2. INSTALLATION EN AVANT. `ansible-galaxy` ne retrograde pas : declarer la 10.3.0
ne suffisait pas a defaire une 13.3.0 deja posee. `--force`.
3. EMPLACEMENT. Le `Makefile` pose `ANSIBLE_HOME ?= $(CURDIR)/.ansible` : sous
`make`, Ansible ne lit QUE `<moteur>/.ansible/collections`. Le role deposait
dans `<racine>/.ansible/collections` — a cote, jamais lu. Invisible chez le
mainteneur, ou les collections viennent du paquet systeme, toujours dans le
chemin quel que soit ANSIBLE_HOME. Et le garde-fou d'installation suivait le
DEPOT des archives : changer la destination ne le declenchait pas. Il mesure
desormais la destination — meme piege qu'en 2026-08-24, deplace d'un cran.
4. BIBLIOTHEQUES PYTHON. Le venv recevait `ansible-core` et `pyyaml`, ecrits en
dur. Les modules Proxmox tournent `delegate_to: localhost` et exigent
`proxmoxer` SUR LE CONTROLEUR.
La bibliotheque Python proxmoxer est absente
Ne d'ici : `requirements-python.txt`, avec sa frontiere ecrite — il ne declare
QUE ce qui tourne sur le controleur. `python-ldap` et `psycopg2` s'executent
sur leurs cibles ; le poste du mainteneur ne les a pas et la flotte se deploie,
ce qui prouve que la ligne est au bon endroit.
P51 garde les trois faiblesses de cette famille : une dependance utilisee sans
etre declaree (le defaut du 2026-08-24, `ansible.posix`), une dependance declaree
sans version, et `proxmoxer` absent alors que des playbooks Proxmox existent.
Quatre controles negatifs verifies.
RESULTAT : ops-01 materialisee par le runner du site. L'agent invite rapporte
`eth0 10.17.19.41/24`, Debian 13 trixie — l'adressage derive du plan, applique.
Un seul executant masque ces ecarts indefiniment ; un second les revele tous en
une soiree. Meme mecanique que le second tenant en aout.
make prouver : CONFORME, 51 OK, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 22:38:35 -04:00
|
|
|
# TACHE SEPAREE : dans `ansible.builtin.pip`, `name` et `requirements` sont MUTUELLEMENT
|
|
|
|
|
# EXCLUSIFS. Les fusionner ne produit pas une erreur parlante — le module ignore l'un des
|
|
|
|
|
# deux, et la bibliotheque manquante ne se revele qu'au premier module qui en depend.
|
|
|
|
|
- name: Installer les bibliotheques Python du controleur (source declaree)
|
|
|
|
|
ansible.builtin.pip:
|
|
|
|
|
requirements: "{{ serveur_ops_racine }}/requirements-python.txt"
|
|
|
|
|
virtualenv: "{{ serveur_ops_venv }}"
|
|
|
|
|
state: present
|
|
|
|
|
become: true
|
|
|
|
|
become_user: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
when: not ansible_check_mode
|
|
|
|
|
register: serveur_ops_pip_controleur
|
|
|
|
|
retries: 3
|
|
|
|
|
delay: 6
|
|
|
|
|
until: serveur_ops_pip_controleur is succeeded
|
|
|
|
|
|
2026-08-26 16:42:24 -04:00
|
|
|
# L'OUTILLAGE DOIT ETRE SUR LE CHEMIN DE CELUI QUI L'EXPLOITE (2026-08-26).
|
|
|
|
|
#
|
|
|
|
|
# Ansible vit dans un venv isole — c'est voulu, il est epingle. Mais rien ne le mettait sur
|
|
|
|
|
# le PATH du compte d'exploitation : `make instancier` y echouait sur
|
|
|
|
|
# « [Errno 2] No such file or directory: 'ansible-inventory' », un message qui accuse un
|
|
|
|
|
# fichier manquant alors que le fichier est la, deux dossiers plus loin.
|
|
|
|
|
#
|
|
|
|
|
# Mesure du 2026-08-26, en eprouvant la sequence depuis le runner du site. Un exploitant y
|
|
|
|
|
# serait tombe exactement de la meme facon — et c'est precisement ce qu'un outil « utilisable
|
|
|
|
|
# sans IA » ne doit pas faire.
|
|
|
|
|
#
|
|
|
|
|
# Un fragment `profile.d` plutot qu'un `.bashrc` : il vaut pour toute session du compte, y
|
|
|
|
|
# compris `sudo -iu setops`, et se retire d'un seul geste.
|
|
|
|
|
- name: Mettre l'outillage du poste sur le chemin du compte d'exploitation
|
|
|
|
|
ansible.builtin.copy:
|
|
|
|
|
dest: /etc/profile.d/50-setops-venv.sh
|
|
|
|
|
content: |
|
|
|
|
|
# GÉNÉRÉ par Set-OPS (rôle serveur_ops). NE PAS éditer à la main.
|
|
|
|
|
# Ansible vit dans un venv épinglé ; sans cette ligne, `make` ne le trouve pas.
|
|
|
|
|
if [ "$(id -un)" = "{{ serveur_ops_utilisateur }}" ]; then
|
|
|
|
|
PATH="{{ serveur_ops_venv }}/bin:$PATH"
|
|
|
|
|
export PATH
|
|
|
|
|
fi
|
|
|
|
|
owner: root
|
|
|
|
|
group: root
|
|
|
|
|
mode: "0644"
|
|
|
|
|
|
2026-08-24 18:55:44 -04:00
|
|
|
# LA CONFIANCE, AVANT LE CLONE — et limitee a une seule url.
|
|
|
|
|
#
|
|
|
|
|
# Voir defaults/main.yml : on ne pose pas cette racine dans le magasin systeme. `git
|
|
|
|
|
# config http.<url>.sslCAInfo` ne l'applique qu'aux echanges avec CETTE forge.
|
|
|
|
|
- name: Deposer la racine de la forge amont
|
|
|
|
|
ansible.builtin.copy:
|
|
|
|
|
src: "{{ serveur_ops_forge_amont_ac }}"
|
|
|
|
|
dest: "{{ serveur_ops_forge_amont_ac_depot }}"
|
|
|
|
|
owner: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
group: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
mode: "0644"
|
|
|
|
|
when:
|
|
|
|
|
- serveur_ops_forge_amont_ac | length > 0
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
- name: Limiter la confiance a la forge amont, et a elle seule
|
|
|
|
|
community.general.git_config:
|
|
|
|
|
name: "http.{{ serveur_ops_forge_url }}/.sslCAInfo"
|
|
|
|
|
scope: global
|
|
|
|
|
value: "{{ serveur_ops_forge_amont_ac_depot }}"
|
|
|
|
|
become: true
|
|
|
|
|
become_user: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
when:
|
|
|
|
|
- serveur_ops_forge_amont_ac | length > 0
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
# --- LE GÉNOME, DEPUIS SA PROPRE FORGE ---------------------------------------
|
|
|
|
|
#
|
|
|
|
|
# Cloné en anonyme : les dépôts du génome sont lisibles sur la forge de l'écosystème, et
|
|
|
|
|
# le poste n'a donc AUCUN justificatif à détenir pour se reconstruire. C'est délibéré —
|
|
|
|
|
# un secret de moins sur la machine qui en concentre déjà beaucoup.
|
|
|
|
|
#
|
2026-08-24 18:55:44 -04:00
|
|
|
# La confiance TLS vient de `client_pki` quand la forge est celle de CET écosystème
|
|
|
|
|
# (racine step-ca dans le magasin système). Quand elle est celle d'un voisin, elle vient
|
|
|
|
|
# de la tâche ci-dessus — limitée à cette seule url. Sans l'une ou l'autre, `git clone`
|
|
|
|
|
# refuse le certificat, et c'est bien qu'il refuse.
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
- name: Cloner le génome depuis la forge de l'écosystème
|
|
|
|
|
ansible.builtin.git:
|
|
|
|
|
repo: "{{ serveur_ops_forge_url }}/{{ serveur_ops_forge_organisation }}/{{ item.depot }}.git"
|
|
|
|
|
dest: "{{ serveur_ops_racine }}/{{ item.dest }}"
|
|
|
|
|
version: "{{ item.branche | default('main') }}"
|
|
|
|
|
update: true
|
|
|
|
|
force: false
|
|
|
|
|
loop: "{{ serveur_ops_depots }}"
|
|
|
|
|
loop_control:
|
|
|
|
|
label: "{{ item.depot }} → {{ item.dest }}"
|
|
|
|
|
become: true
|
|
|
|
|
become_user: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
when: not ansible_check_mode
|
|
|
|
|
register: serveur_ops_clone
|
|
|
|
|
retries: 3
|
|
|
|
|
delay: 6
|
|
|
|
|
until: serveur_ops_clone is succeeded
|
|
|
|
|
|
|
|
|
|
# --- LES COLLECTIONS, SANS DEPENDRE DE GALAXY ---------------------------------
|
|
|
|
|
#
|
|
|
|
|
# UN POSTE D'EXPLOITATION QUI APPELLE galaxy.ansible.com POUR SE CONSTRUIRE N'EST PAS
|
|
|
|
|
# SOUVERAIN. Mesure du 2026-08-23, premier deploiement : `ansible-galaxy collection
|
|
|
|
|
# install` a echoue depuis l'overlay de patient 0 —
|
|
|
|
|
# `SSL: UNEXPECTED_EOF_WHILE_READING` — parce que la frontiere ne laisse pas passer ce
|
|
|
|
|
# flux, et c'est tres bien ainsi. Ouvrir une regle vers un serveur americain pour que
|
|
|
|
|
# l'ecosysteme sache se reconstruire aurait ete la mauvaise reponse.
|
|
|
|
|
#
|
|
|
|
|
# MEME IDIOME QUE serveur_forgejo DEVANT SON PROPRE TIERS : le CONTROLEUR telecharge une
|
|
|
|
|
# fois, dans son cache, puis pousse par SSH. Aucun flux nouveau depuis la cible, et
|
|
|
|
|
# l'artefact devient deployable hors ligne — un poste peut se reconstruire sans internet
|
|
|
|
|
# du tout, ce qui est le sens meme d'une lignee autonome.
|
|
|
|
|
- name: Preparer le cache des collections sur le controleur
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: "{{ serveur_ops_cache_collections }}"
|
|
|
|
|
state: directory
|
|
|
|
|
mode: "0755"
|
|
|
|
|
delegate_to: localhost
|
|
|
|
|
become: false
|
|
|
|
|
run_once: true
|
|
|
|
|
|
|
|
|
|
# `argv` ET NON `cmd` : le chemin du controleur peut contenir une ESPACE (« Espace
|
|
|
|
|
# Chezlepro/… » chez le mainteneur), et `cmd` la lit comme un separateur d'arguments.
|
|
|
|
|
# Constate le 2026-08-23 : ansible-galaxy recevait « /home/…/Espace » puis
|
|
|
|
|
# « Chezlepro/… » comme deux arguments, et refusait — « positional collection_name arg
|
|
|
|
|
# and --requirements-file are mutually exclusive ». Le message ne parlait pas du tout du
|
|
|
|
|
# vrai probleme.
|
|
|
|
|
- name: Telecharger les collections dans le cache du controleur (une seule fois)
|
|
|
|
|
ansible.builtin.command:
|
|
|
|
|
argv:
|
|
|
|
|
- "ansible-galaxy"
|
|
|
|
|
- "collection"
|
|
|
|
|
- "download"
|
|
|
|
|
- "-r"
|
|
|
|
|
- "{{ serveur_ops_requirements_controleur }}"
|
|
|
|
|
- "-p"
|
|
|
|
|
- "{{ serveur_ops_cache_collections }}"
|
|
|
|
|
creates: "{{ serveur_ops_cache_collections }}/requirements.yml"
|
|
|
|
|
delegate_to: localhost
|
|
|
|
|
become: false
|
|
|
|
|
run_once: true
|
|
|
|
|
when: not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
- name: Deposer les collections sur le poste
|
2026-08-24 15:50:37 -04:00
|
|
|
register: serveur_ops_depot_collections
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
ansible.builtin.copy:
|
|
|
|
|
src: "{{ serveur_ops_cache_collections }}/"
|
|
|
|
|
dest: "{{ serveur_ops_racine }}/.collections-hors-ligne/"
|
|
|
|
|
owner: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
group: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
mode: "0644"
|
|
|
|
|
directory_mode: "0755"
|
|
|
|
|
when: not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
# `chdir` OBLIGATOIRE : le `requirements.yml` produit par `collection download` nomme les
|
|
|
|
|
# archives en RELATIF (`community-postgresql-4.2.0.tar.gz`), et ansible-galaxy les cherche
|
|
|
|
|
# depuis le repertoire COURANT, pas depuis celui du fichier. Sans chdir : « Could not find
|
|
|
|
|
# community-postgresql-4.2.0.tar.gz » alors que l'archive est bien la, a cote.
|
portabilite : declarer ce dont le moteur depend — quatre defauts reveles par le runner
Premiere materialisation d'une VM de tenant depuis le runner du SITE. Elle a
echoue quatre fois d'affilee, sur quatre dependances que le moteur ne declarait
nulle part. Chacune fonctionnait chez le mainteneur pour une raison DIFFERENTE,
et aucune de ces raisons n'existe sur une autre machine.
1. VERSIONS DES COLLECTIONS. `requirements.yml` les nommait sans les epingler. Le
runner a recu `community.general` 13.3.0 quand le poste porte la 10.3.0 — et la
11 a retire les modules Proxmox de cette collection.
ERROR! couldn't resolve module/action 'community.general.proxmox_pool'
2. INSTALLATION EN AVANT. `ansible-galaxy` ne retrograde pas : declarer la 10.3.0
ne suffisait pas a defaire une 13.3.0 deja posee. `--force`.
3. EMPLACEMENT. Le `Makefile` pose `ANSIBLE_HOME ?= $(CURDIR)/.ansible` : sous
`make`, Ansible ne lit QUE `<moteur>/.ansible/collections`. Le role deposait
dans `<racine>/.ansible/collections` — a cote, jamais lu. Invisible chez le
mainteneur, ou les collections viennent du paquet systeme, toujours dans le
chemin quel que soit ANSIBLE_HOME. Et le garde-fou d'installation suivait le
DEPOT des archives : changer la destination ne le declenchait pas. Il mesure
desormais la destination — meme piege qu'en 2026-08-24, deplace d'un cran.
4. BIBLIOTHEQUES PYTHON. Le venv recevait `ansible-core` et `pyyaml`, ecrits en
dur. Les modules Proxmox tournent `delegate_to: localhost` et exigent
`proxmoxer` SUR LE CONTROLEUR.
La bibliotheque Python proxmoxer est absente
Ne d'ici : `requirements-python.txt`, avec sa frontiere ecrite — il ne declare
QUE ce qui tourne sur le controleur. `python-ldap` et `psycopg2` s'executent
sur leurs cibles ; le poste du mainteneur ne les a pas et la flotte se deploie,
ce qui prouve que la ligne est au bon endroit.
P51 garde les trois faiblesses de cette famille : une dependance utilisee sans
etre declaree (le defaut du 2026-08-24, `ansible.posix`), une dependance declaree
sans version, et `proxmoxer` absent alors que des playbooks Proxmox existent.
Quatre controles negatifs verifies.
RESULTAT : ops-01 materialisee par le runner du site. L'agent invite rapporte
`eth0 10.17.19.41/24`, Debian 13 trixie — l'adressage derive du plan, applique.
Un seul executant masque ces ecarts indefiniment ; un second les revele tous en
une soiree. Meme mecanique que le second tenant en aout.
make prouver : CONFORME, 51 OK, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 22:38:35 -04:00
|
|
|
# LE GARDE-FOU DOIT SUIVRE LE RESULTAT, PAS LE GESTE (2026-08-27). La condition
|
|
|
|
|
# d'installation ne regardait que le DEPOT des archives. Le jour ou l'on a corrige le
|
|
|
|
|
# CHEMIN d'installation, les archives etaient inchangees : le role a donc conclu qu'il
|
|
|
|
|
# n'y avait rien a faire, et les collections sont restees a l'ancien endroit. Le meme
|
|
|
|
|
# piege qu'en 2026-08-24, deplace d'un cran. On mesure desormais la DESTINATION.
|
|
|
|
|
- name: Voir si les collections sont deja la ou le moteur les cherche
|
|
|
|
|
ansible.builtin.stat:
|
|
|
|
|
path: >-
|
|
|
|
|
{{ serveur_ops_racine }}/{{ (serveur_ops_depots | selectattr('role', 'eq', 'moteur')
|
|
|
|
|
| first).dest }}/.ansible/collections/ansible_collections/community/general/MANIFEST.json
|
|
|
|
|
register: serveur_ops_collections_en_place
|
|
|
|
|
become: true
|
|
|
|
|
become_user: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
- name: Installer les collections depuis le depot local (hors ligne)
|
|
|
|
|
ansible.builtin.command:
|
|
|
|
|
cmd: >-
|
|
|
|
|
{{ serveur_ops_venv }}/bin/ansible-galaxy collection install
|
collections : epingler les versions — le runner echouait la ou le poste reussissait
Premiere materialisation de VM depuis le runner du SITE :
ERROR! couldn't resolve module/action 'community.general.proxmox_pool'
Meme depot, meme playbook, meme plan que chez le mainteneur. La difference tenait
a une seule chose que le moteur ne disait pas : la VERSION de ses collections.
Le poste porte `community.general` 10.3.0. Le runner, monte un jour plus tard, a
recu la 13.3.0 — et la version 11 a RETIRE les modules Proxmox de cette collection
(ils vivent desormais dans `community.proxmox`). `requirements.yml` nommait ses
collections sans dire lesquelles : chaque machine installait donc ce qui etait
courant le jour de son montage. Une dependance non epinglee n'est pas une
dependance, c'est un pari sur l'etat d'Internet a la date du deploiement.
TROIS CORRECTIONS.
`requirements.yml` epingle les trois collections aux versions eprouvees.
`serveur_ops` installe avec `--force`. Sans lui, ansible-galaxy laisse en place une
version SUPERIEURE a celle demandee : il ne retrograde pas. Un poste peut etre en
avance, pas seulement en retard, et le depot doit faire autorite dans les deux sens.
P51 garde les deux faiblesses de ce fichier — celle du 2026-08-24, une collection
utilisee sans etre declaree (`ansible.posix`), et celle d'aujourd'hui, declaree sans
version. La preuve ne lit que les fichiers de TACHES : un `defaults/main.yml` porte
`net.ipv4.ip_forward`, qu'un motif trop large prend pour un module.
MIGRATION CONNUE, PAS FAITE : passer les quatre modules Proxmox a
`community.proxmox` permettra de suivre `community.general` au-dela de la 11.
make prouver : CONFORME, 51 OK, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 18:58:23 -04:00
|
|
|
-r requirements.yml --force
|
portabilite : declarer ce dont le moteur depend — quatre defauts reveles par le runner
Premiere materialisation d'une VM de tenant depuis le runner du SITE. Elle a
echoue quatre fois d'affilee, sur quatre dependances que le moteur ne declarait
nulle part. Chacune fonctionnait chez le mainteneur pour une raison DIFFERENTE,
et aucune de ces raisons n'existe sur une autre machine.
1. VERSIONS DES COLLECTIONS. `requirements.yml` les nommait sans les epingler. Le
runner a recu `community.general` 13.3.0 quand le poste porte la 10.3.0 — et la
11 a retire les modules Proxmox de cette collection.
ERROR! couldn't resolve module/action 'community.general.proxmox_pool'
2. INSTALLATION EN AVANT. `ansible-galaxy` ne retrograde pas : declarer la 10.3.0
ne suffisait pas a defaire une 13.3.0 deja posee. `--force`.
3. EMPLACEMENT. Le `Makefile` pose `ANSIBLE_HOME ?= $(CURDIR)/.ansible` : sous
`make`, Ansible ne lit QUE `<moteur>/.ansible/collections`. Le role deposait
dans `<racine>/.ansible/collections` — a cote, jamais lu. Invisible chez le
mainteneur, ou les collections viennent du paquet systeme, toujours dans le
chemin quel que soit ANSIBLE_HOME. Et le garde-fou d'installation suivait le
DEPOT des archives : changer la destination ne le declenchait pas. Il mesure
desormais la destination — meme piege qu'en 2026-08-24, deplace d'un cran.
4. BIBLIOTHEQUES PYTHON. Le venv recevait `ansible-core` et `pyyaml`, ecrits en
dur. Les modules Proxmox tournent `delegate_to: localhost` et exigent
`proxmoxer` SUR LE CONTROLEUR.
La bibliotheque Python proxmoxer est absente
Ne d'ici : `requirements-python.txt`, avec sa frontiere ecrite — il ne declare
QUE ce qui tourne sur le controleur. `python-ldap` et `psycopg2` s'executent
sur leurs cibles ; le poste du mainteneur ne les a pas et la flotte se deploie,
ce qui prouve que la ligne est au bon endroit.
P51 garde les trois faiblesses de cette famille : une dependance utilisee sans
etre declaree (le defaut du 2026-08-24, `ansible.posix`), une dependance declaree
sans version, et `proxmoxer` absent alors que des playbooks Proxmox existent.
Quatre controles negatifs verifies.
RESULTAT : ops-01 materialisee par le runner du site. L'agent invite rapporte
`eth0 10.17.19.41/24`, Debian 13 trixie — l'adressage derive du plan, applique.
Un seul executant masque ces ecarts indefiniment ; un second les revele tous en
une soiree. Meme mecanique que le second tenant en aout.
make prouver : CONFORME, 51 OK, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 22:38:35 -04:00
|
|
|
-p {{ serveur_ops_racine }}/{{ (serveur_ops_depots | selectattr('role', 'eq', 'moteur')
|
|
|
|
|
| first).dest }}/.ansible/collections
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
chdir: "{{ serveur_ops_racine }}/.collections-hors-ligne"
|
portabilite : declarer ce dont le moteur depend — quatre defauts reveles par le runner
Premiere materialisation d'une VM de tenant depuis le runner du SITE. Elle a
echoue quatre fois d'affilee, sur quatre dependances que le moteur ne declarait
nulle part. Chacune fonctionnait chez le mainteneur pour une raison DIFFERENTE,
et aucune de ces raisons n'existe sur une autre machine.
1. VERSIONS DES COLLECTIONS. `requirements.yml` les nommait sans les epingler. Le
runner a recu `community.general` 13.3.0 quand le poste porte la 10.3.0 — et la
11 a retire les modules Proxmox de cette collection.
ERROR! couldn't resolve module/action 'community.general.proxmox_pool'
2. INSTALLATION EN AVANT. `ansible-galaxy` ne retrograde pas : declarer la 10.3.0
ne suffisait pas a defaire une 13.3.0 deja posee. `--force`.
3. EMPLACEMENT. Le `Makefile` pose `ANSIBLE_HOME ?= $(CURDIR)/.ansible` : sous
`make`, Ansible ne lit QUE `<moteur>/.ansible/collections`. Le role deposait
dans `<racine>/.ansible/collections` — a cote, jamais lu. Invisible chez le
mainteneur, ou les collections viennent du paquet systeme, toujours dans le
chemin quel que soit ANSIBLE_HOME. Et le garde-fou d'installation suivait le
DEPOT des archives : changer la destination ne le declenchait pas. Il mesure
desormais la destination — meme piege qu'en 2026-08-24, deplace d'un cran.
4. BIBLIOTHEQUES PYTHON. Le venv recevait `ansible-core` et `pyyaml`, ecrits en
dur. Les modules Proxmox tournent `delegate_to: localhost` et exigent
`proxmoxer` SUR LE CONTROLEUR.
La bibliotheque Python proxmoxer est absente
Ne d'ici : `requirements-python.txt`, avec sa frontiere ecrite — il ne declare
QUE ce qui tourne sur le controleur. `python-ldap` et `psycopg2` s'executent
sur leurs cibles ; le poste du mainteneur ne les a pas et la flotte se deploie,
ce qui prouve que la ligne est au bon endroit.
P51 garde les trois faiblesses de cette famille : une dependance utilisee sans
etre declaree (le defaut du 2026-08-24, `ansible.posix`), une dependance declaree
sans version, et `proxmoxer` absent alors que des playbooks Proxmox existent.
Quatre controles negatifs verifies.
RESULTAT : ops-01 materialisee par le runner du site. L'agent invite rapporte
`eth0 10.17.19.41/24`, Debian 13 trixie — l'adressage derive du plan, applique.
Un seul executant masque ces ecarts indefiniment ; un second les revele tous en
une soiree. Meme mecanique que le second tenant en aout.
make prouver : CONFORME, 51 OK, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 22:38:35 -04:00
|
|
|
# INSTALLER LA OU LE MOTEUR REGARDE (2026-08-27). Le `Makefile` pose
|
|
|
|
|
# `export ANSIBLE_HOME ?= $(CURDIR)/.ansible` : sous `make`, Ansible ne cherche donc ses
|
|
|
|
|
# collections QUE dans `<moteur>/.ansible/collections`. Ce role les deposait dans
|
|
|
|
|
# `<racine>/.ansible/collections` — a cote, jamais lu. Le runner du SITE echouait ainsi
|
|
|
|
|
# sur `couldn't resolve module/action community.general.proxmox_pool` alors que la
|
|
|
|
|
# collection etait bel et bien installee, complete, et visible par `ansible-doc`.
|
|
|
|
|
#
|
|
|
|
|
# POURQUOI LE MAINTENEUR NE VOYAIT RIEN : sur son poste, les collections viennent du
|
|
|
|
|
# paquet systeme (`/usr/lib/python3/dist-packages/ansible_collections`), toujours dans
|
|
|
|
|
# le chemin de recherche quel que soit `ANSIBLE_HOME`. Le reglage du Makefile n'y a
|
|
|
|
|
# jamais eu de consequence. Sur un runner, ou rien n'est installe par la distribution,
|
|
|
|
|
# il decide de tout. Encore un ecart qu'on ne voit qu'en portant le moteur ailleurs.
|
|
|
|
|
#
|
collections : epingler les versions — le runner echouait la ou le poste reussissait
Premiere materialisation de VM depuis le runner du SITE :
ERROR! couldn't resolve module/action 'community.general.proxmox_pool'
Meme depot, meme playbook, meme plan que chez le mainteneur. La difference tenait
a une seule chose que le moteur ne disait pas : la VERSION de ses collections.
Le poste porte `community.general` 10.3.0. Le runner, monte un jour plus tard, a
recu la 13.3.0 — et la version 11 a RETIRE les modules Proxmox de cette collection
(ils vivent desormais dans `community.proxmox`). `requirements.yml` nommait ses
collections sans dire lesquelles : chaque machine installait donc ce qui etait
courant le jour de son montage. Une dependance non epinglee n'est pas une
dependance, c'est un pari sur l'etat d'Internet a la date du deploiement.
TROIS CORRECTIONS.
`requirements.yml` epingle les trois collections aux versions eprouvees.
`serveur_ops` installe avec `--force`. Sans lui, ansible-galaxy laisse en place une
version SUPERIEURE a celle demandee : il ne retrograde pas. Un poste peut etre en
avance, pas seulement en retard, et le depot doit faire autorite dans les deux sens.
P51 garde les deux faiblesses de ce fichier — celle du 2026-08-24, une collection
utilisee sans etre declaree (`ansible.posix`), et celle d'aujourd'hui, declaree sans
version. La preuve ne lit que les fichiers de TACHES : un `defaults/main.yml` porte
`net.ipv4.ip_forward`, qu'un motif trop large prend pour un module.
MIGRATION CONNUE, PAS FAITE : passer les quatre modules Proxmox a
`community.proxmox` permettra de suivre `community.general` au-dela de la 11.
make prouver : CONFORME, 51 OK, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 18:58:23 -04:00
|
|
|
# `--force` PARCE QU'UN POSTE PEUT ETRE EN AVANCE, PAS SEULEMENT EN RETARD (2026-08-27).
|
|
|
|
|
# Sans lui, `ansible-galaxy` laisse en place une collection deja installee dans une
|
|
|
|
|
# version SUPERIEURE a celle demandee : il ne retrograde pas. Le runner du SITE, monte
|
|
|
|
|
# avant que `requirements.yml` n'epingle ses versions, portait `community.general` 13.3.0
|
|
|
|
|
# — une version d'ou les modules Proxmox ont ete RETIRES. La premiere materialisation de
|
|
|
|
|
# VM depuis le runner a echoue la-dessus. Le depot doit faire autorite dans les DEUX
|
|
|
|
|
# sens : ce que `requirements.yml` declare est ce qui est installe, ni plus haut ni plus
|
|
|
|
|
# bas. Voir la preuve P51.
|
|
|
|
|
#
|
2026-08-24 15:50:37 -04:00
|
|
|
# LE GARDE-FOU SUIVAIT LA MAUVAISE CHOSE (2026-08-24). Il etait `creates: …/community/general` :
|
|
|
|
|
# une collection AJOUTEE a requirements.yml n'aurait jamais ete installee, puisque le
|
|
|
|
|
# repertoire temoin existait deja. Le runner serait reste en retard sur le moteur, en
|
|
|
|
|
# silence. On suit desormais le DEPOT des archives : si les collections deposees
|
|
|
|
|
# changent, on reinstalle.
|
|
|
|
|
changed_when: true
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
become: true
|
|
|
|
|
become_user: "{{ serveur_ops_utilisateur }}"
|
2026-08-24 15:50:37 -04:00
|
|
|
# DEUX `when` SUR UNE MEME TACHE, C'EST UN SEUL — LE DERNIER (2026-08-24). En ajoutant
|
|
|
|
|
# la condition sur le depot, j'ai laisse celle du check-mode juste en dessous : YAML
|
|
|
|
|
# garde la derniere cle et jette l'autre, en silence. `ansible-lint` l'a vu ; personne
|
|
|
|
|
# d'autre ne l'aurait vu. Les conditions vont donc dans UNE liste.
|
|
|
|
|
when:
|
|
|
|
|
- serveur_ops_depot_collections is changed
|
portabilite : declarer ce dont le moteur depend — quatre defauts reveles par le runner
Premiere materialisation d'une VM de tenant depuis le runner du SITE. Elle a
echoue quatre fois d'affilee, sur quatre dependances que le moteur ne declarait
nulle part. Chacune fonctionnait chez le mainteneur pour une raison DIFFERENTE,
et aucune de ces raisons n'existe sur une autre machine.
1. VERSIONS DES COLLECTIONS. `requirements.yml` les nommait sans les epingler. Le
runner a recu `community.general` 13.3.0 quand le poste porte la 10.3.0 — et la
11 a retire les modules Proxmox de cette collection.
ERROR! couldn't resolve module/action 'community.general.proxmox_pool'
2. INSTALLATION EN AVANT. `ansible-galaxy` ne retrograde pas : declarer la 10.3.0
ne suffisait pas a defaire une 13.3.0 deja posee. `--force`.
3. EMPLACEMENT. Le `Makefile` pose `ANSIBLE_HOME ?= $(CURDIR)/.ansible` : sous
`make`, Ansible ne lit QUE `<moteur>/.ansible/collections`. Le role deposait
dans `<racine>/.ansible/collections` — a cote, jamais lu. Invisible chez le
mainteneur, ou les collections viennent du paquet systeme, toujours dans le
chemin quel que soit ANSIBLE_HOME. Et le garde-fou d'installation suivait le
DEPOT des archives : changer la destination ne le declenchait pas. Il mesure
desormais la destination — meme piege qu'en 2026-08-24, deplace d'un cran.
4. BIBLIOTHEQUES PYTHON. Le venv recevait `ansible-core` et `pyyaml`, ecrits en
dur. Les modules Proxmox tournent `delegate_to: localhost` et exigent
`proxmoxer` SUR LE CONTROLEUR.
La bibliotheque Python proxmoxer est absente
Ne d'ici : `requirements-python.txt`, avec sa frontiere ecrite — il ne declare
QUE ce qui tourne sur le controleur. `python-ldap` et `psycopg2` s'executent
sur leurs cibles ; le poste du mainteneur ne les a pas et la flotte se deploie,
ce qui prouve que la ligne est au bon endroit.
P51 garde les trois faiblesses de cette famille : une dependance utilisee sans
etre declaree (le defaut du 2026-08-24, `ansible.posix`), une dependance declaree
sans version, et `proxmoxer` absent alors que des playbooks Proxmox existent.
Quatre controles negatifs verifies.
RESULTAT : ops-01 materialisee par le runner du site. L'agent invite rapporte
`eth0 10.17.19.41/24`, Debian 13 trixie — l'adressage derive du plan, applique.
Un seul executant masque ces ecarts indefiniment ; un second les revele tous en
une soiree. Meme mecanique que le second tenant en aout.
make prouver : CONFORME, 51 OK, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 22:38:35 -04:00
|
|
|
or not serveur_ops_collections_en_place.stat.exists
|
2026-08-24 15:50:37 -04:00
|
|
|
- not ansible_check_mode
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
|
|
|
|
|
# LES DEUX SYMLINKS (D-80). `instance` dit QUEL tenant on pilote. Le poste en pose un par
|
|
|
|
|
# défaut ; l'exploitant le bascule comme sur le poste du mainteneur.
|
site : le runner travaille, et le genome remonte chez lui
`serveur_ops` et `serveur_ops_site` sont deployes sur `site-ops-01` : le moteur,
les plans des trois tenants, les collections hors ligne, et la voute de
l'underlay deposee CHIFFREE. Le site a son runner.
DEUX FORMES DE RUNNER, ET UNE SEULE ETAIT PREVUE.
`serveur_ops` exigeait un depot `role: instance` et un `serveur_ops_instance` —
la forme d'un runner de TENANT, qui pilote un ecosysteme, monte son plan par le
lien `instance`, detient sa voute.
Un runner de SITE ne pilote rien : il MATERIALISE le terrain que d'autres
occuperont, et son inventaire est dynamique. Son plan declarait donc ses depots
de tenants en `role: tenant`, a dessein et avec ses raisons ecrites — et le role
le refusait au nom d'une exigence qui ne le concernait pas. Il exige desormais
que le runner pilote QUELQUE CHOSE, sans prescrire quoi.
Et il posait le lien quand meme : `serveur_ops_instance: ""` donnait
`instance -> /opt/setops/`, un repertoire qui n'est l'ecosysteme de personne. Un
lien qui existe et ne designe rien est pire qu'un lien absent : tout ce qui le
suit croit avoir trouve une instance.
LE CERTIFICAT COUVRE LES NOMS DU SERVICE.
`client_pki` ne mettait dans ses SAN que le FQDN, le nom court et l'IP. Le
clonage du genome a bute dessus : « certificate subject name
(site-forge-01.genese.internal) does not match target hostname
'forge.genese.internal' ». Le nom declare `expose:` etait publie partout —
plancher, zone DNS — et couvert nulle part.
Les expositions que cet hote SERT REELLEMENT entrent maintenant dans le
certificat. Un certificat qui revendiquerait le nom d'un service rendu ailleurs
serait une usurpation, pas une commodite.
`make genome-pousser` — LE RUNNER POUSSE, LE POSTE NE ROUTE PAS.
La forge du genome vit DANS le site, sur un reseau que le poste de l'exploitant
ne route pas. On ne perce pas un chemin pour lui : on lui retire le role. Le
poste emballe les commits dans un `git bundle` — un fichier, verifiable, qui ne
demande aucun reseau — et le runner verifie, avance EN AVANCE RAPIDE SEULEMENT,
puis pousse avec SA cle, autorisee en ecriture sur ces depots-la seulement.
Ce qui est pousse se DERIVE de `serveur_ops_depots`. `DEPOT=<nom>` en cible un
seul.
Trois pieges rencontres, tous inscrits dans le code : l'outil ne peut pas etre
supposé present sur le runner (il ne recevrait cette version qu'APRES la poussee
qu'elle sert a faire — le controleur le porte) ; la branche n'est pas toujours
`main` (deux depots vivent sur `master`, et le plan le declarait deja) ; le
dossier des depots freres contient un espace, d'ou `argv` et non `cmd`.
Le juge n'est pas le journal du playbook mais LA FORGE : on demande a son API ce
qu'elle porte, et on refuse si ca differe de ce que porte le runner. Six depots
verifies.
Pourquoi ca comptait : la forge du site etait restee quatre commits derriere le
poste, sans que rien ne le signale — dont le correctif qui desarme le pare-feu
Proxmox. Un ecosysteme qui se reproduit depuis une forge en retard reproduit ses
defauts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 08:52:37 -04:00
|
|
|
#
|
|
|
|
|
# UN RUNNER DE SITE N'EN A PAS (2026-08-26). Il ne pilote aucun écosystème — il matérialise
|
|
|
|
|
# le terrain — et son propre inventaire est DYNAMIQUE (`site_inventaire.py`). Son plan
|
|
|
|
|
# déclare donc `serveur_ops_instance: ""`, et c'est une réponse, pas un oubli.
|
|
|
|
|
#
|
|
|
|
|
# Sans la garde ci-dessous, la chaîne rendait `{{ racine }}/` + `""` : le lien `instance`
|
|
|
|
|
# pointait sur `/opt/setops/` lui-même — un répertoire qui n'est l'écosystème de personne.
|
|
|
|
|
# Mesuré le 2026-08-26 : `instance -> /opt/setops/`. Un lien qui existe et ne désigne rien
|
|
|
|
|
# est pire qu'un lien absent : tout ce qui le suit croit avoir trouvé une instance.
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
- name: Désigner l'instance pilotée par défaut
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
src: "{{ serveur_ops_racine }}/{{ serveur_ops_instance }}"
|
|
|
|
|
dest: >-
|
|
|
|
|
{{ serveur_ops_racine }}/{{ (serveur_ops_depots | selectattr('role', 'eq', 'moteur') | first).dest }}/instance
|
|
|
|
|
state: link
|
|
|
|
|
owner: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
group: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
force: true
|
site : le runner travaille, et le genome remonte chez lui
`serveur_ops` et `serveur_ops_site` sont deployes sur `site-ops-01` : le moteur,
les plans des trois tenants, les collections hors ligne, et la voute de
l'underlay deposee CHIFFREE. Le site a son runner.
DEUX FORMES DE RUNNER, ET UNE SEULE ETAIT PREVUE.
`serveur_ops` exigeait un depot `role: instance` et un `serveur_ops_instance` —
la forme d'un runner de TENANT, qui pilote un ecosysteme, monte son plan par le
lien `instance`, detient sa voute.
Un runner de SITE ne pilote rien : il MATERIALISE le terrain que d'autres
occuperont, et son inventaire est dynamique. Son plan declarait donc ses depots
de tenants en `role: tenant`, a dessein et avec ses raisons ecrites — et le role
le refusait au nom d'une exigence qui ne le concernait pas. Il exige desormais
que le runner pilote QUELQUE CHOSE, sans prescrire quoi.
Et il posait le lien quand meme : `serveur_ops_instance: ""` donnait
`instance -> /opt/setops/`, un repertoire qui n'est l'ecosysteme de personne. Un
lien qui existe et ne designe rien est pire qu'un lien absent : tout ce qui le
suit croit avoir trouve une instance.
LE CERTIFICAT COUVRE LES NOMS DU SERVICE.
`client_pki` ne mettait dans ses SAN que le FQDN, le nom court et l'IP. Le
clonage du genome a bute dessus : « certificate subject name
(site-forge-01.genese.internal) does not match target hostname
'forge.genese.internal' ». Le nom declare `expose:` etait publie partout —
plancher, zone DNS — et couvert nulle part.
Les expositions que cet hote SERT REELLEMENT entrent maintenant dans le
certificat. Un certificat qui revendiquerait le nom d'un service rendu ailleurs
serait une usurpation, pas une commodite.
`make genome-pousser` — LE RUNNER POUSSE, LE POSTE NE ROUTE PAS.
La forge du genome vit DANS le site, sur un reseau que le poste de l'exploitant
ne route pas. On ne perce pas un chemin pour lui : on lui retire le role. Le
poste emballe les commits dans un `git bundle` — un fichier, verifiable, qui ne
demande aucun reseau — et le runner verifie, avance EN AVANCE RAPIDE SEULEMENT,
puis pousse avec SA cle, autorisee en ecriture sur ces depots-la seulement.
Ce qui est pousse se DERIVE de `serveur_ops_depots`. `DEPOT=<nom>` en cible un
seul.
Trois pieges rencontres, tous inscrits dans le code : l'outil ne peut pas etre
supposé present sur le runner (il ne recevrait cette version qu'APRES la poussee
qu'elle sert a faire — le controleur le porte) ; la branche n'est pas toujours
`main` (deux depots vivent sur `master`, et le plan le declarait deja) ; le
dossier des depots freres contient un espace, d'ou `argv` et non `cmd`.
Le juge n'est pas le journal du playbook mais LA FORGE : on demande a son API ce
qu'elle porte, et on refuse si ca differe de ce que porte le runner. Six depots
verifies.
Pourquoi ca comptait : la forge du site etait restee quatre commits derriere le
poste, sans que rien ne le signale — dont le correctif qui desarme le pare-feu
Proxmox. Un ecosysteme qui se reproduit depuis une forge en retard reproduit ses
defauts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 08:52:37 -04:00
|
|
|
when:
|
|
|
|
|
- serveur_ops_instance | default('') | trim | length > 0
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
# Et s'il n'y en a pas, le lien ne doit pas SURVIVRE d'un passage precedent : un runner
|
|
|
|
|
# qu'on reconfigure en runner de site garderait sinon un lien perime vers un tenant.
|
|
|
|
|
- name: Retirer le lien `instance` quand le poste ne pilote aucun écosystème
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: >-
|
|
|
|
|
{{ serveur_ops_racine }}/{{ (serveur_ops_depots | selectattr('role', 'eq', 'moteur') | first).dest }}/instance
|
|
|
|
|
state: absent
|
|
|
|
|
when:
|
|
|
|
|
- serveur_ops_instance | default('') | trim | length == 0
|
|
|
|
|
- not ansible_check_mode
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
|
2026-08-23 12:24:28 -04:00
|
|
|
# LE SECOND SYMLINK. Sans lui, le poste sait configurer des machines qui existent ; il ne
|
|
|
|
|
# sait pas en creer, faute de savoir sur quelle fabric les poser. C'est la difference
|
|
|
|
|
# entre exploiter et engendrer.
|
|
|
|
|
- name: Désigner la fabric sur laquelle l'écosystème repose
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
src: "{{ serveur_ops_racine }}/{{ serveur_ops_underlay }}/underlay.yml"
|
|
|
|
|
dest: >-
|
|
|
|
|
{{ serveur_ops_racine }}/{{ (serveur_ops_depots | selectattr('role', 'eq', 'moteur') | first).dest }}/underlay.yml
|
|
|
|
|
state: link
|
|
|
|
|
owner: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
group: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
force: true
|
|
|
|
|
when:
|
|
|
|
|
- serveur_ops_underlay | length > 0
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
|
serveur_ops : la difference entre une archive et une matrice
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.
Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.
setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.
Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.
Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00
|
|
|
# --- LA CLÉ DU POSTE ---------------------------------------------------------
|
|
|
|
|
#
|
|
|
|
|
# Le poste se fabrique sa propre paire, distincte de celle du mainteneur. Deux
|
|
|
|
|
# exploitants, deux clés : on peut révoquer l'un sans couper l'autre — et l'accès du
|
|
|
|
|
# poste se lit dans les `authorized_keys` de la flotte, au lieu de se confondre avec
|
|
|
|
|
# celui d'un humain.
|
|
|
|
|
#
|
|
|
|
|
# `ssh-keygen` plutôt que `community.crypto.openssh_keypair` : le dépôt ne requiert que
|
|
|
|
|
# `community.postgresql` et `community.general`, et fabriquer une paire de clés ne
|
|
|
|
|
# justifie pas d'imposer une collection de plus à tout écosystème qui déploie un poste.
|
|
|
|
|
- name: Assurer le répertoire SSH du poste
|
|
|
|
|
ansible.builtin.file:
|
|
|
|
|
path: "{{ serveur_ops_racine }}/.ssh"
|
|
|
|
|
state: directory
|
|
|
|
|
owner: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
group: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
mode: "0700"
|
|
|
|
|
|
|
|
|
|
- name: Fabriquer la clé SSH du poste
|
|
|
|
|
ansible.builtin.command:
|
|
|
|
|
cmd: >-
|
|
|
|
|
ssh-keygen -t {{ serveur_ops_cle_type }} -N ''
|
|
|
|
|
-C "setops@{{ inventory_hostname }}.{{ domaine_interne }}"
|
|
|
|
|
-f {{ serveur_ops_racine }}/.ssh/id_{{ serveur_ops_cle_type }}
|
|
|
|
|
creates: "{{ serveur_ops_racine }}/.ssh/id_{{ serveur_ops_cle_type }}"
|
|
|
|
|
become: true
|
|
|
|
|
become_user: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
when:
|
|
|
|
|
- serveur_ops_cle_generer | bool
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
register: serveur_ops_cle
|
|
|
|
|
|
|
|
|
|
- name: Relire la clé publique du poste
|
|
|
|
|
ansible.builtin.slurp:
|
|
|
|
|
src: "{{ serveur_ops_racine }}/.ssh/id_{{ serveur_ops_cle_type }}.pub"
|
|
|
|
|
register: serveur_ops_pub
|
|
|
|
|
when:
|
|
|
|
|
- serveur_ops_cle_generer | bool
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
# ÉCRIRE, PUIS RELIRE (D-68) — et rendre le résultat EXPLOITABLE. Cette clé ne sert à
|
|
|
|
|
# rien tant qu'elle n'est pas autorisée sur la flotte : on l'affiche pour que l'exploitant
|
|
|
|
|
# la reprenne dans les intrants, au lieu de la laisser dormir sur le disque.
|
|
|
|
|
- name: La clé publique à autoriser sur la flotte
|
|
|
|
|
ansible.builtin.debug:
|
|
|
|
|
msg:
|
|
|
|
|
- "Clé publique du poste d'exploitation — à ajouter aux intrants SSH du plan :"
|
|
|
|
|
- "{{ serveur_ops_pub.content | b64decode | trim }}"
|
|
|
|
|
when:
|
|
|
|
|
- serveur_ops_cle_generer | bool
|
|
|
|
|
- not ansible_check_mode
|
|
|
|
|
|
|
|
|
|
- name: Déposer le mode d'emploi sur le poste
|
|
|
|
|
ansible.builtin.template:
|
|
|
|
|
src: LISEZ-MOI.md.j2
|
|
|
|
|
dest: "{{ serveur_ops_racine }}/LISEZ-MOI.md"
|
|
|
|
|
owner: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
group: "{{ serveur_ops_utilisateur }}"
|
|
|
|
|
mode: "0644"
|