diff --git a/COLLECTE.md b/COLLECTE.md index df19154..9906e5e 100644 --- a/COLLECTE.md +++ b/COLLECTE.md @@ -1,8 +1,42 @@ -# À relever chez Technolibre — avant de lancer quoi que ce soit +# À relever sur place — TechnoLibre -> Une ligne non remplie ici est une ligne qui bloquera le déploiement plus tard, à un -> endroit où le message d'erreur ne dira pas qu'elle manquait. -> Référence : `docs/preparer-un-site-hebergeur.md` §7, adapté au cas **un seul nœud**. +**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. + +| 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 | + +**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 +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 a été décidé, et qu'il suffit de confirmer + +| | Valeur | Raison | +|---|---|---| +| Index du site | `31` | Les sites prennent leur propre index depuis le 2026-09-12 | +| 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 | +| 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 | +| Gabarit | `99998` | Le même dans toute la flotte | + +--- ## 1. Le chiffre qui décide de tout diff --git a/plan/10-intrants.yml b/plan/10-intrants.yml index 15e31ec..21d42ac 100644 --- a/plan/10-intrants.yml +++ b/plan/10-intrants.yml @@ -4,13 +4,13 @@ # 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`. -domaine_interne: <> -organisation: <> +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. -rebond: ansible@<> -cle_ssh: ~/.ssh/<> +rebond: ansible@10.31.0.1 +cle_ssh: ~/.ssh/technolibre integrations_exemptes: {} @@ -21,16 +21,16 @@ runner_cle_publique: "" # 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. gabarit: - vmid: <> + vmid: 99998 nom: modeleSetOPS-minimal - noeud: <> + noeud: atelier machine: q35 bios: ovmf - stockage: <> + stockage: local-lvm # 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. backup_pubkey: "" nftables_admin_ssh: [] -supervision_courriel: <> +supervision_courriel: sysadmin@technolibre.ca diff --git a/plan/applications.yml b/plan/applications.yml index 4c2f7b5..b10a379 100644 --- a/plan/applications.yml +++ b/plan/applications.yml @@ -9,7 +9,7 @@ # `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.<>` dans ses SAN, mais **aucune zone ne +# 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. # @@ -52,7 +52,7 @@ applications: # `ROOT_URL`, donc dans l'`origin` de chaque ecosysteme descendant, pour toujours. port: 443 expose: - - forge.<> + - 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 @@ -73,7 +73,7 @@ applications: groupe: serveur_step_ca hote: site-pki-01 expose: - - pki.<> + - pki.socle.internal # LE DNS — autoritatif et résolveur sur la même machine, à dessein. powerdns: @@ -83,7 +83,7 @@ applications: groupe: serveur_resolveur hote: site-dns-01 expose: - - dns.<> + - 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. @@ -119,7 +119,7 @@ applications: # `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.<> + - 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 @@ -156,7 +156,7 @@ applications: # 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.<>`, + # 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. @@ -164,7 +164,7 @@ applications: groupe: serveur_grafana hote: site-mon-01 expose: - - observatoire.<> + - 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. diff --git a/plan/serveurs.yml b/plan/serveurs.yml index 96bbc7c..0a5f580 100644 --- a/plan/serveurs.yml +++ b/plan/serveurs.yml @@ -23,7 +23,7 @@ serveurs: etat: actif reseau: site-pilotage ip: 10.31.31.11 - noeud: <> + noeud: atelier gabarit: { vcpu: 2, memoire: 4096, disque: 40G } vmid: 9001 variables: @@ -68,7 +68,7 @@ serveurs: etat: actif reseau: site-genome ip: 10.31.33.21 - noeud: <> + noeud: atelier gabarit: { vcpu: 2, memoire: 2048, disque: 120G } vmid: 9002 @@ -78,7 +78,7 @@ serveurs: etat: actif reseau: site-genome ip: 10.31.33.11 - noeud: <> + noeud: atelier 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. @@ -114,7 +114,7 @@ serveurs: etat: actif reseau: site-autorite ip: 10.31.32.11 - noeud: <> + noeud: atelier 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. @@ -134,7 +134,7 @@ serveurs: etat: actif reseau: site-service ip: 10.31.34.11 - noeud: <> + noeud: atelier gabarit: { vcpu: 2, memoire: 2048, disque: 40G } vmid: 9005 variables: @@ -176,7 +176,7 @@ serveurs: etat: actif reseau: site-sauvegarde ip: 10.31.35.11 - noeud: <> + noeud: atelier gabarit: { vcpu: 2, memoire: 2048, disque: 400G } vmid: 9010 @@ -193,7 +193,7 @@ serveurs: etat: actif reseau: site-supervision ip: 10.31.36.11 - noeud: <> + noeud: atelier gabarit: { vcpu: 2, memoire: 4096, disque: 64G } vmid: 9011 # ELLE PORTE UNE BASE, DONC DE L'ETAT — P36 l'a exige des la declaration. diff --git a/proxmox-hebergeur.yml b/proxmox-hebergeur.yml new file mode 100644 index 0000000..2d921cf --- /dev/null +++ b/proxmox-hebergeur.yml @@ -0,0 +1,57 @@ +# Le CLUSTER, vu par l'HEBERGEUR — pas par un tenant. +# +# API du cluster, noeuds, stockages, ponts : du materiel possede par l'hebergeur. +# Recopiees dans le group_vars de chaque tenant, ces valeurs avaient deja diverge chez +# Chezlepro — deux inventaires contradictoires du meme cluster. Ce fichier vit donc dans +# le depot de l'HEBERGEUR, a cote d'underlay.yml (D-14), et se trouve par derivation du +# symlink qui designe deja l'hebergeur (D-17). +# +# Les secrets (jeton d'API) n'entrent jamais ici : voute de l'instance. +# +# CREE LE 2026-09-13, ET C'EST UNE CONSEQUENCE DIRECTE DU CHOIX `routage_tenants: sdn`. +# En mode EVPN, `devis_opnsense` derive le prochain saut des routes de la frontiere depuis +# `proxmox_sdn.sortie_primaire`. Sans ce fichier, la derivation rend une chaine VIDE — et +# le devis se tait au lieu d'ecrire faux, ce qui est le bon comportement mais laisse la +# 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, par leur /etc/hosts. 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_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 + +# 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. +proxmox_ponts: +- vmbr0 + +proxmox_sdn: + # ASN DERIVE DE L'INDEX DU SITE (31), pas repris de Chezlepro (65000). Les deux sites + # ont vocation a etre relies ; deux clusters qui echangent des routes avec le meme + # numero d'AS produisent une panne dont le message ne parle pas d'AS. Un numero derive + # est unique par construction, comme tout le reste de l'adressage. + asn: 65031 + # HUIT CARACTERES AU PLUS — l'identifiant sert de base aux noms de bridge, veth et tap. + # Nomme d'apres le SITE (31), parce que le controleur est un objet de CLUSTER : il + # survivra au premier locataire et en servira d'autres. + controleur: EVPN0031 + noeuds_de_sortie: + - atelier + sortie_primaire: atelier + +# `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. +proxmox_stockages: +- local-lvm + +proxmox_validate_certs: false diff --git a/underlay.yml b/underlay.yml index ba66306..c5fa64e 100644 --- a/underlay.yml +++ b/underlay.yml @@ -22,16 +22,47 @@ underlay: tenants: OPS-Technolibre: 23 - # CE QUI ROUTE ENTRE LES ZONES D'UN LOCATAIRE — à trancher devant le matériel. + # CE QUI ROUTE ENTRE LES ZONES D'UN LOCATAIRE — TRANCHÉ LE 2026-09-13. + # + # Deux modes existent : # `switch` : un commutateur porte les SVI et les ACL (mode par défaut du moteur) - # `sdn` : EVPN sur le nœud, un VRF par locataire (éprouvé à 3 nœuds, jamais à 1) - # Voir COLLECTE.md §4 : la réponse dépend de ce qu'il y a entre le nœud et l'OPNsense. - routage_tenants: <> - routeur: <> # le commutateur, ou la frontière si elle route tout - dialecte: <> # dicte la forme des ACL et des routes du devis + # `sdn` : EVPN sur le nœud, un VRF par locataire + # + # ICI IL N'Y A PAS DE COMMUTATEUR DE NIVEAU 3. Entre le nœud et l'OPNsense, il n'y a + # qu'un lien. En mode `switch`, le seul équipement capable de porter les SVI serait + # donc la frontière elle-même : il faudrait lui ajouter SIX interfaces VLAN de plus — + # celles du locataire — en plus de ses six pattes de site, et vérifier à la main les + # ACL entre elles. Douze interfaces sur une machine, pour un écosystème. + # + # En `sdn`, le routage ET le filtrage inter-zone du locataire vivent SUR LE NŒUD. + # Aucun VLAN de locataire ne circule sur le fil, la frontière ne voit que le transit, + # et le moteur sait déjà poser tout ça (`appliquer_sdn`). L'inter-locataire, lui, + # sort du VRF et passe par la frontière, qui le police. + # + # L'OBJECTION — « EVPN sur un seul nœud, c'est un maillage sans pair » — est réelle + # mais se retourne : un VTEP unique n'a AUCUNE session à établir, là où le mode + # `switch` demanderait de configurer et d'éprouver douze interfaces routées. La + # complexité qu'on croyait éviter était de l'autre côté. + # + # C'est aussi le mode qu'exerce Chezlepro : mêmes chemins de code, mêmes devis. + routage_tenants: sdn + + # LA FRONTIÈRE ROUTE TOUT — il n'y a pas d'autre équipement de niveau 3 sur ce site. + # Le champ accepte « le commutateur, ou la frontière si elle route tout » : c'est le + # second cas. + routeur: portail + + # Sans commutateur, le dialecte ne commande presque rien (le devis switch n'émet plus + # ni VLAN de locataire, ni SVI, ni ACL en mode `sdn`). On garde celui de la flotte, + # pour qu'un exploitant qui passe d'un site à l'autre lise la même forme. + dialecte: binardat + mtu_overlay: 1450 - # À `false` quand le matériel ne sait pas lier une ACL à une interface de routage. - acl_inter_tenant: <> + + # UN SEUL LOCATAIRE, ET L'INTER-LOCATAIRE PASSE DÉJÀ PAR LA FRONTIÈRE. Rien à lier à + # une interface de routage qui n'existe pas. À revoir le jour où un deuxième + # écosystème s'installe ici — ce sera alors un geste, pas un effet de bord. + acl_inter_tenant: false stp: mode: rstp @@ -62,32 +93,37 @@ underlay: # 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: <>, mtu: 1500 } - - { nom: site-autorite, description: Autorité de certification, vlan: 32, sous_reseau: 10.31.32.0/24, pont: <>, mtu: 1500 } - - { nom: site-genome, description: Forge et cache de paquets, vlan: 33, sous_reseau: 10.31.33.0/24, pont: <>, mtu: 1500 } - - { nom: site-service, description: Noms (DNS autoritaire), vlan: 34, sous_reseau: 10.31.34.0/24, pont: <>, mtu: 1500 } - - { nom: site-sauvegarde, description: Dépôt de sauvegarde mutualisé, vlan: 35, sous_reseau: 10.31.35.0/24, pont: <>, mtu: 1500 } - - { nom: site-supervision, description: Supervision et observabilité, vlan: 36, sous_reseau: 10.31.36.0/24, pont: <>, mtu: 1500 } + - { 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 } hotes: # L'UNIQUE NŒUD. `via` = l'interface physique qui porte le trunk vers la frontière. - - { nom: <>, reseau: management, ip: <>, role: hyperviseur } - - { nom: <>, reseau: transit-frontiere, ip: 10.0.4.41, role: hyperviseur, via: <> } + - { nom: atelier, reseau: management, ip: 10.31.0.41, role: hyperviseur } + - { nom: atelier, reseau: transit-frontiere, ip: 10.0.4.41, role: hyperviseur, via: <> } # 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: <>, reseau: management, ip: 10.31.0.1, role: frontiere } - - { nom: <>, reseau: transit-frontiere, ip: 10.0.4.1, role: frontiere } - - { nom: <>, reseau: site-pilotage, ip: 10.31.31.1, role: frontiere } - - { nom: <>, reseau: site-autorite, ip: 10.31.32.1, role: frontiere } - - { nom: <>, reseau: site-genome, ip: 10.31.33.1, role: frontiere } - - { nom: <>, reseau: site-service, ip: 10.31.34.1, role: frontiere } - - { nom: <>, reseau: site-sauvegarde, ip: 10.31.35.1, role: frontiere } - - { nom: <>, reseau: site-supervision, ip: 10.31.36.1, role: frontiere } + - { 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 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. materialisation: - vmid_modele: <> - stockage: <> + # 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. + vmid_modele: 99998 + # `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 clone_complet: true