Le site de reprise refait sur le modele de SITE-Chezlepro, et sa face publique par relais

- Carte au schema actuel (index 31, zones derivees, publication VLAN 37), equipements reels :
  frontiere requin, noeud maurice, commutateur caillou.
- Neuf machines, memes noms et VMID qu'au site de Chezlepro ; runner des deux locataires.
- maurice : vmbr0 administration (nic0), vmbr1 VLAN-aware pour les VM (nic2) ; stockages nvme
  et miroir (ZFS 2 x 12 To, site-backup-01).
- opnsense.yml : optN mesures (opt1 transit, opt2..opt8 zones, opt9 RELAIS) ; face publique par
  le relais (opt9, RELAIS_GW), adresse du site et pool des locataires ; silence du relais.
- underlay.yml : reseau `relais` (tunnel WireGuard 10.31.60.0/30), hote relais (VPS OVH) et
  cles publiques des deux bouts.
- plan/domaines.yml et plan/mainteneurs.yml ; documentation (README, PREMIERE-HEURE,
  COLLECTE) a jour du releve sur place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-10-13 21:20:04 -04:00
parent 8b80a51a18
commit 2e223f135a
13 changed files with 521 additions and 538 deletions

1
.gitignore vendored
View file

@ -12,4 +12,3 @@
*.key
*.vault.yml.bak
flux-genere/

View file

@ -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 |
|---|---|---|
| `<<IFACE>>` | `ip -br link` sur le nœud | Le nom de la carte réseau dépend du matériel (`eno1`, `enp1s0`…) |
| `<<IP_PUBLIQUE>>` | OPNsense, interface WAN | Donnée par le fournisseur d'accès |
| `<<IP_FRONTIERE_ADMIN>>` | OPNsense, interface de gestion | Dépend du plan d'adressage existant sur place |
| `<<optN>>` ×9 | OPNsense → Interfaces → Assignments | Les noms `optN` sont attribués dans l'ordre de création |
| `<<lan|optN>>` | Idem | Selon que la patte de gestion est la LAN d'origine ou une autre |
| `<<optN>>` ×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 ?

View file

@ -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 <ta-carte>
```
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.

View file

@ -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 (`<<IFACE>>`).
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

View file

@ -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://<<IP_FRONTIERE_ADMIN>>
opnsense_wan_ip: <<IP_PUBLIQUE>>
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: <<optN>>
site-autorite: <<optN>>
site-genome: <<optN>>
site-service: <<optN>>
site-sauvegarde: <<optN>>
site-supervision: <<optN>>
# 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: <<optN>>
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: <<optN>>
opnsense_if_wan: wan
opnsense_if_transit: <<optN>>
opnsense_if_wan: wan
opnsense_if_gestion: <<lan|optN>>
opnsense_if_site: <<optN>>
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

View file

@ -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

View file

@ -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/<rôle>.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

View file

@ -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

10
plan/domaines.yml Normal file
View file

@ -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

9
plan/mainteneurs.yml Normal file
View file

@ -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

View file

@ -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.<index>.<vlan de la zone>.<meme dernier octet>, 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

View file

@ -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

View file

@ -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.<index>.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.<vlan>.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: <<IFACE>> }
- { nom: atelier, reseau: transit-frontiere, ip: 10.0.4.41, role: hyperviseur, via: <<IFACE>> }
- { 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