OPS-Patient0/README.md
Daniel Allaire 163383185c artefacts : la forge sert aussi les binaires
serveur_artefacts colocalise sur forge-01. Toute la flotte prend ses paquets
Debian dans l'ecosysteme. Eprouve en coupant l'amont.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 14:42:26 -04:00

164 lines
7.6 KiB
Markdown

# OPS-Patient0 — l'écosystème d'origine
> **Pour qui :** l'**exploitant** de la lignée. Ce dépôt est le plan d'un écosystème
> Set-OPS comme les autres — mais de celui dont les autres descendent.
## Ce qu'il est
Patient 0 est le **plus petit écosystème complet** : une PKI, un DNS, un edge, une
**forge**, et un **poste d'exploitation**. Cinq machines. Sa raison d'être tient en une
phrase :
> porter les dépôts qui fabriquent les écosystèmes, et les servir à ses enfants.
Un tenant ordinaire existe pour ses gens : Chezlepro héberge de l'identité, du courriel,
de la collaboration. Patient 0 n'héberge que **la lignée**.
## Ce qu'il remplace
Aujourd'hui encore, tout ce qui fabrique Chezlepro dépend de `eregion.chezlepro.ca` — une
machine **hors flotte**, montée à la main, que Set-OPS ne déploie pas, ne sauvegarde pas
et ne prouve pas. C'est un point unique de défaillance, situé exactement là où il fait le
plus mal : à la racine.
Patient 0 le remplace par un écosystème **bâti par le moteur, sauvegardé par le moteur,
vérifié par le harnais**. On ne déplace pas le point unique de défaillance : on l'élimine.
## La boucle, et comment elle se casse
Pour rebâtir patient 0, il faut le dépôt du moteur — qui vit sur patient 0. On n'échappe
pas à ça par la ruse, mais par le **nombre**. Le génome doit exister en au moins trois
endroits vivants, sans coordination :
```
patient 0 (la forge mère) · le poste de l'exploitant · restic hors cluster
+ chaque écosystème enfant, qui en porte un miroir
```
N'importe quel survivant réamorce les autres. Une famille, pas un maître.
## État au 2026-08-23 : matérialisé
Les cinq machines tournent. L'adressage dérive du seul seed `index: 29` — supernet
`10.29.0.0/16`, zones en `10.29.(15+zone).0/24`, VLAN `1290+zone`.
| machine | fonction | adresse | ce qu'elle porte |
|---|---|---|---|
| `infra-edge-01` | infra-edge | `10.29.16.11` | nginx — publie `forge.genese.internal` |
| `infra-dns-01` | infra-dns | `10.29.19.11` | PowerDNS autoritatif |
| `infra-pki-01` | infra-pki | `10.29.19.21` | step-ca — l'autorité interne |
| `ops-01` | ops | `10.29.19.41` | le **poste d'exploitation** |
| `forge-01` | forge | `10.29.21.11` | Forgejo — le génome, **et** le cache d'artefacts |
**Forgejo tourne sur SQLite**, pas sur une VM PostgreSQL dédiée : une base qu'une
poignée de personnes sollicite ne justifie pas un serveur, une zone, un secret et une
sauvegarde de plus. Moins de surface sur la machine dont tout descend.
**Ni courriel ni base de données centrale.** Le plan en a porté au stade projet ; ils ont
été retirés. Patient 0 n'a pas d'usagers à notifier.
**Sauvegarde** : `infra-pki-01` et `forge-01` poussent leur état vers
`eregion.chezlepro.ca` — les deux seules machines qui détiennent quelque chose
d'irremplaçable (les clés de l'AC, les dépôts).
**Il est hébergé par la fabric de Chezlepro** (`SITE-Chezlepro`), au même titre qu'un
autre tenant. Il n'a pas d'underlay à lui.
**Il sert ses propres binaires.** `forge-01` porte aussi la source d'artefacts
(apt-cacher-ng) : toute la flotte y prend ses paquets Debian au lieu d'aller chez Debian.
La forge est la source, du code **et** des binaires. Éprouvé en coupant l'amont — un
paquet en cache est servi en `0 o/s`, un paquet absent est refusé par un `503`.
**Il résout par lui-même.** Les quatre hôtes clients interrogent un Unbound local, qui
tient la zone `genese.internal` de `infra-dns-01` et **récurse depuis les serveurs
racine** pour le reste — `forward-addr` = 0, aucun résolveur tiers n'est consulté.
`infra-dns-01` reste hors du groupe : un autoritatif ne se résout pas auprès de lui-même
par un récurseur local.
## Le génome, sur sa forge
Les dépôts vivent sous l'organisation `genome` :
| dépôt | miroir de l'amont |
|---|---|
| `set-ops-public` | **oui** — toutes les 8 h |
| `ops-patient0` | **oui** — toutes les 8 h |
| `site-chezlepro` | **oui** — toutes les 8 h, authentifié |
| `set-ops-modeles` | **oui** — toutes les 8 h, authentifié |
| `ops-chezlepro` | non, et privé — le plan d'un tenant voisin, sans usage ici |
Les quatre miroirs suivent `forge.alliance-boreale.ca`. Les deux dépôts privés sont lus
par un jeton de **lecture seule** (`vault_miroir_amont`, portée unique
`read:repository`) : un jeton capable d'écrire chez le parent inverserait le sens de la
filiation — l'enfant pourrait réécrire le génome dont il est issu.
Les quatre restent **lisibles** sur la forge de patient 0, et c'est ainsi que son poste
d'exploitation les clone : en anonyme, sans détenir aucun justificatif.
L'étiquette signée `v2026.08.21` a traversé le miroir intacte — la provenance reste
vérifiable depuis l'enfant.
## Le poste d'exploitation
`ops-01` porte `/opt/setops` : Ansible épinglé (core 2.18), le génome cloné **depuis sa
propre forge**, et les deux symlinks de D-80.
```
Set-OPS-public/instance -> OPS-Patient0 quel tenant on pilote
Set-OPS-public/underlay.yml -> SITE-Chezlepro/… sur quelle fabric il repose
```
Ce qu'il **n'a pas**, et n'aura jamais : le mot de passe de la voûte, saisi à
l'exécution ; le fichier de voûte lui-même, hors dépôt ; `underlay.vault.yml`, les
secrets du monde physique. Il lit la **carte** de la fabric, jamais ses **clés**.
D'où une ligne nette, mesurée depuis la machine :
```
make instancier DIFF VIDE : le plan reproduit exactement l'inventaire actuel
make underlay-plan refusé — aucune voûte
```
Il reproduit sa propre structure sans aucun secret. Il ne touche pas à la fabric sans
qu'un humain apporte la clé.
## Ce que ce dépôt contient, et ce qu'il ne contiendra jamais
| | |
|---|---|
| `plan/` | les cinq machines, leurs zones, leurs applications |
| `inventories/production/group_vars/` | les intrants, le placement Proxmox, le **gabarit** de voûte |
| `inventories/production/hosts.yml` | **généré** depuis le plan — ne jamais l'éditer à la main |
| `parente.yml` | de quels dépôts, à quels commits, cet écosystème descend |
| la voûte et son mot de passe | **jamais**. Ni ici, ni dans aucun dépôt : c'est le seul objet que la reproduction exige d'un humain |
Conséquence à connaître, et qui n'est pas un défaut :
```
la STRUCTURE se reconstruit depuis la forge
les SECRETS se restaurent depuis la sauvegarde (restic)
```
Deux sources distinctes, qu'un même incident n'atteint pas ensemble.
## Deux réglages à connaître
**`index: 29`** — tout l'adressage en dérive. Choisi libre : 13 est le lab, 17 Chezlepro,
23 Technolibre. Les index bas (1, 11) ont déjà forcé deux renumérotages, ils tombaient
dans des plages occupées par du matériel.
**`federe: true`** — patient 0 est pris en compte par les devis du site : la frontière,
le SDN et le pare-feu de l'hyperviseur lui réservent ses zones. Il est resté à `false`
tant qu'il n'était qu'un plan, et a été basculé **avant** `make sdn-appliquer` — sinon
ses VLAN n'auraient existé nulle part.
## Ce qui reste devant
- [ ] **Décider où il vit.** Sur `asgard`, la perte du cluster emporte patient 0 *et*
Chezlepro d'un coup. Ailleurs, la famille survit à la perte du cluster. Le
déménagement tient en **trois** valeurs de `group_vars/proxmox.yml` — nœud, stockage,
gabarit. Le pont n'en fait pas partie : chaque VM atterrit sur le VNet dérivé de sa
zone.
- [ ] **Les dépôts tiers en HTTPS** (Smallstep, Grafana, Icinga) vont encore en direct :
les faire passer par le cache demande de réécrire leurs sources en
`http://cache/<remap>/…`. Les dépôts Debian, eux, sont couverts.