Mesure sur le terrain : chaque runner lit son depot en SSH avec sa cle de deploiement, et la forge lui refuse les autres, alors meme que les depots sont publics. Le role ne clone plus en HTTPS que les depots publics ; les depots instance, tenant et hebergeur passent en SSH, cle d'hote epinglee, commande SSH posee dans leur config git. Avant l'armement, le controleur les apporte en git bundle. La cle d'hote de la forge est declaree au plan du site et offerte par la fiche. genome_etat et genome_pousser lisent l'API authentifies ; la sonde genome-servi compte les publics ; forge_amorcer cree prives les depots des ecosystemes et du site. make forge-etancheite mesure le tout. Les depots restent publics. 95 preuves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
143 lines
9 KiB
Markdown
143 lines
9 KiB
Markdown
# Dépôts privés sur la forge du site — conception du chantier
|
|
|
|
> **Pour qui :** le mainteneur qui décide de ce chantier puis le conduit, et quiconque se demande
|
|
> pourquoi un runner ne lit que ses propres dépôts.
|
|
|
|
Préparé le 2026-10-11. Décisions D1 à D3 prises le même jour par Daniel : les trois recommandations.
|
|
|
|
## 1. Le constat
|
|
|
|
Sur la forge du site, l'organisation `genome` porte cinq dépôts, tous **publics** :
|
|
|
|
| Dépôt | Contenu | Qui en a besoin |
|
|
|---|---|---|
|
|
| `set-ops-public` | le moteur | tous les runners |
|
|
| `set-ops-modeles` | les modèles génériques | le runner du site |
|
|
| `site-chezlepro` | la carte de la fabric, le plan du site | le runner du site |
|
|
| `ops-chezlepro` | le plan, l'inventaire et la face de Chezlepro | son runner, le runner du site |
|
|
| `ops-technolibre` | le plan, l'inventaire et la face de Technolibre | son runner, le runner du site |
|
|
|
|
Mesuré le 2026-10-11 : depuis le runner de Technolibre, `git ls-remote` sans identifiant lit la
|
|
tête de `ops-chezlepro` (`b4fbd85`) et de `site-chezlepro` (`51dae24`). Chaque locataire peut donc
|
|
lire le plan de l'autre, et la carte du site. **Aucun n'en a besoin** : chaque runner de locataire
|
|
ne clone que le moteur et son propre dépôt ; ce que le site lui donne arrive par la fiche déposée
|
|
dans son dépôt.
|
|
|
|
D'où ça vient : le 2026-09-12, à la première reconstruction du site, les dépôts créés privés ont
|
|
cassé le clonage anonyme des runners. Ils sont passés publics, avec l'argument que seuls ceux
|
|
qui ont franchi la frontière joignent la forge (`scripts/forge_amorcer.py`). Les autres locataires
|
|
en font partie.
|
|
|
|
## 2. La cible
|
|
|
|
- **Publics** : `set-ops-public` et `set-ops-modeles`. Ils sont génériques, identiques pour tous.
|
|
- **Privés** : `site-chezlepro` et chaque `ops-<locataire>`.
|
|
- **Le runner du site** lit et pousse tous les dépôts avec sa clé, déjà enregistrée comme clé de
|
|
déploiement en écriture par `genome_pousser.yml`. Mesuré le 2026-10-11 : il lit les cinq dépôts
|
|
en SSH, avec une vérification stricte de la clé d'hôte. Rien à créer pour lui.
|
|
- **Le runner d'un locataire** lit son seul dépôt, avec une clé de déploiement **en lecture
|
|
seule** : la clé publique de son runner, déjà déclarée au plan (`ssh_baseline_cles_admin`) et
|
|
dont la privée lui est remise à l'armement depuis sa voûte (`vault_runner_cle_ssh`).
|
|
- **Aucun secret ne change de main.** Le locataire publie la clé publique de son runner dans sa
|
|
face réseau ; le site l'enregistre sur le dépôt de ce locataire, avec ses propres
|
|
identifiants d'administration de la forge (`vault_forgejo_admin`, déjà dans sa voûte).
|
|
|
|
### Éprouvé le 2026-10-11 (étape 1)
|
|
|
|
Clés de lecture enregistrées par `make forge-cles`, flux posé sur `site-forge-01` et à la
|
|
frontière. Depuis chaque runner, `git ls-remote` en SSH, clé d'hôte de la forge épinglée (lue
|
|
sur sa machine par l'accès d'administration) :
|
|
|
|
| Depuis | son dépôt | l'autre locataire | `site-chezlepro` | `set-ops-public` |
|
|
|---|---|---|---|---|
|
|
| runner de Technolibre | lu (`0172dd8`) | refusé | refusé | refusé |
|
|
| runner de Chezlepro | lu (`74d5567`) | refusé | refusé | refusé |
|
|
|
|
Le refus vient de la forge (« Deploy Key … is not authorized to read »), **alors que les dépôts
|
|
sont encore publics** : une clé de déploiement ne vaut que pour le dépôt qui l'a enregistrée.
|
|
Conséquence : le moteur, public, continue de se cloner en HTTPS sans identifiant ; seuls les
|
|
dépôts privés passent par SSH.
|
|
|
|
## 3. Le nœud : l'insémination
|
|
|
|
Le site amorce le runner d'un locataire **avant** que celui-ci ait reçu sa clé stable (elle
|
|
arrive à l'armement, geste humain, après). Pendant l'insémination, le rôle `serveur_ops` clone
|
|
pourtant le dépôt du locataire : avec un dépôt privé, ce clonage échoue. Même chose au premier
|
|
déploiement du runner du site, dont la clé est neuve.
|
|
|
|
**Remède proposé : le colis.** Quand un runner ne peut pas encore lire un dépôt privé, le
|
|
contrôleur qui joue `serveur_ops` (le runner du site pendant l'insémination, le poste
|
|
ailleurs) lui apporte ce dépôt en `git bundle`. Le mécanisme existe déjà : `genome_colis.py` porte
|
|
le génome du poste au runner du site. Le runner clone le colis, puis pointe `origin` vers l'URL
|
|
SSH de la forge. Ses tirages suivants passent par sa clé, une fois armé.
|
|
|
|
## 4. Les décisions à prendre
|
|
|
|
**D1 — Comment le runner d'un locataire lit-il son dépôt ?**
|
|
- *Clé de déploiement en SSH (recommandé).* Le runner continue de tirer lui-même ; il garde son
|
|
autonomie (émancipation, `make` lancé sur le runner, garde `verifier_genome_a_jour`). Coût : un
|
|
flux nouveau, du runner de chaque locataire vers la forge du site, en SSH.
|
|
- *Colis seulement.* Aucun flux nouveau, aucune clé de déploiement pour les locataires : le
|
|
contrôleur apporte toujours le dépôt. Mais le runner ne tire plus son dépôt lui-même, et sa
|
|
garde de génome n'a plus de forge à laquelle se comparer.
|
|
|
|
**D2 — Sur quelle écoute SSH ?**
|
|
- *Le `sshd` de la machine, port 22 (recommandé pour commencer).* Le runner du site et le poste
|
|
l'utilisent déjà pour pousser ; l'utilisateur `git` y est contraint par la forge. Le flux
|
|
n'ouvre que les adresses des runners de locataires, pas leurs supernets.
|
|
- *Le serveur SSH intégré de Forgejo, sur un port dédié.* Il n'expose pas le `sshd` de la
|
|
machine, mais sa cohabitation avec le `sshd` existant reste à éprouver avant de s'y fier.
|
|
|
|
**D3 — La preuve.** Ce chantier touche l'insémination : je propose de le prouver par une
|
|
reconstruction complète de Technolibre (raser, créer, inséminer, armer, monter), dépôts
|
|
privés, avant de reprendre le lot 3b.
|
|
|
|
## 5. Ce qui change dans le code
|
|
|
|
État au 2026-10-11 : tout ce tableau est écrit, sauf la bascule elle-même. La clé d'hôte de
|
|
la forge est déclarée dans le plan du site (`forge_ssh_cle_hote`), offerte par la fiche
|
|
(`serveur_ops_forge_cle_hote`) et copiée par chaque locataire. Le moteur reste cloné en HTTPS.
|
|
|
|
| Pièce | Changement |
|
|
|---|---|
|
|
| `serveur_ops_depots` | un drapeau `prive: true` sur les dépôts `instance`, `tenant` et `hebergeur` |
|
|
| `roles/serveur_ops` | URL SSH et clé du runner pour les dépôts privés ; colis du contrôleur quand le runner ne peut pas encore les lire ; clé d'hôte de la forge épinglée |
|
|
| `contexte.py` (face) | la face publie la clé publique de lecture du runner (`genome.cle_lecture`) |
|
|
| `contexte.py` (fiche) | la fiche du site publie la clé d'hôte SSH de sa forge, que le runner du locataire épingle |
|
|
| nouvelle cible `forge-cles` | le site enregistre, d'après les faces, la clé de lecture de chaque locataire sur son dépôt, et retire celles qui ne sont plus publiées |
|
|
| `forge_amorcer.py` | crée les dépôts privés comme privés |
|
|
| flux | `serveur_forge_site` : entrée SSH depuis les runners des locataires hébergés (paire nouvelle, résolue depuis les faces) ; `serveur_ops` : sortie correspondante |
|
|
| `genome_etat.yml` | lit la forge par SSH ou authentifié : l'API anonyme répondrait 404 pour un dépôt privé |
|
|
| `sonde-genome-servi` | ne compte plus que les dépôts publics (au moins le moteur) : c'est ce qu'un écosystème neuf clone sans rien détenir ; les privés sont suivis par `genome-etat`, `forge-cles` et les runners |
|
|
|
|
Inchangés : `sonde-genome-a-jour` (son repère ne compare que `set-ops-public`), le poste (il
|
|
pousse déjà en SSH), la console (`etat_forge` lit `origin`, qui deviendra l'URL SSH).
|
|
|
|
## 6. Les preuves à écrire
|
|
|
|
- **Hors ligne (`make prouver`)** : chaque dépôt `instance`, `tenant` ou `hebergeur` est déclaré
|
|
privé ; chaque face publie une clé de lecture, et cette clé est dans `ssh_baseline_cles_admin`.
|
|
- **Sur le terrain (`make forge-etancheite`)**, avec témoins :
|
|
- sans identifiant, un dépôt privé refuse et un dépôt public répond ;
|
|
- le runner d'un locataire lit son dépôt et **ne lit pas** celui de l'autre ;
|
|
- les clés de déploiement de chaque dépôt sont exactement : runner du site en écriture, runner
|
|
du locataire en lecture.
|
|
- **Par reconstruction** : D3.
|
|
|
|
## 7. L'ordre de bascule
|
|
|
|
Chaque étape se vérifie avant la suivante, et la bascule se défait d'un appel par dépôt
|
|
(repasser public).
|
|
|
|
1. **Éprouver** sur la forge du site, sans rien basculer : enregistrer la clé de lecture du
|
|
runner de Technolibre sur `ops-technolibre`, ouvrir le flux pour ce seul runner, et mesurer
|
|
qu'il lit son dépôt en SSH.
|
|
2. **Construire** le code et les preuves (§5, §6) ; `make verifier`.
|
|
3. **Déployer sans basculer** : flux et frontière (`make frontiere-appliquer CONFIRMER=true`,
|
|
lancé par Daniel), clés de déploiement, remotes SSH sur les trois runners. Les dépôts sont
|
|
encore publics : chaque runner doit déjà tirer en SSH.
|
|
4. **Basculer** `site-chezlepro`, `ops-chezlepro` et `ops-technolibre` en privé. Mesurer avec
|
|
`make forge-etancheite`, puis la veille des trois consoles.
|
|
5. **Prouver** par la reconstruction de Technolibre (D3).
|
|
6. Reprendre le lot 3b : les demandes vivent alors dans le dépôt de chaque locataire, lisibles
|
|
par lui et par le site seulement.
|