--- # Les machines du SITE — l'équivalent de `plan/serveurs.yml` chez un tenant. # # 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. # # `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. 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 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. 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-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_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 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 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 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 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 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. site-mon-01: etat: actif reseau: site-supervision ip: 10.31.36.11 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. # # 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]