Set-OPS-Public/docs/depots-prives-conception.md
Daniel Allaire d7717a4f98 serveur_ops : les depots prives se lisent en SSH, ou arrivent en colis
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>
2026-10-11 20:33:38 -04:00

9 KiB

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.