diff --git a/.gitignore b/.gitignore index 1f72769..1004996 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,3 @@ *.key *.vault.yml.bak -flux-genere/ diff --git a/COLLECTE.md b/COLLECTE.md index fad2f02..fbb3cec 100644 --- a/COLLECTE.md +++ b/COLLECTE.md @@ -1,28 +1,26 @@ # À relever sur place — TechnoLibre **Tout ce qui pouvait être décidé l'a été le 2026-09-13.** Ce qui suit n'est pas un -choix : ce sont des FAITS que seul le matériel peut dire. Treize valeurs, pas trente-cinq. +choix : ce sont des FAITS que seul le matériel peut dire. Quinze valeurs : deux cartes, l'adresse du WAN, dix noms d'interface, deux paires de jetons. | Ce qu'il faut | Où le lire | Pourquoi personne ne peut le décider | |---|---|---| | `<>` | `ip -br link` sur le nœud | Le nom de la carte réseau dépend du matériel (`eno1`, `enp1s0`…) | | `<>` | OPNsense, interface WAN | Donnée par le fournisseur d'accès | -| `<>` | OPNsense, interface de gestion | Dépend du plan d'adressage existant sur place | -| `<>` ×9 | OPNsense → Interfaces → Assignments | Les noms `optN` sont attribués dans l'ordre de création | -| `<>` | Idem | Selon que la patte de gestion est la LAN d'origine ou une autre | +| `<>` ×10 | OPNsense → Interfaces → Assignments | Les noms `optN` sont attribués dans l'ordre de création | | `proxmox_api_token_id` | Datacenter → Permissions → API Tokens | Délivré par le nœud à la création | | `proxmox_api_token_secret` | Idem — **affiché une seule fois** | Ne se relit jamais ; le noter tout de suite | | `vault_opnsense_api_key` | System → Access → Users → api keys | Délivré par la frontière | | `vault_opnsense_api_secret` | Téléchargé avec la clé, même fichier | Idem | **Le piège des `optN`.** Le devis raisonne en ARRIVÉE : une règle posée sur la mauvaise -patte ne correspond jamais, et rien ne le signale. Relever les neuf noms exacts avant de +patte ne correspond jamais, et rien ne le signale. Relever les dix noms exacts avant de poser quoi que ce soit, y compris celui de la patte face au nœud Proxmox — elle manquait chez Chezlepro et toutes les règles entrantes des locataires tombaient dans le vide. -**Ce qui est mesuré, pas relevé.** `local-lvm` accueille quinze clones complets, soit -environ 600 Go. Vérifier `vgs` et `df -h` AVANT de lancer la matérialisation : c'est la -seule décision de ce document qui peut encore changer, et elle se prend avec un chiffre. +**Ce qui est mesuré, pas relevé.** Relevé le 2026-10-13 : `local-lvm` ne fait que 130 Go. +Les VM vont sur `nvme` (LVM-thin, NVMe 465 Go), `site-backup-01` sur `miroir` (ZFS, 2 × 12 +To). Revérifier `pvesm status` AVANT de lancer la matérialisation. **Les quatre jetons vont dans la voûte**, pas dans un fichier de plan : @@ -43,15 +41,15 @@ prendre. Les dix autres secrets du site sont déjà engendrés. | | Valeur | Raison | |---|---|---| | Index du site | `31` | Les sites prennent leur propre index depuis le 2026-09-12 | -| Plan d'administration | `10.31.0.0/24` | **Un seul** — frontière `.1`, nœud `.41`, passerelle amont `.254` | +| Plan d'administration | `10.31.0.0/24` | **Un seul** — frontière `.1`, nœud `.11`, commutateur `.111` — passerelle de tous : la frontière | | Adresse du poste | une secondaire dans `10.31.0.0/24` | De là, l'API Proxmox, la frontière et le rebond sont tous joignables | -| Nœud Proxmox | `atelier` | À poser comme nom d'hôte à l'installation | -| Frontière | `portail` | Étiquette dans la carte ; l'OPNsense peut garder son nom réel | +| Nœud Proxmox | `maurice` | Nom d'hôte posé à l'installation (2026-10-13) | +| Frontière | `requin` | Nom d'hôte de l'OPNsense (2026-10-13) | | Domaine du site | `socle.internal` | Distinct de `technolibre.internal`, qui est au locataire | | Routage des locataires | `sdn` (EVPN sur le nœud) | Sans commutateur L3, le mode `switch` obligerait la frontière à porter douze interfaces routées | | ASN | `65031` | Dérivé de l'index — deux sites reliés ne peuvent pas collisionner | | Contrôleur EVPN | `EVPN0031` | Objet de cluster : nommé d'après le site, pas d'après son premier locataire | -| Pont | `vmbr0` | Un seul, VLAN-aware — sans seconde carte, d'autres ponts ne sépareraient rien | +| Ponts | `vmbr0` sur `nic0`, `vmbr1` sur `nic2` | Administration en 1G ; les VLAN des VM en 10G, VLAN-aware | | Gabarit | `99998` | Le même dans toute la flotte | --- @@ -59,16 +57,14 @@ prendre. Les dix autres secrets du site sont déjà engendrés. ## 1. Le chiffre qui décide de tout ``` -SITE 7 VM 20 Go RAM 776 Go provisionnés -tenant 14 VM 37 Go RAM 460 Go provisionnés - ───────────────────────────────────────── -TOTAL 21 VM 57 Go RAM ~1,2 To +SITE 9 VM 23 Go RAM 816 Go provisionnés +chaque locataire ~14 VM ~37 Go RAM ~460 Go provisionnés ``` Sur trois nœuds ça se répartit. Sur **un seul**, la même machine porte tout — et la RAM est la contrainte dure (le disque se dégonfle en provisionnement fin, pas la mémoire). -- [ ] **RAM physique du nœud** : ______ Go → si < 64, décider de réduire AVANT de câbler +- [x] **RAM physique du nœud** : **256 Go** (2 × 128, ASUS Z10PE-D16 WS) — la mémoire n'est plus la contrainte - [ ] **Espace libre du stockage `images`** : ______ Go (viser 1,2 To ; 800 Go à la rigueur) ## 2. L'hyperviseur @@ -108,6 +104,16 @@ Ce qu'il y a entre le nœud Proxmox et l'OPNsense décide du mode de routage : - [ ] **SDN EVPN sur le nœud** → indépendant du matériel, mais jamais éprouvé sur un nœud unique +**Relevé du 2026-10-13** : `caillou`, commutateur de couche 2 seulement (4 × 2,5G, 4 × SFP+), +entre `requin` (`ix0`) et `maurice` (`nic2`) ; les VLAN 31 à 37 et 40 y passent étiquetés, +prouvés par ARP depuis `maurice` (témoin : VLAN 99, sans réponse). + +- [ ] **Le VLAN 1 (administration) traverse encore les deux ports SFP+** du lien des zones, + non étiqueté : les diffusions du poste arrivent sur `nic2` et sur `ix0` (mesuré en + faisant émettre le poste pendant l'écoute). Retirer le VLAN 1 des MEMBRES de ces deux + ports, pas seulement du natif ; natif = un VLAN sans autre membre (999). Remis à plus + tard par Daniel le 2026-10-13. + ## 5. Cohabitation d'adressage - [ ] `ip route` sur le poste de Mathieu — quelles plages `10.x` sont déjà prises ? diff --git a/PREMIERE-HEURE.md b/PREMIERE-HEURE.md index 688c974..22f14f7 100644 --- a/PREMIERE-HEURE.md +++ b/PREMIERE-HEURE.md @@ -14,24 +14,18 @@ parlera de réseau alors qu'il s'agira d'une patte manquante. ## 0 · Se poser sur son réseau d'administration -Avant tout, donner au poste une adresse secondaire — c'est de là que tout se fait. - -``` -sudo ip addr add 10.31.0.17/24 dev -``` - -De cette adresse tu atteindras la frontière (`.1`), le nœud (`.41`) et, plus tard, le -rebond vers les machines du site. C'est exactement ce que tu fais déjà chez toi avec -`10.17.0.17` et `10.37.0.17`. +Le poste est branché sur `caillou`, carte filaire en `10.31.0.101/24` — c'est de là que +tout se fait. De cette adresse on atteint la frontière (`.1`), le nœud (`.11`) et, plus +tard, le rebond vers les machines du site. > À relever avant : l'adresse **actuelle** des deux machines, pour pouvoir y revenir si > une manœuvre coupe l'accès. --- -## 1 · La frontière — `portail` +## 1 · La frontière — `requin` -### 1.1 Les huit pattes +### 1.1 Les neuf pattes Une par zone, plus le plan d'administration et le transit. **Le dernier octet est toujours `.1`** : c'est l'invariant dont le devis dérive les règles. @@ -46,14 +40,29 @@ Une par zone, plus le plan d'administration et le transit. **Le dernier octet es | service | 34 | `10.31.34.1/24` | les noms | | sauvegarde | 35 | `10.31.35.1/24` | le dépôt | | supervision | 36 | `10.31.36.1/24` | le témoin | +| publication | 37 | `10.31.37.1/24` | l'edge et le DNS public du site | + +**Le câblage du 2026-10-13** : deux ports, deux rôles. + +- **`igc0` (LAN, 2,5G)** : l'administration seule, `10.31.0.1/24`, branchée sur `caillou` + (VLAN 1 non étiqueté). Aucun VLAN de zone n'y est posé. +- **`ix0` (SFP+ 10G, non assigné)** : branché sur un SFP+ de `caillou`, comme `nic2` de `maurice` + (`vmbr1`) — le chemin des zones est `ix0` → `caillou` → `nic2`. Les pattes des zones sont + des **interfaces VLAN posées sur `ix0`** : `vlan031` à `vlan037`, et `vlan040` pour le + transit (OPNsense impose le préfixe `vlan0`). `caillou` porte aussi le VLAN 40. Assignées + le 2026-10-13 : `opt1` = `vlan040`, `opt2` à `opt8` = `vlan031` à `vlan037` ; `ix0` + lui-même n'est plus assigné. Non étiqueté, `ix0` + est dans le VLAN 1 de `caillou`, celui de l'administration : il ne reçoit pas d'adresse. + +`caillou` est déjà réglé : on n'y touche pas. ### 1.2 Relever les noms d'interface — le piège du jour -Dans **Interfaces → Assignments**, noter le nom `optN` attribué à **chacune** des huit, +Dans **Interfaces → Assignments**, noter le nom `optN` attribué à **chacune** des neuf, transit compris. > Le devis raisonne en **arrivée** : une règle posée sur la mauvaise patte ne correspond -> jamais, et rien ne le signale. Ces neuf noms vont dans `opnsense.yml`, et ils doivent +> jamais, et rien ne le signale. Ces dix noms vont dans `opnsense.yml`, et ils doivent > être exacts. ### 1.3 Le compte d'API @@ -73,13 +82,24 @@ ANSIBLE_VAULT_IDENTITY_LIST="$(python3 scripts/voutes.py identites)" \ ### 1.4 L'accès SSH -Le rebond vers les machines du site passe par la frontière. Créer l'utilisateur `ansible` -avec accès shell, et y poser cette clé publique : +Le rebond vers les machines du site passe par la frontière, et `frontiere_pki.py` y lit +`config.xml` par `sudo`. Dans **System → Access → Users**, l'utilisateur `ansible` (le même +que celui de l'API) reçoit : + +- **Login shell** : `/bin/sh` ; +- **Group membership** : `admins` ; +- **Authorized keys** : cette clé publique : ``` ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICf8ecGQ555LuTDaFaqzc3SG+wy0Y8ECqmsIRxemc0dM Cle ansible pour le royaume technolibre ``` +Puis, dans **System → Settings → Administration** : + +- **Secure Shell** : activé, sur l'interface LAN seulement ; connexion root refusée, + mot de passe refusé (clé seulement) ; +- **Sudo** : `No password`, pour le groupe `admins`. + Vérifier ensuite, depuis le poste : ``` @@ -88,24 +108,26 @@ ssh ansible@10.31.0.1 'echo ok; sudo -n true && echo "sudo ok"' --- -## 2 · Le nœud — `atelier` +## 2 · Le nœud — `maurice` ### 2.1 Le nom d'hôte -`atelier` — c'est ce que le plan déclare, et l'API l'utilise comme identifiant dans ses -chemins. Un autre nom oblige à corriger `proxmox-hebergeur.yml`. +`maurice` (posé à l'installation) — c'est ce que le plan déclare, et l'API l'utilise comme +identifiant dans ses chemins. Un autre nom oblige à corriger `proxmox-hebergeur.yml`. ### 2.2 Les adresses -Un seul pont, **VLAN-aware**, portant tout : +Deux ponts, une carte chacun : -| Réseau | VLAN | Adresse | -|---|---|---| -| administration | — | `10.31.0.41/24` — passerelle `10.31.0.1` | -| transit | 40 | `10.0.4.41/24` | -| transport VXLAN | 50 | `10.31.50.41/24` | +| Pont | Carte | Rôle | Adresse | +|---|---|---|---| +| `vmbr0` | `nic0` (1G) | administration seule | `10.31.0.11/24` — passerelle `10.31.0.1` | +| `vmbr1` | `nic2` (10G) | les VLAN des VM (31 à 37) | aucune | -> `vmbr0` doit être **VLAN aware** : sans cela les VLAN des zones ne traverseront pas, et +Sur `vmbr1`, plus tard : le transit (VLAN 40, `10.0.4.11/24`) et le transport VXLAN +(VLAN 50, `10.31.50.11/24`). + +> `vmbr1` doit être **VLAN aware** : sans cela les VLAN des zones ne traverseront pas, et > les VM naîtront sur un réseau muet. ### 2.3 Le compte d'API @@ -125,12 +147,38 @@ Le **secret n'est affiché qu'une fois**. Il va dans la voûte, sous > après des `403` pendant le déploiement. Le resserrer ensuite est un rôle sur mesure, dix > minutes — et c'est un geste à faire, pas une intention. -### 2.4 Le gabarit doré +### 2.4 Le compte `ansible` du nœud + +L'API ne fait pas tout : le SDN, le pare-feu du nœud et ses métriques se posent par SSH. +Même compte qu'au site de Chezlepro — `ansible`, par clé, `sudo` sans mot de passe : + +``` +apt install -y sudo +useradd -m -s /bin/bash ansible +install -d -m 700 -o ansible -g ansible /home/ansible/.ssh +echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICf8ecGQ555LuTDaFaqzc3SG+wy0Y8ECqmsIRxemc0dM Cle ansible pour le royaume technolibre' \ + > /home/ansible/.ssh/authorized_keys +chown ansible:ansible /home/ansible/.ssh/authorized_keys +chmod 600 /home/ansible/.ssh/authorized_keys +echo 'ansible ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/ansible +chmod 440 /etc/sudoers.d/ansible +visudo -cf /etc/sudoers.d/ansible +``` + +Vérifier depuis le poste : + +``` +ssh -i ~/.ssh/id_ed25519_ansible_technolibre ansible@10.31.0.11 'hostname; sudo -n true && echo "sudo ok"' +``` + +Attendu : `maurice`, puis `sudo ok`. + +### 2.5 Le gabarit doré Depuis la clé USB, dossier `gabarits/` : ``` -qmrestore vzdump-qemu-9006-*.vma.zst 9006 --storage local-lvm +qmrestore vzdump-qemu-9006-*.vma.zst 9006 --storage nvme qm template 9006 qm config 9006 | grep -E '^(name|machine|bios|template)' ``` @@ -140,20 +188,21 @@ Attendu : `name=modeleSetOPS-minimal`, `machine=q35`, `bios=ovmf`, `template=1`. > `--storage` est **obligatoire** : le disque vient d'un Ceph qui n'existe pas ici. > Et `qm template` est ce qui rend la VM clonable — sans lui, le clonage refusera. -### 2.5 Mesurer avant de matérialiser +### 2.6 Mesurer avant de matérialiser ``` vgs ; df -h ``` -Quinze clones **complets** demandent environ 600 Go. C'est la seule décision de ce document -qui peut encore changer, et elle se prend avec un chiffre sous les yeux. +Les neuf machines du site demandent 816 Go en clones **complets** : 416 Go sur `nvme`, et +les 400 Go de `site-backup-01` sur `miroir`. Chaque locataire repris demande environ 460 Go +de plus — il ne tiendra pas sur le NVMe, et devra aller sur `miroir`. --- ## 3 · Renseigner ce qu'on a relevé -Dans `opnsense.yml` — les neuf noms d'interface et les deux adresses de la frontière. +Dans `opnsense.yml` — les dix noms d'interface et les deux adresses de la frontière. Dans la voûte — les quatre jetons. Puis, depuis `Set-OPS-public` avec le lien `underlay.yml` pointant sur ce site : @@ -173,9 +222,9 @@ python3 scripts/devis_sdn.py --verifier | Index du site | `31` | | Domaine | `socle.internal` | | Routage des locataires | `sdn` — EVPN sur le nœud, ASN `65031`, contrôleur `EVPN0031` | -| Pont | `vmbr0`, VLAN-aware | -| Stockage | `local-lvm` | +| Ponts | `vmbr0` (administration, `nic0`) ; `vmbr1` (VM, `nic2`), VLAN-aware | +| Stockage | `nvme` (LVM-thin, NVMe 465 Go) pour les VM ; `miroir` (ZFS, 2 × 12 To) pour `site-backup-01` | | Gabarit | `9006` — `99998` est son précédent, jamais cloné | -Dix des quatorze secrets du site sont déjà engendrés. Les quatre restants sont les jetons -ci-dessus. +Quatorze des dix-huit secrets du site sont déjà engendrés. Les quatre restants sont les +jetons ci-dessus. diff --git a/README.md b/README.md index 4fe289c..8da8f3a 100644 --- a/README.md +++ b/README.md @@ -33,61 +33,80 @@ de quoi reconstruire des machines vides. Un site de reprise sans la donnée reprend l'infrastructure, pas le service. C'est la question à trancher avant de qualifier ce site de « site de reprise » devant quiconque. +## Refait le 2026-10-12 sur le modèle de `SITE-Chezlepro` + +Le dépôt de septembre ne suivait plus les méthodes du moteur : schéma de la carte +(`nature`, `segment_physique`), zone de publication, edge et DNS public du site, +`domaines.yml`, `mainteneurs.yml`, réglages de la frontière. Il porte désormais **les mêmes +fichiers, les mêmes zones et les mêmes noms de VM** qu'au site de Chezlepro — un exploitant +qui connaît l'un connaît l'autre. Seuls changent l'index (`31`), le domaine +(`socle.internal`), les noms des équipements (`requin`, `maurice`, `caillou`) et ce que +seul le matériel peut dire (`<<…>>`, voir `COLLECTE.md`). + +On le juge **sans toucher au lien** `underlay.yml` du moteur : + +``` +SETOPS_UNDERLAY=../SITE-Technolibre/underlay.yml python3 scripts/prouver.py +``` + +Quatre écarts y restent, et ils sont **attendus** pour un site de reprise : les locataires +désignent encore le site de Chezlepro, où ils tournent (P37, P69, P73, P79). + ## Ce qui le distingue du site de Chezlepro -| | Chezlepro | Technolibre | +| | Chezlepro | TechnoLibre | |---|---|---| -| Nœuds Proxmox | 3 (asgard, gandalf, vishnu) | **1** | +| Nœuds Proxmox | 3 (asgard, gandalf, vishnu) | **1** — `maurice`, ASUS Z10PE-D16 WS, 2 CPU, **2 × 128 Go** | | Version | PVE 8.4 | **PVE 9** | -| Stockage partagé | Ceph NVMe + TrueNAS iSCSI | **local au nœud** | +| Stockage | Ceph NVMe + TrueNAS iSCSI | **local au nœud** : `nvme` (VM), `miroir` ZFS 2 × 12 To (sauvegardes) | | Clones | liés, sur stockage partagé | **complets** — pas d'autre nœud pour porter le gabarit | -| Frontière | OPNsense | OPNsense | +| Frontière | OPNsense (`bifrost-1`) | OPNsense sur **QOTOM** (`requin`) — 5 × 2,5G, 4 × SFP+ 10G | +| Adresse publique | fixe (pool de quatre) | **dynamique** — face fixe : le relais (VPS), à confirmer | Trois conséquences directes : -1. **Le SPOF est total et assumé.** Le gabarit, ses clones et le site entier sont sur la - même machine. Perdre le nœud, c'est tout perdre — d'où l'importance du dépôt de - sauvegarde hors nœud dès le premier jour. +1. **Le point unique de panne est total et assumé.** Perdre le nœud, c'est tout perdre — + d'où le dépôt de sauvegarde hors nœud dès le premier jour. 2. **`clone_complet: true`.** Un clone lié dépend à vie de son gabarit ; sans second nœud, - ce lien n'achète rien et coûte une dépendance. -3. **Proxmox 9 n'a jamais été éprouvé.** Le moteur n'analyse aucune version et n'appelle - que des chemins d'API stables, mais c'est la première fois. Surveiller le pare-feu - (`proxmox-firewall` nftables depuis la 9) et le SDN (passé GA). + ce lien n'achète rien. +3. **Proxmox 9 n'a jamais été éprouvé ici.** Surveiller le pare-feu (`proxmox-firewall` + nftables) et le SDN. -## Le chiffre à vérifier en premier +## Le chiffre ``` -SITE 7 VM 20 Go RAM 776 Go provisionnés -tenant 14 VM 37 Go RAM 460 Go provisionnés - ───────────────────────────────────────── -TOTAL 21 VM 57 Go RAM ~1,2 To +SITE 9 VM 23 Go RAM 816 Go provisionnés +OPS-Chezlepro ~14 VM ~37 Go RAM ~460 Go \ reprise : l'un, l'autre, +OPS-Technolibre ~14 VM ~37 Go RAM ~460 Go / ou les deux + ─────────────────────────────── +TOTAL ~37 VM ~97 Go RAM ~1,7 To ``` -Sur un seul nœud, la même machine porte tout, et **la RAM est la contrainte dure**. En -dessous de 64 Go, il faut décider de réduire avant de câbler, pas pendant le déploiement. +Avec 256 Go, **la mémoire n'est plus la contrainte** : le site peut reprendre les deux +locataires à la fois. Le disque, lui, est à mesurer (`vgs ; df -h`). ## L'adressage -- **Gestion** : `10.31.0.0/24` — l'index du SITE, distinct de celui de son locataire - (23). Le plan d'administration de l'hébergeur ne vit plus chez un de ses clients. -- **Zones du site** : `10.31.31` à `10.31.36` — **même forme que Chezlepro** (le 3e octet - reste le numéro de VLAN), avec l'index du site au 2e octet. - > Décision du 2026-09-12 : sites et locataires se partagent la classe A, chacun avec son - > propre index. Les deux sites peuvent donc être reliés (§8 du guide) sans renumérotage. -- **Chemins** (transit) : `10.0.4.0/24`, comme chez Chezlepro. +- **Administration** : `10.31.0.0/24`, non étiquetée — frontière `.1` (`requin`), nœud + `.11` (`maurice`), poste de l'exploitant `.101`, commutateur `.111` (`caillou`). +- **Zones du site** : `10.31.31` à `10.31.37` (VLAN 31 à 37) — le 3e octet est le VLAN, + comme chez Chezlepro. `.1` = la frontière, mêmes derniers octets que chez Chezlepro pour les + VM (`site-forge-01` = `.33.11`, `site-edge-01` = `.37.11`…). +- **Transit** : `10.0.4.0/24` (VLAN 40) ; **VXLAN** : `10.31.50.0/24` (VLAN 50). -## L'ordre des gestes, le jour J +## L'ordre des gestes -1. Remplir `COLLECTE.md` **en entier** — une ligne vide bloque plus tard, ailleurs. -2. Reporter les valeurs dans `underlay.yml`, `plan/10-intrants.yml`, `opnsense.yml`. -3. Trancher le mode de routage devant le matériel (`COLLECTE.md` §4). -4. Gabarit : vérifier ou fabriquer (`docs/procedure-template-debian13-proxmox.md`). -5. Voûte : y déposer les deux paires de secrets, jamais dans git. -6. `make underlay` — le devis lit le site réel et refuse ce qui ne concorde pas. -7. `make site-creer CONFIRMER=true`, puis le socle. +1. `PREMIERE-HEURE.md` : adresses de la frontière et du nœud, comptes d'API et SSH. +2. Reporter dans `opnsense.yml` les **dix** noms `optN`, et dans `underlay.yml` les cartes du + nœud (`<>`). +3. Voûte : les quatre jetons (Proxmox, OPNsense) — les quatorze autres secrets y sont. +4. `make underlay`, puis le harnais (ci-dessus) — il refuse ce qui ne concorde pas. +5. `make site-creer CONFIRMER=true`, puis le socle et les services. +6. Une fois `site-pki-01` en place : `scripts/frontiere_pki.py` (autorité de la frontière, + syslog, exportateur, interface), puis `opnsense_api_verifier_certs: true`. ## Voir aussi - `docs/preparer-un-site-hebergeur.md` — ce qu'un hébergeur doit fournir -- `docs/implanter-un-tenant-sur-un-site.md` — y poser `OPS-Technolibre` ensuite +- `docs/implanter-un-tenant-sur-un-site.md` — y poser un locataire - `docs/hebergeur-exploitation.md` — l'exploitation courante diff --git a/opnsense.yml b/opnsense.yml index 648f661..2460969 100644 --- a/opnsense.yml +++ b/opnsense.yml @@ -1,25 +1,80 @@ -# Intrants de la frontière de Technolibre (OPNsense). -# Les SECRETS (clé et secret d'API) ne vivent PAS ici : voûte chiffrée de l'instance. +# Intrants de la frontiere du site de TechnoLibre (OPNsense sur QOTOM : 5 ports 2,5G, 4 SFP+ 10G). +# Memes cles qu'au site de Chezlepro (refait sur son modele le 2026-10-12). +# Les SECRETS (cle et secret d'API) ne vivent PAS ici : `underlay.vault.yml`. --- -opnsense_api_url: https://<> -opnsense_wan_ip: <> +opnsense_api_key: '{{ vault_opnsense_api_key }}' +opnsense_api_secret: '{{ vault_opnsense_api_secret }}' +opnsense_api_url: https://10.31.0.1 +# FAUX JUSQU'A CE QUE LA FRONTIERE SOIT CERTIFIEE : elle sert d'abord le certificat +# auto-signe d'OPNsense. `scripts/frontiere_pki.py` lui donne son autorite (signee par la +# racine de CE site, une fois site-pki-01 en place) puis l'interface passe au certificat de +# services ; alors seulement, mettre `true` — comme au site de Chezlepro le 2026-10-12. +opnsense_api_verifier_certs: false -# L'interface d'arrivée de chaque zone. D-61 : le devis raisonne en ARRIVÉE, donc une -# règle posée sur la mauvaise patte ne correspond JAMAIS — et rien ne le signale. -# Relever les noms exacts (`optN`) dans Interfaces > Assignments. +# L'INTERFACE D'ARRIVEE DE CHAQUE ZONE. Le devis raisonne en ARRIVEE : une regle posee sur la +# mauvaise patte ne correspond JAMAIS, et rien ne le signale. MESURE le 2026-10-13 dans +# `config.xml` de `requin`, pas devine : OPNsense attribue les `optN` a l'assignation. +# Les zones sont des VLAN poses sur `ix0` (SFP+ 10G), qui rejoint `caillou` puis `nic2` de +# `maurice` ; `ix0` lui-meme n'est plus assigne. +opnsense_if_gestion: lan # igc0, GESTION +opnsense_if_transit: opt1 # vlan040, TENANTS opnsense_if_zones: - site-pilotage: <> - site-autorite: <> - site-genome: <> - site-service: <> - site-sauvegarde: <> - site-supervision: <> - # La patte face au nœud Proxmox — par où arrive TOUT le trafic des locataires. - # Elle manquait chez Chezlepro et les règles entrantes des tenants ne correspondaient - # à rien : la poser dès le premier jour. - transit-frontiere: <> + site-pilotage: opt2 # vlan031, PILOTAGE + site-autorite: opt3 # vlan032, AUTORITE + site-genome: opt4 # vlan033, GENOME + site-service: opt5 # vlan034, SERVICE + site-sauvegarde: opt6 # vlan035, SAUVEGARDE + site-supervision: opt7 # vlan036, SUPERVISION + site-publication: opt8 # vlan037, PUBLICATION + # La patte face au noeud — par ou arrive TOUT le trafic des locataires. Elle manquait chez + # Chezlepro le premier jour et les regles entrantes des locataires tombaient dans le vide. + transit-frontiere: opt1 # vlan040, TENANTS +# AUCUNE PATTE « SITE » PLATE ICI. Chez Chezlepro, `opnsense_if_site` nomme l'ancienne patte +# du /24 d'avant les zones (vlan030) ; ce site est ne avec ses zones et n'en a pas. Le devis +# s'en sert encore en repli et pour la sortie DNS du site : la cle reste un MARQUEUR, que le +# devis rend visible, plutot qu'une patte inventee — a trancher au premier devis. +opnsense_if_site: <> +opnsense_if_wan: wan -opnsense_if_transit: <> -opnsense_if_wan: wan -opnsense_if_gestion: <> -opnsense_if_site: <> +opnsense_silences: + - nom: wan + interface: wan + motif: >- + Refus par defaut du WAN. Le balayage d'Internet est permanent ; le refus par defaut reste + CONSIGNE sur toutes les interfaces internes, ou il sert au diagnostic. + - nom: relais + interface: opt9 + motif: >- + La face publique arrive par le relais : le balayage d'Internet aussi. Meme refus muet + que le WAN — mesure le 2026-10-13, des balayages consignes sur les trois adresses + relayees des la premiere minute du tunnel. + +# L'exportateur de metriques de la frontiere (greffon os-node_exporter), sur sa patte de +# supervision ; `frontiere_pki.py` le passe en HTTPS. +opnsense_exportateur_metriques: + patte: site-supervision + port: 9100 + +# LA FACE PUBLIQUE PASSE PAR LE RELAIS (2026-10-13). Le WAN (`igc4`) n'a qu'une adresse +# DHCP, derriere un reseau prive amont : il sert la SORTIE du site (apt, mises a jour), rien +# d'autre. Les adresses fixes sont louees sur un VPS d'OVH et arrivent par le tunnel `wg0`, +# assigne `opt9` (RELAIS) — voir le reseau `relais` de `underlay.yml`. +# +# `interface` : la ou le devis pose ce que le site publie (regles entrantes, redirections, +# poignees de main des tunnels d'administration, traduction sortante des locataires). +# `passerelle` : le `reply-to` de chacune de ces regles. SANS LUI, la requete entre et la +# reponse repart par la route par defaut — le WAN — et se perd : mesure le 2026-10-13, trois +# pings depuis l'Internet arrives sur `wg0`, zero reponse, jusqu'a `replyto: RELAIS_GW`. +# C'est aussi la sortie des locataires repris : tout leur trafic passe par le relais, pour +# qu'ils gardent UNE adresse vue de l'exterieur (decision de Daniel, 2026-10-13). +opnsense_face_publique: + interface: opt9 + passerelle: RELAIS_GW + +# L'adresse publique du SITE — relayee, comme les autres. +opnsense_wan_ip: 51.79.45.193 +# Le pool des locataires, pour une reprise. Un locataire repris ici RECOIT cette adresse par +# le contrat du site (`make site-intrants`) a la place de celle qu'il a au site de Chezlepro. +opnsense_ips_publiques: + 51.79.45.194: OPS-Chezlepro + 51.79.58.151: OPS-Technolibre diff --git a/plan/10-intrants.yml b/plan/10-intrants.yml index c8bb296..257df73 100644 --- a/plan/10-intrants.yml +++ b/plan/10-intrants.yml @@ -1,59 +1,60 @@ -# Intrants de base du SITE-Technolibre — les valeurs-racines dont tout le reste dérive. -# ⚠ Ce qui est marqué <<…>> est à relever sur place. Voir COLLECTE.md. +# Intrants de base du SITE-Technolibre — les valeurs-racines dont tout le reste derive. +# Memes cles qu'au site de Chezlepro (refait sur son modele le 2026-10-12). +# Ce qui ne peut exister qu'apres un premier deploiement est laisse vide, et dit quand le poser. --- -# LE DOMAINE INTERNE DU SITE, pas celui de son locataire. Chezlepro utilise -# `genese.internal` ; deux sites qui porteraient le même nom de zone ne pourraient pas -# coexister dans un même résolveur. Proposition : `technolibre.site` ou `atelier.internal`. +# LE DOMAINE INTERNE DU SITE, pas celui d'un locataire. Chezlepro utilise `genese.internal` ; +# deux sites qui porteraient le meme nom de zone ne pourraient pas coexister dans un meme +# resolveur — et une reprise les fait justement se rencontrer. domaine_interne: socle.internal organisation: TechnoLibre -# Par où l'administration entre. Chez Chezlepro c'est la patte LAN de la frontière ; -# ici ce sera la patte de gestion de l'OPNsense (10.23.0.1) ou un accès direct. +# Le resolveur que les VM interrogent a leur premiere mise en route, avant que celui du site +# n'existe : la frontiere, comme chez Chezlepro. +dns_amorcage: 10.31.0.1 + +# Par ou l'administration entre : la patte d'administration de la frontiere. rebond: ansible@10.31.0.1 -# LE NOM REEL DE LA CLE, pas un nom plausible. Celle-ci existe sur le poste et sert -# deja a la flotte de TechnoLibre ; `~/.ssh/technolibre` ne designait rien. +# LE NOM REEL DE LA CLE. Celle-ci existe sur le poste et sert deja a la flotte de TechnoLibre. cle_ssh: ~/.ssh/id_ed25519_ansible_technolibre integrations_exemptes: {} -# La clé publique du runner du site — GÉNÉRÉE au premier déploiement de `site-ops-01`, -# puis recopiée ici. Laisser vide au départ : c'est normal. +# La cle publique du runner du site — GENEREE au premier deploiement de `site-ops-01`, puis +# recopiee ici (et dans `cles_admin`). Vide au depart : c'est normal. runner_cle_publique: "" +# `forge_ssh_cle_hote` : la cle d'hote SSH de la forge, relevee apres le premier deploiement +# de `site-forge-01` — comme au site de Chezlepro. Absente tant que la forge n'existe pas. -# LE GABARIT. Sur un nœud unique il n'y a pas d'autre machine pour le porter : -# ne jamais le personnaliser, et ne jamais convertir une VM i440fx en q35. +# LE GABARIT. Sur un noeud unique il n'y a pas d'autre machine pour le porter : ne jamais le +# personnaliser, et ne jamais convertir une VM i440fx en q35. gabarit: - # LE MEME GABARIT QUE LE RESTE DE LA FLOTTE. 99998 est son PRECEDENT — garde ici - # pour que l'on sache d'ou l'on vient, jamais clone. + # LE MEME GABARIT QUE LE RESTE DE LA FLOTTE. 99998 est son PRECEDENT — garde ici pour que + # l'on sache d'ou l'on vient, jamais clone. vmid: 9006 precedent: 99998 nom: modeleSetOPS-minimal - noeud: atelier + noeud: maurice machine: q35 bios: ovmf - stockage: local-lvm + stockage: nvme -# Clé publique du compte de dépôt des sauvegardes du site lui-même — générée au -# déploiement de `site-backup-01`, recopiée ensuite. # LA MOITIE PUBLIQUE de la paire de sauvegarde du site. Sa jumelle privee vit dans -# `underlay.vault.yml` — jamais versionnee. C'est cette cle-ci que le depot autorise : -# la publier est sans risque, et c'est meme le seul moyen qu'elle serve. +# `underlay.vault.yml` — jamais versionnee. C'est cette cle-ci que le depot autorise. backup_pubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf8O1ASPbRE2J+3uOrdJBRFJZCap8WeHjupdboI1KKF sauvegarde site-technolibre" -nftables_admin_ssh: [] +# D'ou l'administration SSH est admise : le plan d'administration du site. +nftables_admin_ssh: + - 10.31.0.0/24 + supervision_courriel: sysadmin@technolibre.ca -# LA REPLICATION DU DNS PUBLIC AVEC UN SITE PAIR (2026-09-16). -# -# Deux serveurs de noms, sur deux reseaux distincts, tenus par deux organisations : c'est ce -# qui garde un domaine joignable quand l'un tombe — et le registre des `.ca` en exige deux. -# Chaque site replique les zones publiques de l'autre, par le tunnel WireGuard. -# -# DECLAREE DES DEUX COTES, OU PAS DU TOUT. Declaree d'un seul cote, un site servirait des -# zones que son pair ne replique pas : le second serveur de noms serait vide sans que -# personne le voie. La preuve refuse une relation sans son vis-a-vis. -# -# `inactif` : le serveur du pair n'existe pas encore. Rien n'est emis tant qu'elle l'est. +# Les cles admises sur les machines du site, en plus de celle de l'exploitant. Le runner du +# site s'y ajoute des que sa cle existe (premier deploiement de `site-ops-01`). +cles_admin: [] + +# LA REPLICATION DU DNS PUBLIC AVEC UN SITE PAIR (2026-09-16). Deux serveurs de noms, sur deux +# reseaux distincts : c'est ce qui garde un domaine joignable quand l'un tombe. Declaree des +# deux cotes, ou pas du tout. `inactif` : rien n'est emis tant que le pair n'existe pas. dns_public_pairs: - site: SITE-Chezlepro etat: inactif diff --git a/plan/applications.yml b/plan/applications.yml index b10a379..ca75daa 100644 --- a/plan/applications.yml +++ b/plan/applications.yml @@ -1,81 +1,37 @@ --- -# Les services du SITE et leur placement — même forme que chez un tenant. -# -# `groupe` est le rôle Ansible, `hote` la machine de `plan/serveurs.yml` qui le porte. -# C'est de ce registre que l'inventaire tire ses groupes : une application déclarée ici -# range son hôte dans le groupe correspondant, et `playbooks/groupes/.yml` le -# trouve sans qu'on câble quoi que ce soit. -# -# `expose:` NOMME LE SERVICE, indépendamment de la machine qui le rend. -# -# C'est la pièce qui manquait, et son absence s'est vue au pire endroit : le certificat -# de la forge portait `forge.socle.internal` dans ses SAN, mais **aucune zone ne -# résolvait ce nom**. On avait donc du TLS correct sur un nom que personne ne pouvait -# appeler — et l'usage retombait sur `site-forge-01`, c'est-à-dire sur la machine. -# -# Un nom de service survit au déménagement du service ; un nom de machine, non. - +# Repris de SITE-Chezlepro le 2026-10-12 : le site de reprise porte les memes services, +# sous les memes noms, dans son propre domaine (`socle.internal`). +# Le moteur derive de ce registre les groupes, les expositions et les certificats. applications: - # LE RUNNER DU SITE — DEUX RÔLES, ET DANS CET ORDRE. - # - # `serveur_ops` INSTALLE : ansible, le cache de collections, les dépôts du génome clonés - # depuis la forge du site, les symlinks du moteur. `serveur_ops_site` n'installe rien — - # il dépose la voûte de l'underlay (chiffrée) et ajoute le pouvoir de MATÉRIALISER. - # - # C'est le même patron que `serveur_artefacts` + `serveur_cache_site` : un installateur - # et un marqueur. J'avais déclaré le marqueur seul, et son assertion l'a dit sans - # détour : « exige `serveur_ops_site_depot`, cloné par `serveur_ops` ». ops: groupe: serveur_ops hote: site-ops-01 + port: 8090 + expose: + - console.socle.internal ops_site: groupe: serveur_ops_site hote: site-ops-01 - - # LA SOURCE D'ARTEFACTS, et son marquage comme racine de chaîne. Les deux vont - # ensemble : `serveur_artefacts` INSTALLE apt-cacher-ng, `serveur_cache_site` MARQUE ce - # cache comme racine et vérifie qu'il n'a pas d'amont — il n'installe rien. artefacts: groupe: serveur_artefacts hote: site-cache-01 cache_site: groupe: serveur_cache_site hote: site-cache-01 - - # LA FORGE DU GÉNOME. `expose` porte son nom de service : c'est lui que le certificat - # doit couvrir, et lui que la zone souveraine doit résoudre. forgejo: groupe: serveur_forgejo hote: site-forge-01 - # 443, ET NON 3000. Le `3000` est le port que Forgejo ecoute DERRIERE un edge, en - # clair. Ici il sert lui-meme son TLS : garder 3000 aurait grave `:3000` dans - # `ROOT_URL`, donc dans l'`origin` de chaque ecosysteme descendant, pour toujours. port: 443 expose: - - forge.socle.internal - # LE MARQUEUR DE LA FORGE DU GÉNOME — même patron que `artefacts` + `cache_site`. - # - # Le site rend deux services à ses locataires pendant leur jeunesse : les PAQUETS et le - # GÉNOME. Le premier était déclaré, le second ne l'était pas — alors que D-81 fait de - # cette forge l'autorité dont tout écosystème se reproduit. - # - # Mesuré le 2026-08-28 sur `ops-01`, première machine de la reconstruction de - # Chezlepro : le cache du site répondait, la forge non, et le clonage du génome - # attendait sans fin. Le tenant déclarait pourtant lire son génome à cette adresse. + - forge.socle.internal forge_site: groupe: serveur_forge_site hote: site-forge-01 - - # L'AUTORITÉ. Elle sert le 443 à ses voisins du même segment, en L2 — rien ne traverse - # la frontière, donc aucune règle ne l'accompagne au devis. `expose` lui donne quand - # même son nom de service : les clients s'y enrôlent par un nom, jamais par une adresse. step_ca: groupe: serveur_step_ca hote: site-pki-01 expose: - - pki.socle.internal - - # LE DNS — autoritatif et résolveur sur la même machine, à dessein. + - pki.socle.internal powerdns: groupe: serveur_powerdns hote: site-dns-01 @@ -83,91 +39,49 @@ applications: groupe: serveur_resolveur hote: site-dns-01 expose: - - dns.socle.internal - # LE MARQUEUR DU RÉSOLVEUR DU SITE — troisième service prêté aux locataires, après les - # paquets (`cache_site`) et le génome (`forge_site`). Même patron : un installateur, un - # marqueur. - # - # Un écosystème neuf n'a ni cache, ni forge, ni résolveur — et c'est lui qui doit les - # construire. Sans celui-ci, ses machines sortent en 443 par adresse et restent - # AVEUGLES AUX NOMS : `apt` s'en sort par le mandataire du cache, qui résout à sa place, - # mais un `get_url` ou un dépôt tiers en HTTPS échoue. Mesuré le 2026-08-30 sur - # `infra-pki-01`, première machine à porter l'autorité de Chezlepro. - # - # `client_resolveur` bascule chaque tenant chez lui dès que son propre résolveur existe. - # Retirer cet emprunt ce jour-là est une émancipation — un geste, pas un effet. + - dns.socle.internal resolveur_site: groupe: serveur_resolveur_site hote: site-dns-01 - # LE SERVEUR DE SAUVEGARDE, ET SON MARQUEUR — meme patron que les trois autres - # services pretes : `serveur_backup` INSTALLE le depot, `serveur_backup_site` dit qu'il - # sert les locataires et declare le flux qui le permet. backup: groupe: serveur_backup hote: site-backup-01 backup_site: groupe: serveur_backup_site hote: site-backup-01 - # LE NOM QUE LES LOCATAIRES ÉCRIVENT DANS LEUR CONFIGURATION. - # - # Un locataire grave l'adresse de son dépôt dans `client_backup_repo`, donc dans le - # chemin de CHACUN de ses instantanés. Y graver `10.0.35.11` rendrait le dépôt - # indéplaçable : le jour où il change de machine, tous les locataires cessent de - # déposer, et chacun doit être modifié un par un — pendant que plus rien n'est - # sauvegardé. - # - # `sauvegarde`, pas `site-backup-01` : c'est le SERVICE qu'on nomme. La machine qui - # le rend a le droit de changer sans que personne ne réécrive quoi que ce soit. expose: - - sauvegarde.socle.internal - - # LA SUPERVISION DU SITE. `serveur_backup` rapporte PASSIVEMENT ici, avec un `ttl` : - # c'est l'expiration de ce `ttl` qui fait qu'un SILENCE alerte. Une sauvegarde qui - # cesse ne produit aucune erreur, seulement une absence — sans destinataire pour ce - # rapport, il n'y a pas de supervision, il y a un script qui tourne. + - sauvegarde.socle.internal postgresql: groupe: serveur_postgresql hote: site-mon-01 icinga: groupe: serveur_icinga hote: site-mon-01 - # L'OBSERVABILITE DU SITE — LA SIENNE, ET RIEN QUE LA SIENNE (D-87, 2026-09-10). - # - # Elle manquait, et son absence etait le REVERS de la frontiere : en refusant de voir - # les journaux de ses locataires — parce qu'ils contiennent du CONTENU, et qu'un - # hebergeur qui les lit en sait plus que s'il detenait leur annuaire — le site s'etait - # prive des siens. Ses sept machines n'expediaient rien nulle part. - # - # Le remede n'est pas d'assouplir la regle : c'est de lui donner SA pile. Aucun lien - # avec celle d'un tenant, dans aucun sens. Un locataire n'y envoie rien, et le site n'y - # lit que ses propres machines. - # - # POSEE SUR `site-mon-01`, la zone de supervision : c'est deja la qu'Icinga juge l'etat - # du site, et le zonage veut qu'une preoccupation vive dans une seule zone. La machine a - # la place (3,3 Go disponibles, charge 0,10 au moment du choix). prometheus: groupe: serveur_prometheus hote: site-mon-01 loki: groupe: serveur_loki hote: site-mon-01 - # GRAFANA SANS SSO, ET C'EST VOULU. Chez un tenant il vit derriere `oauth2_proxy`, donc - # derriere Keycloak. Le site n'a pas d'annuaire — et ne doit pas en avoir un pour ca. - # Faire monter l'identite pour offrir un tableau de bord serait payer tres cher une - # commodite : l'acces se fait depuis le plan d'administration, qui est deja la barriere. - # - # LE NOM DIT LA FONCTION, PAS LE PRODUIT (2026-09-10). C'etait `tableaux.socle.internal`, - # un mot que rien d'autre n'employait. `observatoire` est le meme nom que chez le locataire - # (`observatoire.chezlepro.internal`) : un seul vocabulaire des deux cotes, et un nom qui - # ne ment pas le jour ou Grafana est remplace. grafana: groupe: serveur_grafana hote: site-mon-01 + port: 3000 + websocket: true expose: - - observatoire.socle.internal - - # LE RELAIS DE COURRIEL DU SITE — souverain, et c'est tout l'interet : emprunter le MTA - # d'un locataire ferait dependre le site d'un ecosysteme qu'il peut outvivre. + - observatoire.socle.internal + nginx: + groupe: serveur_nginx + hote: site-edge-01 + dns_public: + groupe: serveur_dns_public + hote: site-dnspub-01 + icingaweb2: + groupe: serveur_icingaweb2 + hote: site-mon-01 + port: 8080 + expose: + - vigie.socle.internal postfix: groupe: serveur_postfix hote: site-mon-01 diff --git a/plan/bases-donnees.yml b/plan/bases-donnees.yml index a43fcfc..4168a22 100644 --- a/plan/bases-donnees.yml +++ b/plan/bases-donnees.yml @@ -1,21 +1,14 @@ --- -# LE REGISTRE DES BASES DU SITE — la garde D-72 : sans entree ici, `resoudre_base` -# REFUSE plutot que de deviner un hote, un nom de base ou un secret. -# -# Le site n'en a qu'une, et c'est voulu. Chez un locataire, PostgreSQL vit sur une -# machine dediee parce que plusieurs services la partagent ; ici un seul en a besoin. -# La base est donc sur la machine qui la consomme — une seconde VM n'aurait fait -# qu'ajouter une machine a surveiller a celle qui surveille. +# Repris de SITE-Chezlepro le 2026-10-12 : le site de reprise porte les memes services, +# sous les memes noms, dans son propre domaine (`socle.internal`). +# Les secrets nommes ici vivent dans la voute du site (underlay.vault.yml). serveurs_bd: pg-site: type: postgres hote: site-mon-01 port: 5432 groupe: serveur_postgresql - bases_donnees: - # LA BASE D'ICINGA. Elle porte l'historique de la supervision — pas irremplacable, - # mais une base l'est par nature, et `site-mon-01` porte donc `client_backup`. icingadb: serveur: pg-site base: icingadb @@ -24,3 +17,11 @@ bases_donnees: consommateur: icinga portee: application usage: principale + icingaweb2: + serveur: pg-site + base: icingaweb2 + proprietaire: icingaweb2 + secret: vault_bd_icingaweb2 + consommateur: icingaweb2 + portee: application + usage: principale diff --git a/plan/domaines.yml b/plan/domaines.yml new file mode 100644 index 0000000..765f3e3 --- /dev/null +++ b/plan/domaines.yml @@ -0,0 +1,10 @@ +--- +# Repris de SITE-Chezlepro le 2026-10-12 : le site de reprise porte les memes services, +# sous les memes noms, dans son propre domaine (`socle.internal`). +domaines_publics: + socle.internal: + autorite: auto-heberge + edge: serveur_nginx + resolution_interne: service + secondaires: [] + dnssec: false diff --git a/plan/mainteneurs.yml b/plan/mainteneurs.yml new file mode 100644 index 0000000..ce9db4b --- /dev/null +++ b/plan/mainteneurs.yml @@ -0,0 +1,9 @@ +--- +# Qui maintient les locataires de ce site — repris de SITE-Chezlepro (2026-10-12). +mainteneurs: + daniel: + nom: Daniel Allaire + courriel: allaire.dan@chezlepro.ca + locataires: + - OPS-Chezlepro + - OPS-Technolibre diff --git a/plan/serveurs.yml b/plan/serveurs.yml index 1670fdb..4697891 100644 --- a/plan/serveurs.yml +++ b/plan/serveurs.yml @@ -1,204 +1,115 @@ --- -# Les machines du SITE — l'équivalent de `plan/serveurs.yml` chez un tenant. +# Les machines du SITE — les MEMES qu'au site de Chezlepro, sous les memes noms (decision de +# Daniel, 2026-10-12) : un exploitant qui connait l'un connait l'autre, et une reprise ne +# demande d'apprendre aucun nom. # -# UNE SEULE DIFFÉRENCE AVEC CELUI D'UN TENANT, mais elle est structurante : ici -# l'adressage est **déclaré**, là-bas il est **dérivé**. Un tenant écrit `fonction:` et -# tout descend de son `index` ; un site écrit `ip`, `vmid`, `noeud`, parce qu'il n'y a -# aucun seed dont les faire descendre — le site *est* le terrain. +# Ici l'adressage est DECLARE (un site est le terrain, il n'a pas de seed dont le deriver). +# La regle reste celle de Chezlepro : 10..., et +# le meme VMID. `reseau:` nomme un reseau de `underlay.yml`, qui fournit pont, VLAN, masque et +# passerelle. # -# `reseau:` nomme un réseau de `underlay.yml`, qui fournit le pont, l'étiquette VLAN, le -# masque et la passerelle. La fabric reste la source de ces valeurs-là : on la nomme, on -# ne la recopie pas. -# -# UNE ZONE PAR NATURE D'AUTORITÉ (2026-08-25). Ces machines ont vécu quelques heures dans -# un `/24` plat — la plus autoritaire du système avec moins d'isolation que n'importe -# quelle machine de tenant. Chacune vit désormais dans la zone de ce qu'elle détient, et -# tout ce qui va d'une zone à l'autre est routé, donc policé par la frontière. - +# UN SEUL NOEUD : toutes sur `maurice`. Somme : 9 VM, 17 vCPU, 23 Go de RAM, 816 Go de disque +# provisionne — a l'aise dans 2 x 128 Go. Disques : 416 Go sur `nvme`, 400 Go +# (`site-backup-01`) sur `miroir`. serveurs: - # LE RUNNER DU SITE. Il MATÉRIALISE : VNets, VM, routes, flux — il prépare le terrain - # qu'un runner de tenant occupera ensuite. Il détient la voûte de l'underlay, jamais - # celle d'un tenant. Voir roles/serveur_ops_site/README.md pour la ligne de partage. site-ops-01: etat: actif reseau: site-pilotage ip: 10.31.31.11 - noeud: atelier + noeud: maurice gabarit: { vcpu: 2, memoire: 4096, disque: 40G } vmid: 9001 variables: - # CE QUE LE RUNNER DU SITE DOIT DÉTENIR POUR TRAVAILLER. - # - # Le moteur, la carte de l'hébergeur, les modèles — et les PLANS qu'il matérialise. - # `tenant` et non `instance` : il ne PILOTE pas ces écosystèmes, il leur prépare le - # terrain. Configurer leurs services exige leurs voûtes, qu'il n'aura jamais. + # LES DEUX LOCATAIRES : ce site est la reprise de l'un ET de l'autre. Le runner doit + # pouvoir redeployer chacun depuis son propre depot. serveur_ops_depots: - { depot: "set-ops-public", dest: "Set-OPS-public", role: "moteur" } - { depot: "site-technolibre", dest: "SITE-Technolibre", role: "hebergeur" } - { depot: "set-ops-modeles", dest: "Set-OPS-Modeles", role: "modeles", branche: "master" } + - { depot: "ops-chezlepro", dest: "OPS-Chezlepro", role: "tenant" } - { depot: "ops-technolibre", dest: "OPS-Technolibre", role: "tenant", branche: "master" } - # AUCUNE INSTANCE ACTIVE : un SITE n'est pas un tenant, il n'a pas de plan monté par - # le symlink `instance`. Son propre inventaire est dynamique (`site_inventaire.py`). serveur_ops_instance: "" + serveur_ops_gui_auth: locale serveur_ops_underlay: "SITE-Technolibre" - # Le dépôt que `serveur_ops_site` habille de la voûte, une fois cloné ci-dessus. serveur_ops_site_depot: "SITE-Technolibre" serveur_ops_site_voute_source: >- {{ (playbook_dir ~ '/../../underlay.yml') | realpath | dirname }}/underlay.vault.yml - # ARMER CE RUNNER — il est maître de sa voûte et en détient la clé (2026-08-28). - # - # Sans elle, il porte le chiffré et ne peut rien en faire : il calcule son - # inventaire, et chaque geste qui demande un secret échoue sur une valeur vide. - # - # LA CLÉ DE CE SITE, ET ELLE SEULE. Depuis la séparation des voûtes, le mot de passe - # de l'underlay n'ouvre plus aucun tenant : ce runner ne peut donc ouvrir que la - # fabric, ce qui est exactement son pouvoir. C'était faux jusqu'au 2026-08-28, où - # un mot de passe unique ouvrait les six voûtes de la flotte. - # - # Le chemin est un POINTEUR — le fichier vit sur le poste de l'exploitant et - # n'entre dans aucun dépôt. serveur_ops_site_cle_deposer: true serveur_ops_site_cle_source: "~/.config/setops-vault-site-technolibre" - - # LA RACINE DE LA CHAÎNE DE CACHES : - # VM du tenant -> cache du tenant -> cache du SITE -> Debian - # Debian n'est ainsi téléchargé qu'une fois pour tout le site, et ce cache ne voit que - # des requêtes agrégées — jamais quelle machine de quel tenant installe quoi. site-cache-01: etat: actif reseau: site-genome ip: 10.31.33.21 - noeud: atelier + noeud: maurice gabarit: { vcpu: 2, memoire: 2048, disque: 120G } vmid: 9002 - - # LA FORGE DU GÉNOME. Elle a d'abord vécu chez un écosystème — - # et tout l'univers en dépendait pour se reproduire. site-forge-01: etat: actif reseau: site-genome ip: 10.31.33.11 - noeud: atelier + noeud: maurice gabarit: { vcpu: 2, memoire: 4096, disque: 80G } vmid: 9003 - # CETTE MACHINE DÉTIENT DE L'ÉTAT — elle dépose donc sur le dépôt du site. - # - # `client_backup` est une intégration FACULTATIVE : elle se déclare là où il y a - # quelque chose à perdre, pas partout. Ici, le génome — les quatre dépôts dont tout descend. Ils vivent - # aussi sur les postes et les runners, mais la forge est le seul endroit où ils se - # rejoignent. integrations: [client_backup] variables: - # Elle tourne seule : ni PostgreSQL ni Keycloak sur le site. C'est délibéré — - # cette forge sert LE GÉNOME, pas une équipe. SQLite est un choix de conception, - # pas un repli : la base tient dans un fichier, que la sauvegarde emporte déjà. serveur_forgejo_bd: sqlite - # Elle sert son propre TLS : il n'y a pas d'edge devant elle sur le site. serveur_forgejo_tls: true - # Le port du schema, pas celui d'un service derriere un edge. Forgejo tournant en - # `git`, l'unite lui accorde CAP_NET_BIND_SERVICE pour s'y lier. serveur_forgejo_http_port: 443 - # Forgejo tourne en `git` dès le départ, contrairement à nginx ou Postfix qui - # lisent la clé en root avant de déprivilégier. Accès GROUPE à la clé privée — - # pas un élargissement général. client_pki_cle_groupe: git client_pki_cle_mode: "0640" - # Un cert renouvelé sur disque reste servi périmé tant que le consommateur n'est - # pas rechargé. La cicatrice est déjà dans le dépôt ; on ne la refait pas. client_pki_reload_services: - forgejo - - # L'AUTORITÉ DE CERTIFICATION DU SITE. Sans elle, la forge servait le génome en clair - # et aucune machine n'avait de certificat — donc aucun chiffrement est-ouest. site-pki-01: etat: actif reseau: site-autorite ip: 10.31.32.11 - noeud: atelier + noeud: maurice gabarit: { vcpu: 2, memoire: 2048, disque: 32G } vmid: 9004 - # CETTE MACHINE DÉTIENT DE L'ÉTAT — elle dépose donc sur le dépôt du site. - # - # `client_backup` est une intégration FACULTATIVE : elle se déclare là où il y a - # quelque chose à perdre, pas partout. Ici, la racine de l'autorité de certification. Compromise, elle forge - # tout nom ; perdue, il faut redistribuer la confiance à chaque machine de chaque - # écosystème. integrations: [client_backup] - - # LE DNS DU SITE — autoritatif ET résolveur, colocalisés. - # - # Ils partagent la zone souveraine, et le repli de port de PowerDNS (53 -> 5300) DÉRIVE - # de cette colocalisation : le résolveur prend le 53, l'autoritatif se range derrière. - # Les séparer casserait cette dérivation. site-dns-01: etat: actif reseau: site-service ip: 10.31.34.11 - noeud: atelier + noeud: maurice gabarit: { vcpu: 2, memoire: 2048, disque: 40G } vmid: 9005 variables: - # CORRIGÉ LE 2026-08-25 — c'était `false`, avec pour motif « le site n'a pas d'edge, - # aucun FQDN public à faire pointer quelque part ». Le raisonnement confondait - # PUBLIC et EXPOSÉ. - # - # Le site n'a effectivement aucun domaine public. Mais `plan/applications.yml` - # déclare bien trois expositions — `forge.genese.internal`, `pki.genese.internal`, - # `dns.genese.internal` — et ce sont des noms de SERVICE, que les certificats - # portent et que les clients appellent. Ils n'avaient aucun enregistrement dans la - # zone : seul le plancher `/etc/hosts` savait les résoudre. - # - # Un service ne doit pas dépendre d'un plancher pour être joignable. Le plancher est - # un filet — il rattrape le DNS éteint — pas le sol. serveur_powerdns_publier_expositions: true - # LE DEPOT DE SAUVEGARDE DU SITE — le quatrieme service prete aux locataires. - # - # Apres les paquets, le genome et les noms : l'ETAT. Un ecosysteme neuf n'a pas de - # depot ou sauvegarder, et c'est justement quand il commence a detenir quelque chose - # d'irremplacable qu'il en a besoin. - # - # CE QUE CA CORRIGE, ET QUI ETAIT DANGEREUX (mesure le 2026-09-01). Chezlepro - # sauvegardait sur `backup-01`, UNE VM DE SA PROPRE FLOTTE. Raser l'ecosysteme aurait - # detruit les donnees ET leur seul filet dans le meme geste. La doctrine affirmait - # pourtant que `client_backup_cible` « pointe deja hors de l'ecosysteme » — faux pour Chezlepro. Un document qui decrit - # une propriete que le reel n'a pas est exactement ce que ce depot traque. - # - # SA ZONE EST A LUI SEUL. Il detient l'etat de CHAQUE tenant : cles d'autorite, - # annuaires, bases, courriel. C'est la machine dont la compromission coute le plus cher - # du site — plus que la forge, dont le contenu est du code, et plus que l'AC, qui forge - # des noms sans detenir de donnees. - # - # SON DISQUE EST LE PLUS GROS DU SITE : il accueille l'etat de tous les locataires, et - # restic garde des instantanes. On le dimensionne large plutot que de decouvrir la - # limite le jour ou une sauvegarde echoue en silence. site-backup-01: etat: actif reseau: site-sauvegarde ip: 10.31.35.11 - noeud: atelier + noeud: maurice gabarit: { vcpu: 2, memoire: 2048, disque: 400G } vmid: 9010 - - # LE TEMOIN DU SITE — celui qui sait quand les autres se taisent. - # - # Il porte SA propre base : chez un locataire, PostgreSQL vit sur une machine dediee - # parce que plusieurs services la partagent. Ici un seul en a besoin, et une seconde VM - # ne ferait qu'ajouter une machine a surveiller a celle qui surveille. - # - # Il porte aussi un relais de courriel. Sans lui, la seule facon d'alerter serait - # d'emprunter le MTA d'un locataire — le site dependrait alors d'un ecosysteme qu'il - # peut outvivre, et une emancipation emporterait son alerte avec elle. + # SUR LE MIROIR, pas sur le NVMe : ses 400 Go ne tiendraient pas a cote des huit autres, + # et c'est la machine dont le disque doit survivre a la perte d'un disque. + stockage: miroir site-mon-01: etat: actif reseau: site-supervision ip: 10.31.36.11 - noeud: atelier + noeud: maurice gabarit: { vcpu: 2, memoire: 4096, disque: 64G } vmid: 9011 - # ELLE PORTE UNE BASE, DONC DE L'ETAT — P36 l'a exige des la declaration. - # - # L'historique d'Icinga n'est pas irremplacable ; la base l'est par nature, et le - # catalogue ne connait pas la nuance. C'est tant mieux : une exception ici serait - # exactement ce que cette preuve existe pour empecher. Le dump coute quelques - # megaoctets et vit deja sur le depot du site. integrations: [client_backup] + site-edge-01: + etat: actif + reseau: site-publication + ip: 10.31.37.11 + noeud: maurice + gabarit: { vcpu: 2, memoire: 2048, disque: 20G } + vmid: 9012 + variables: + client_pki_reload_services: + - nginx + # LE SECOND SERVEUR DE NOMS PUBLIC des deux ecosystemes (2026-09-29) : il tourne ICI, et le + # relais (VPS) ne fait que lui faire suivre les requetes par le tunnel du site. + site-dnspub-01: + etat: actif + reseau: site-publication + ip: 10.31.37.21 + noeud: maurice + gabarit: { vcpu: 1, memoire: 1024, disque: 20G } + vmid: 9013 diff --git a/proxmox-hebergeur.yml b/proxmox-hebergeur.yml index 47bef76..2d01ba4 100644 --- a/proxmox-hebergeur.yml +++ b/proxmox-hebergeur.yml @@ -15,28 +15,29 @@ # frontiere sans route de retour vers le locataire. Mesure faite avant la visite, pas # pendant. --- -# UNE ADRESSE, PAS UN NOM DE NOEUD. `atelier` ne resout ni depuis le poste de -# l exploitant ni depuis le runner : seuls les hyperviseurs connaissent ce nom. +# UNE ADRESSE, PAS UN NOM DE NOEUD. `maurice` ne resout ni depuis le poste de +# l'exploitant ni depuis le runner : seuls les hyperviseurs le connaissent, par leur +# /etc/hosts. # -# C'est la patte du PLAN D'ADMINISTRATION — ce site n'en a qu'un. L'exploitant s'y -# donne une adresse secondaire et atteint l API sans routage intermediaire. `atelier` ne resout ni depuis le poste de l'exploitant -# ni depuis le runner : seuls les hyperviseurs connaissent ce nom, par leur /etc/hosts. Les +# C'est la patte du PLAN D'ADMINISTRATION — ce site n'en a qu'un, et le poste de +# l'exploitant y est branche (10.31.0.101) : l'API se joint sans routage intermediaire. Les # NOEUDS gardent leurs noms plus bas — ce sont des identifiants dans les chemins d'API, pas # des points de contact. -proxmox_api_host: 10.31.0.41 +proxmox_api_host: 10.31.0.11 proxmox_api_port: '8006' proxmox_api_user: ansible@pve # UN SEUL NOEUD. C'est la difference de fond avec Chezlepro, et elle est assumee : pas de # migration, pas de quorum, le SPOF est total. Ce fichier le dit plutot que de le masquer. proxmox_noeuds: -- atelier +- maurice -# UN SEUL PONT. Les six zones du site et celles du locataire sont des VLAN portes par le -# meme pont, en mode VLAN-aware. Sur un noeud sans seconde carte, ajouter des ponts -# n'ajouterait aucune separation reelle. +# DEUX PONTS, DEUX CARTES (decision de Daniel, 2026-10-13). `vmbr0` sur `nic0` (1G) : +# l'administration du noeud, 10.31.0.11, rien d'autre. `vmbr1` sur `nic2` (10G), VLAN-aware +# et sans adresse : les zones du site et celles des locataires repris. Une VM ne nait +# jamais sur `vmbr0`. proxmox_ponts: -- vmbr0 +- vmbr1 proxmox_sdn: # ASN DERIVE DE L'INDEX DU SITE (31), pas repris de Chezlepro (65000). Les deux sites @@ -49,13 +50,16 @@ proxmox_sdn: # survivra au premier locataire et en servira d'autres. controleur: EVPN0031 noeuds_de_sortie: - - atelier - sortie_primaire: atelier + - maurice + sortie_primaire: maurice -# `local-lvm` : ce que Proxmox pose a l'installation, et la seule chose presente sur un -# noeud unique. Quinze clones COMPLETS y tiennent ou n'y tiennent pas — c'est la premiere -# mesure a faire sur place, avant de lancer quoi que ce soit. +# DEUX STOCKAGES (releve et decision du 2026-10-13). `local-lvm` (130 Go, sur le SSD du +# systeme) ne tenait pas les 816 Go du plan : il n'est pas declare, aucune VM n'y nait. +# - `nvme` : LVM-thin sur le NVMe de 465 Go — le gabarit et les VM du site ; +# - `miroir` : ZFS en miroir sur les deux disques de 12 To — `site-backup-01`, la ou +# s'accumule l'etat de tous les locataires. proxmox_stockages: -- local-lvm +- nvme +- miroir proxmox_validate_certs: false diff --git a/underlay.yml b/underlay.yml index dcb2456..7719466 100644 --- a/underlay.yml +++ b/underlay.yml @@ -1,169 +1,174 @@ -# Underlay de SITE-Technolibre — l'infrastructure PHYSIQUE de l'hébergeur. +# Underlay — infrastructure PHYSIQUE du site de TechnoLibre (noeud maurice). # -# UN SEUL NŒUD PROXMOX, en version 9. C'est la différence de fond avec le site de -# Chezlepro : pas de Ceph, pas d'iSCSI, pas de migration, pas de fabric de stockage. -# Le gabarit et ses clones vivent sur la même machine — le SPOF est total, et assumé. +# SITE DE REPRISE : il n'heberge aucune production. Chezlepro et TechnoLibre tournent au site +# de Chezlepro ; ce site-ci existe pour les REPRENDRE (exercice ou sinistre). C'est pourquoi +# il declare les deux index de locataires. # -# Dérivé du modèle `exemples/modeles/socle` (« un seul commutateur, pas de fabric de -# stockage séparée — le point de départ honnête d'un petit hébergeur »), adapté. +# UN SEUL NOEUD : pas de Ceph, pas d'iSCSI, pas de migration. Le gabarit et ses clones vivent +# sur la meme machine — le point unique de panne est total, et assume pour un site de reprise. # -# ⚠ TOUT CE QUI EST MARQUÉ <<…>> EST À RELEVER SUR PLACE. Voir COLLECTE.md. +# Refait le 2026-10-12 sur le modele de SITE-Chezlepro (memes cles, memes zones, memes noms de +# VM) : le depot de septembre ne suivait plus les methodes du moteur. Les valeurs que seul le +# materiel peut dire restent marquees `<<...>>` — voir COLLECTE.md. +# +# Le moteur la monte par symlink (Set-OPS-public/underlay.yml -> ce fichier), ou la lit par +# `SETOPS_UNDERLAY` sans toucher au symlink. Validee par `make underlay` / preuve P23. --- underlay: - # Le locataire que ce site hébergera. Son index est déjà fédéré (23) et il ne - # change pas : c'est lui qui porte l'adressage d'OPS-Technolibre, ses VLAN et ses VMID. - # L'INDEX DU SITE LUI-MÊME. Déclaré ici, et pas seulement porté par les adresses : - # c'est ce qui le rend visible à la garde des collisions (`make instances`). - # Depuis le 2026-09-12, SITES et OPS partagent la classe A — deux écosystèmes ne - # peuvent donc plus prendre le même nombre, quel que soit leur genre. + # L'index du site lui-meme : 10.31.0.0/16. Les sites et les locataires se partagent la + # classe A, chacun avec SON index (Chezlepro : site 37, locataires 17 et 23). index: 31 - # CE SITE EST UN SITE DE REPRISE (2026-09-13). - # - # Il n'heberge aucune production : celle de TechnoLibre vit chez Chezlepro, et celle de - # Chezlepro chez lui. Ce site existe pour les REPRENDRE — l'une ou l'autre, ou les deux — - # lors d'un exercice ou d'un sinistre. - # - # Les deux index sont donc declares. Ce n'est pas une intention : c'est ce qui permet a - # `make instances` de garder l'unicite, et au SDN d'allouer les VNets des deux le jour ou - # on les demande. - # - # UN LOCATAIRE N'APPARTIENT A AUCUN SITE. Reprendre, c'est faire pointer son symlink - # `underlay.yml` ici, reprendre les intrants par `make site-intrants`, et redeployer - # depuis son propre depot. Le plan du locataire ne change pas. + # Les locataires que ce site peut REPRENDRE, avec l'index qu'ils ont deja. Une reprise ne + # renumerote rien : le plan du locataire ne change pas, seul change le site qu'il habite. tenants: OPS-Chezlepro: 17 OPS-Technolibre: 23 - # CE QUI ROUTE ENTRE LES ZONES D'UN LOCATAIRE — `sdn`, COMME CHEZLEPRO. - # - # En EVPN, le routage ET le filtrage inter-zone d'un locataire vivent sur le nœud : - # aucun VLAN de locataire ne circule sur le fil, seulement du VXLAN encapsulé. Le devis - # switch cesse alors d'émettre VLAN de locataire, SVI et ACL — vérifié le 2026-09-13 : - # sept VLAN émis (les six du site plus le transit), zéro SVI. - # - # L'inter-locataire, lui, sort du VRF et passe par la frontière, qui le police. + # Le commutateur entre la frontiere et le noeud (confirme sur place le 2026-10-13) : + # 4 ports 2,5G et 4 SFP+, couche 2 seulement — ni routage ni filtrage. La carte 10G du + # noeud (2 SFP+) et un SFP+ du QOTOM y sont branches ; c'est la racine du spanning-tree. + routeur: caillou + + # UN SEUL NOEUD : le routage des locataires vit dans l'EVPN du noeud (controleur EVPN0031, + # ASN 65031 — proxmox-hebergeur.yml). Sans commutateur L3, le mode `switch` obligerait la + # frontiere a porter une interface routee par zone de locataire. routage_tenants: sdn - - # LE COMMUTATEUR, ET C'EST UNE CORRECTION (2026-09-13). Ce champ portait `portail`, la - # frontière, parce qu'on avait cru qu'il n'y avait rien entre la fabric et l'OPNsense. - # Il y a bien un commutateur — comme à Chezlepro, et à la même place. C'est lui qui - # porte l'underlay ; la frontière ne fait que la bordure nord/sud. - routeur: arche-1 - - dialecte: binardat mtu_overlay: 1450 - - # UN SEUL LOCATAIRE POUR L'INSTANT, et l'inter-locataire passe déjà par la frontière. - # Même valeur qu'à Chezlepro. À revoir le jour où un deuxième écosystème s'installe. acl_inter_tenant: false - - # `rstp` plutôt que `mstp` : un seul commutateur, donc aucune instance par VLAN à - # distinguer. La topologie reste l'étoile de Chezlepro — un centre, des feuilles. + dialecte: binardat stp: mode: rstp topologie: etoile reseaux: - # PLAN DE GESTION — la seule chose qui doit être unique entre deux sites. - # `10..0.0/24`, index 31 : celui du SITE, distinct de celui de son - # locataire (23). Décision du 2026-09-12 : SITES et OPS partagent la classe A, - # chacun avec son propre index — le plan d'administration de l'hébergeur ne vit - # plus dans le supernet d'un de ses locataires. - # UN SEUL PLAN D'ADMINISTRATION, ET C'EST UNE DIFFÉRENCE ASSUMÉE AVEC CHEZLEPRO. - # - # Chezlepro sépare `management` (le plan d'admin du site) de `grappe-controle` (où - # vivent l'interface web et l'API de Proxmox). Cette séparation y a une cause - # historique : ses trois nœuds existaient AVANT Set-OPS, sur un réseau qui leur était - # déjà propre. - # - # Ici, un seul nœud et un terrain vierge : un second réseau ne séparerait rien. Il - # obligerait seulement à router entre les deux pour que le poste de l'exploitant — - # posé sur l'admin — atteigne une API posée ailleurs. - # - # L'exploitant se donne une adresse secondaire dans ce réseau et atteint d'un coup la - # frontière (.1), le nœud (.41) et le rebond vers les machines du site. + # LE PLAN D'ADMINISTRATION : un port physique de la frontiere (la LAN du QOTOM), non + # etiquete. C'est la que vivent le poste de l'exploitant (10.31.0.101), la frontiere (.1) + # et l'interface d'administration du noeud (.11). Aucune VM n'y nait. - nom: management - description: Gestion du nœud, API Proxmox, poste de l'exploitant - vlan: null + nature: fabric + description: Equipements, frontiere, administration du noeud, poste de l'exploitant + segment_physique: true sous_reseau: 10.31.0.0/24 + passerelle: 10.31.0.1 + mtu: 1500 + + # --- LES ZONES DU SITE — les memes qu'au site de Chezlepro -------------------------- + # Une zone par nature d'autorite ; chacune est un VLAN sur `vmbr1` — le pont des VM, sur + # la carte 10G (`nic2`), separe de l'administration (`vmbr0` sur `nic0`, decision de + # Daniel le 2026-10-13) — avec sa patte `.1` sur la frontiere, qui police tout passage + # d'une zone a l'autre. + # L'adresse se derive de l'index et du VLAN : 10.31..0/24. + - nom: site-pilotage + nature: site + description: Le runner du SITE — voute de l'underlay, API Proxmox et OPNsense + vlan: 31 + pont: vmbr1 + mtu: 1500 + - nom: site-autorite + nature: site + description: La racine de confiance — step-ca. Compromise, elle forge tout nom. + vlan: 32 + pont: vmbr1 + mtu: 1500 + - nom: site-genome + nature: site + description: La forge et le cache — le code et les binaires dont tout descend + vlan: 33 + pont: vmbr1 + mtu: 1500 + - nom: site-service + nature: site + description: La resolution — ce que toutes les zones interrogent + vlan: 34 + pont: vmbr1 + mtu: 1500 + - nom: site-sauvegarde + nature: site + description: L'etat de TOUS les locataires — la zone la plus concentree du site + vlan: 35 + pont: vmbr1 + mtu: 1500 + - nom: site-supervision + nature: site + description: Le temoin — ce qui sait quand les autres se taisent + vlan: 36 + pont: vmbr1 + mtu: 1500 + - nom: site-publication + nature: site + description: L'edge du SITE et son DNS public — les seules machines faites pour etre JOINTES + vlan: 37 + pont: vmbr1 mtu: 1500 - # LIEN VERS LA FRONTIÈRE. Sans lui, la flotte n'a ni sortie ni chemin de retour : - # elle serait routée jusqu'à la bordure puis muette — très difficile à diagnostiquer. - nom: transit-frontiere - description: Lien nœud Proxmox <-> OPNsense, et sortie par défaut des locataires + nature: fabric + description: Frontiere nord/sud — lien du noeud ET chemin de sortie des locataires vlan: 40 sous_reseau: 10.0.4.0/24 passerelle_sortie: 10.0.4.1 mtu: 1500 - # LES SIX ZONES DU SITE. Une préoccupation par zone. - # Même FORME que le site de Chezlepro — le 3e octet reste le numéro de VLAN. - # Ce qui change : le 2e octet porte l'index du site (31) au lieu de 0. - # Les deux sites peuvent donc être reliés (§8 du guide) sans renumérotage. - - { nom: site-pilotage, description: Runner et pilotage, vlan: 31, sous_reseau: 10.31.31.0/24, pont: vmbr0, mtu: 1500 } - - { nom: site-autorite, description: Autorité de certification, vlan: 32, sous_reseau: 10.31.32.0/24, pont: vmbr0, mtu: 1500 } - - { nom: site-genome, description: Forge et cache de paquets, vlan: 33, sous_reseau: 10.31.33.0/24, pont: vmbr0, mtu: 1500 } - - { nom: site-service, description: Noms (DNS autoritaire), vlan: 34, sous_reseau: 10.31.34.0/24, pont: vmbr0, mtu: 1500 } - - { nom: site-sauvegarde, description: Dépôt de sauvegarde mutualisé, vlan: 35, sous_reseau: 10.31.35.0/24, pont: vmbr0, mtu: 1500 } - - { nom: site-supervision, description: Supervision et observabilité, vlan: 36, sous_reseau: 10.31.36.0/24, pont: vmbr0, mtu: 1500 } - - # TRANSPORT DU VXLAN ENTRE VTEP. Exigé par `routage_tenants: sdn` — c'est le réseau - # dans lequel les tunnels des locataires sont encapsulés. Il ne porte JAMAIS de - # trafic de gestion, et aucune machine de locataire ne le voit. - # - # Chezlepro l'adresse en 192.168.50.0/24 ; ici il DÉRIVE de l'index du site, comme - # tout le reste. Les deux sites ont vocation à être reliés : deux transports VXLAN - # au même adressage produiraient une panne dont le message ne parle pas d'adressage. + # Le transport VXLAN : une seule VTEP aujourd'hui, mais l'EVPN en exige une adresse, et + # un second noeud n'aura qu'a s'y ajouter. - nom: underlay-vxlan + nature: fabric description: Transport VXLAN entre VTEP — aucun trafic de gestion vlan: 50 sous_reseau: 10.31.50.0/24 mtu: 1500 + # LA FACE PUBLIQUE DU SITE (2026-10-13). Le site n'a qu'une adresse DHCP ; ses trois + # adresses fixes sont louees sur un VPS d'OVH (le relais) et lui arrivent par ce tunnel, + # INITIE PAR LA FRONTIERE. Le relais repond a l'ARP d'OVH pour elles et les route en /32 + # dans le tunnel, sans traduction : elles arrivent intactes sur `requin`, qui les porte. + # Ni VLAN ni port : un tunnel ne traverse aucun commutateur. + - nom: relais + nature: fabric + fabric: relais + description: Tunnel WireGuard vers le relais OVH — par ou arrivent les adresses publiques + tunnel: wireguard + sous_reseau: 10.31.60.0/30 + mtu: 1420 + hotes: - # L'UNIQUE NŒUD. `via` = l'interface physique qui porte le trunk vers la frontière. - - { nom: atelier, reseau: management, ip: 10.31.0.41, role: hyperviseur, via: vmbr0 } - - { nom: atelier, reseau: underlay-vxlan, ip: 10.31.50.41, role: hyperviseur, via: <> } - - { nom: atelier, reseau: transit-frontiere, ip: 10.0.4.41, role: hyperviseur, via: <> } + - { nom: caillou, role: switch, reseau: management, ip: 10.31.0.111 } - # LE COMMUTATEUR, entre la fabric et la frontière. Une seule patte, sur le plan de - # gestion : c'est par là qu'on le configure, et le devis n'a pas besoin d'autre chose. - - { nom: arche-1, reseau: management, ip: 10.31.0.3, role: switch } + # La frontiere (QOTOM) — hors flotte Ansible. `.1` partout : c'est l'invariant dont le + # devis derive les regles. + - { nom: requin, reseau: management, ip: 10.31.0.1, role: frontiere } + - { nom: requin, reseau: transit-frontiere, ip: 10.0.4.1, role: frontiere } + - { nom: requin, reseau: site-pilotage, ip: 10.31.31.1, role: frontiere } + - { nom: requin, reseau: site-autorite, ip: 10.31.32.1, role: frontiere } + - { nom: requin, reseau: site-genome, ip: 10.31.33.1, role: frontiere } + - { nom: requin, reseau: site-service, ip: 10.31.34.1, role: frontiere } + - { nom: requin, reseau: site-sauvegarde, ip: 10.31.35.1, role: frontiere } + - { nom: requin, reseau: site-supervision, ip: 10.31.36.1, role: frontiere } + - { nom: requin, reseau: site-publication, ip: 10.31.37.1, role: frontiere } + # Les CLES PUBLIQUES du tunnel ne sont pas des secrets : chaque bout a besoin de celle de + # l'autre. Les cles privees restent, l'une dans OPNsense, l'autre dans la voute du site + # (`vault_relais_wg_cle_privee`), pour que le relais se reconstruise sans changer de cle. + - { nom: requin, reseau: relais, ip: 10.31.60.2, role: frontiere, + cle_publique: mScwuAKruvArh8+WQuCO7I/sad26BBqyUTxjQ2I+/mM= } - # LA PASSERELLE AMONT — la boîte du fournisseur d'accès, en amont de la frontière. - # Déclarée pour que le devis sache où s'arrête notre responsabilité. - - { nom: routeur-site, reseau: management, ip: 10.31.0.254, role: passerelle_amont } + # Le relais — VPS OVH, Debian 13, administre par Set-OPS (role `serveur_relais`). Sa + # console SSH reste sur son adresse propre ; les trois adresses relayees n'y sont pas + # attribuees (proxy ARP). Son port d'ecoute derive de l'index : 51800 + 31. + - { nom: relais, reseau: relais, ip: 10.31.60.1, role: relais, console: 15.235.101.239, + cle_publique: CC6qpkjcMAemkvZkD9URE8IO7CH3VFqGcXkU2rwvkRU= } - # LA FRONTIÈRE, patte par patte. Une ligne par zone qu'elle sert : c'est de là que - # le devis dérive les interfaces d'arrivée des règles (D-61 raisonne en ARRIVÉE). - - { nom: portail, reseau: management, ip: 10.31.0.1, role: frontiere } - - { nom: portail, reseau: transit-frontiere, ip: 10.0.4.1, role: frontiere } - - { nom: portail, reseau: site-pilotage, ip: 10.31.31.1, role: frontiere } - - { nom: portail, reseau: site-autorite, ip: 10.31.32.1, role: frontiere } - - { nom: portail, reseau: site-genome, ip: 10.31.33.1, role: frontiere } - - { nom: portail, reseau: site-service, ip: 10.31.34.1, role: frontiere } - - { nom: portail, reseau: site-sauvegarde, ip: 10.31.35.1, role: frontiere } - - { nom: portail, reseau: site-supervision, ip: 10.31.36.1, role: frontiere } + # Le noeud — ASUS Z10PE-D16 WS, deux processeurs, 2 x 128 Go. Deux cartes, deux roles + # (releve du 2026-10-13) : `nic0` (1G) porte `vmbr0`, l'administration seule ; `nic2` + # (10G) porte `vmbr1`, VLAN-aware et sans adresse, ou vivent les VLAN des VM. + - { nom: maurice, reseau: management, ip: 10.31.0.11, role: hyperviseur, via: vmbr0 } + - { nom: maurice, reseau: underlay-vxlan, ip: 10.31.50.11, role: hyperviseur, via: vmbr1 } + - { nom: maurice, reseau: transit-frontiere, ip: 10.0.4.11, role: hyperviseur, via: vmbr1 } - # LE GABARIT ET SON STOCKAGE. Sur un nœud unique, `clone_complet` est le choix sûr : - # un clone lié dépend à vie du gabarit, et il n'y a pas d'autre nœud pour le porter. + # Les machines du site naissent du gabarit du PLAN DU SITE (plan/10-intrants.yml), en + # clones complets, sur le NVMe du noeud (`nvme`, LVM-thin, ~460 Go) — decision de Daniel le + # 2026-10-13. `local-lvm` (130 Go, sur le SSD du systeme) ne les aurait pas tenues. + # `site-backup-01` deroge : il vit sur `miroir` (ZFS, 2 x 12 To) — plan/serveurs.yml. materialisation: - # MÊME VMID QUE PARTOUT AILLEURS DANS LA FLOTTE. Le gabarit est le même actif d'un - # site à l'autre ; lui donner un numéro par site obligerait à le chercher. - # LE VMID N'EST PLUS DECLARE ICI (2026-09-13). Il vivait a la fois dans - # `plan/10-intrants.yml` (`gabarit:`) et ici — et les deux ont diverge : le plan - # disait 9006, ce champ 99998, que le plan nomme justement `precedent`. - # - # Les machines du SITE naissaient donc de l'ancien gabarit et celles des - # LOCATAIRES du nouveau, sans que rien ne le dise — les deux clonent. - # - # `site_machines` lit desormais `underlay.gabarit()`, c'est-a-dire le PLAN DU - # SITE. Le motif d'origine tient toujours : cette source ne depend d'aucun - # symlink `instance`, donc le site ne clone jamais le gabarit d'un tenant. - # `local-lvm` — le stockage que Proxmox pose à l'installation. Sur un nœud unique il - # n'y a rien d'autre, et c'est honnête de le dire : quinze clones complets y tiennent - # ou n'y tiennent pas, et c'est la première chose à mesurer sur place. - stockage: local-lvm + stockage: nvme clone_complet: true