Set-OPS-Public/docs/carte-set-ops.md
Daniel Allaire 1832530f29 sondes : les six premieres, et le patron qui les rend eprouvables
Ajout de meta/supervision.yml a six roles, chacun deposant sa propre sonde
selon le contrat des greffons Nagios.

DEUX PRINCIPES POSES AU DOCUMENT DE CONCEPTION, parce que la premiere
sonde les a imposes :

1. UNE SONDE DOIT POUVOIR ETRE MISE EN DEFAUT PAR PARAMETRE. Cible et
seuils sont des variables du role : on la prouve rouge avec un port ferme
ou un seuil impossible, sur une machine reelle, sans rien casser, et
aussi souvent qu on veut. Une sonde qu on ne peut prouver qu en cassant un
service ne sera prouvee qu une fois.

2. LA SONDE VIT LA OU VIT LA VERITE. « Ce noeud est-il collecte ? » est
une sonde de serveur_prometheus, pas de client_metrique : une seule y voit
les N noeuds, et surtout elle voit le cas SILENCIEUX — celui qui a cesse d
etre collecte ne peut pas s en plaindre.

LES SIX : cache-apt (artefacts, repond + place), resolution (resolveur,
zone interne ET Internet — deux chemins distincts), forge (forgejo, son
propre /api/healthz), collecte (prometheus, 15/15 cibles), tableaux
(grafana, base ok), ingestion (loki, PRET a ingerer, pas seulement en
ecoute).

TROIS FOIS J AI ECRIT LA SONDE AVANT DE MESURER, ET TROIS FOIS ELLE A EU
TORT. La forge : port 443 et chemin des depots INVENTES — elle ecoute en
3000 derriere l edge et n a legitimement aucun depot. Loki : j ai conclu
« panne persistante » sur deux lectures prises a quelques secondes d
intervalle, juste apres un redemarrage ; l anneau etait ACTIVE et la
reponse est passee a ready moins d une minute plus tard. Le delai de
stabilisation est desormais un AVERTISSEMENT nomme, pas une panne.

On demande au service ce qu il pense de lui-meme quand il sait le dire
(healthz, /ready, /api/health) plutot que d inventer un critere de l
exterieur.

make prouver : CONFORME.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-10 02:48:55 -04:00

13 KiB

Carte d'orientation Set-OPS

Pour qui : le mainteneur — celui qui va modifier le moteur. À lire avant d'ajouter quoi que ce soit.

Tu viens plutôt exploiter un écosystème déjà déployé ? Wiki → Reprendre l'écosystème. Tu apprends le métier ? Wiki → Accueil.

Point d'entrée vers le corpus documentaire, et catalogue des mécanismes transverses — ceux qui vivent dans le code et qu'on re-découvre sinon. Créée le 2026-07-03 après un audit du dépôt, revue le 2026-07-29. But : ne plus re-déterrer ce qui existe.

Le dépôt est déjà bien documenté. Le manque n'était pas la doc du modèle, mais (a) un index « par où commencer » et (b) une carte des mécanismes (dispersés dans le code + les README de rôles). Cette page comble ces deux trous.

Le dépôt en chiffres

Ces valeurs sont mesurées, pas recopiées : P48 les recompte et refuse tout écart. Elles étaient toutes fausses le 2026-08-26 — de 6 rôles, de 12 pièces d'audit, de 8 décisions. Aucune ne faisait travailler personne ; mais une carte dont les faits vérifiables sont faux cesse d'être consultée, et c'est alors ses pointeurs qu'on perd.

Ce qu'on compte Combien Comment on le mesure
rôles 67 roles/*/
README de rôles 67 roles/*/README.md — l'écart avec la ligne au-dessus est la dette
documents 40 docs/*.md
pièces d'audit 41 docs/audit/*
unités de wiki 27 wiki/*.md
décisions en vigueur 83 lignes | **D-nn** | de decisions-architecture.md
décisions renversées 3 lignes | **D-nn** — du même document

1. À lire d'abord (dans l'ordre)

Sujet Documents
Autorité / gouvernance AGENTS.md (source d'autorité), CLAUDE.md, docs/MISE-A-JOUR-CODEX-CLAUDE.md
Le modèle (plan) docs/architecture-set-ops.md (survol) → docs/plan-et-generation.md (à fond) → docs/meta-classe.md (concept)
Services, maturité, dette docs/catalogue-services.md (la carte de maturité + la cruft y sont déjà)
Exploitation / VM docs/vm-lifecycle.md, docs/procedure-template-debian13-proxmox.md, docs/config-proxmox.md, docs/nomenclature-vm.md, docs/multi-instances.md
Conceptions de domaine docs/identite-sso.md, docs/courriel-conception.md, docs/bindings-conception.md, docs/dns-interne.md, docs/dimensionnement-ressources.md, docs/integrations-vm.md
Réseau / pare-feu docs/flux-conception.md (le modèle) → docs/registre-flux.md (généré, matrice d'audit) → docs/frontiere-opnsense.md (la bordure nord/sud) ; underlay : underlay.yml.example + make underlay
Ordre de déploiement docs/couches-deploiement.yml (couches) + docs/dependances-groupes.yml (graphe) → playbooks/site.yml (généré, make site)
Conformité du déployé docs/devis-services.md — les cinq devis de service (make identite-plan, certificats-plan, expositions-plan, postgresql-plan, courriel-plan) et les cinq devis d'infrastructure (frontiere-plan, proxmox-fw-plan, sdn-plan, underlay-plan, placement-plan). Répondent à ce que make prouver ne demande jamais : ce qui tourne correspond-il à ce qui est déclaré ?
Preuve / recette docs/audit/affirmations.md (registre), make prouver → docs/audit/preuve-<date>.md — statique : lit le dépôt, aucun appel réseau ; la conformité du déployé est l'affaire des devis de service (ligne au-dessus), docs/audit/plan-de-recette.md (généré du wiki), docs/audit/protocole-operateur-independant.md
Décisions d'architecture docs/decisions-architecture.md — les décisions en vigueur (comptées ci-dessus), pourquoi, où lire le détail, et ce qui les garde ; plus les décisions renversées et leur cause
SDN / routage docs/sdn-evpn.md — décision du 2026-08-02 : le routage inter-zone passe des commutateurs aux hyperviseurs (zones EVPN = VRF). En service depuis le 2026-08-03 (routage_tenants: sdn dans l'underlay.yml du site) : les trunks ne portent plus que deux VLAN d'underlay au lieu de quinze, les passerelles .1 sont anycast sur chaque hyperviseur. Écart mesuré par make sdn-plan
Migration de tenant docs/migration-tenant.md — recette en neuf étapes (0 à 8), machine à états, gardes ; le receveur se construit avant tout gel
Exploitation courante docs/runbooks-exploitation.md, docs/intrants-communs.md, docs/intrants-base-gui-conception.md, docs/theme-forgejo-hors-flotte.md
Pédagogie (le wiki) wiki/ — les unités (comptées ci-dessus) publiées par make wiki-publier ; entrer par wiki/Home.md
Vision / positionnement docs/ecosysteme-chezlepro.md, docs/positionnement.md, docs/pouvoirs-set-ops.md

2. Les mécanismes transverses (et OÙ ils vivent)

Ce que je re-découvre sinon. Consulter avant de concevoir un nouveau mécanisme.

Mécanisme Ce que c'est Où, dans le code Doc
Plan → inventaire plan/*.yml → hosts.yml généré scripts/instancier.py, scripts/inventory_rules.py plan-et-generation.md
Schéma des registres la forme des six registres — champs, types, énumérations, requis — dérivée des validateurs, jamais écrite à la main. Sert à générer les formulaires plutôt qu'à les écrire. La cohérence reste aux valider_* : un schéma ne sait pas dire qu'un consommateur désigne une application inexistante scripts/schema_plan.py (make schema) → docs/audit/schema-plan.json ; garde P61 plan-et-generation.md
Nomenclature dérivée VMID / IP / VLAN / FQDN dérivés inventory_rules.deriver_nomenclature + plan/nomenclature.yml nomenclature-vm.md
Dimensionnement RAM/CPU/disque sommés par logiciel roles/*/meta/empreinte.yml → deriver_ressources dimensionnement-ressources.md
Bindings app→app lien côté app (liens) résolu en host_vars plan/applications.yml liens: + roles/*/meta/liens.yml + instancier.resoudre_liens bindings-conception.md
Bindings app→base lien côté base (consommateur/portee) résolu dans le rôle plan/bases-donnees.yml + rôle utilitaire resoudre_base (lookup('vars', secret), no_log) inclus par le consommateur bindings-conception.md §5
Résolution d'annuaire connexion LDAP (uri/base DN/bind) dérivée, jamais recopiée rôle utilitaire resoudre_annuaire (inclus par dovecot/postfix/keycloak/icingaweb2 et amorcage_acces) identite-sso.md
Plancher de résolution /etc/hosts généré depuis l'inventaire + alias d'expose → l'écosystème se résout DNS éteint rôle hosts_statiques (appliqué dans la couche socle) dns-interne.md
Pont de certificat cert step_ca → service, resync au renouvellement script *-cert-sync + unité .path, dans chaque rôle serveur ; cert déposé par client_pki —
Ordonnancement socle-first socle/durci avant les client_* serveur_debian/serveur_durci d'abord (posent /etc/hosts via hosts_statiques) —
Sûreté check-mode dry-run fiable when: not ansible_check_mode sur les tâches de service + handlers —
Voûte au déploiement secret jamais en clair ; une voûte, une clé depuis le 2026-08-28 ANSIBLE_VAULT_IDENTITY_LIST construit par scripts/voutes.py (clé nommée ~/.config/setops-vault-<dépôt>) ; déréférencé par lookup('vars', <nom>) autorisation.md §6.1
Multi-instance un dépôt par écosystème ; l'active = symlink instance/, les autres découvertes par convention (dossiers frères, aucun registre) active : symlink instance/ ; découverte : scripts/instances.py / devis_reseau.py (glob ../*/plan/nomenclature.yml avec index) ; garde-fou collision : preuve P21 multi-instances.md
Exposition → edge app expose un FQDN public servi par un edge plan/domaines.yml + expose (applications) bindings-conception.md §4
Exploitation de l'hébergeur ses opérations n'appartiennent à aucun tenant et restent hors overlay à moitié construit : les VM du site ont leur inventaire (scripts/site_inventaire.py), leur socle, leur durcissement, leurs sauvegardes et leur supervision (site-mon-01, 2026-09-02). Les équipements — hyperviseurs, commutateurs, frontière — n'ont toujours ni inventaire, ni sauvegarde de configuration, ni supervision hebergeur-exploitation.md
Authentification web → Keycloak ; LDAP source unique ; secours par sudo, formulaire local non annoncé <rôle>_connexion_locale: false (grafana, forgejo, nextcloud) ; garde de version Forgejo ≥ 10 authentification.md
Accès & habilitations Set-OPS amorce un accès sysadmin puis se retire ; les appartenances aux groupes ne sont jamais réconciliées — c'est une personne qui gouverne construit et éprouvé (2026-08-08) : rôle amorcage_acces (idempotence par existence, D-67), groupes projetés en rôles par serveur_keycloak, meta/acces.yml dans les 5 rôles web ; chaîne LDAP → Keycloak → groupe → service exercée de bout en bout sur Icinga Web 2 autorisation.md (§6 = runbook de reprise)
SDN EVPN ajouter un tenant implique 1 zone + 6 VNets + 6 sous-réseaux, tous dérivés du seed scripts/devis_sdn.py (make devis-sdn) ; nommage dérivé du seed (t17, t17serv), ≤ 8 caractères ; garde P30 sdn-evpn.md §2
Pools Proxmox un pool par tenant : les noms courts de VM sont volontairement identiques d'un tenant à l'autre (même fonction, même nom), et seule la console Proxmox en souffrait scripts/devis_proxmox_pools.py (make devis-proxmox-pools) ; nom dérivé de l'index ; garde de collision = preuve P28 decisions-architecture.md D-37
Routage aucun commutateur ne route : la frontière est le seul équipement L3 ; les switches commutent passerelle dit qui porte la passerelle, le SVI se dérive du rôle du porteur decisions-architecture.md D-49/50
Devis de service LIT le système en marche et le compare à ce que le plan dérive ; n'écrit rien (D-23/D-24 portés du réseau aux services). Le playbook relève, Python compare playbooks/maintenance/devis-*.yml + scripts/devis_*.py ; cible make <sujet>-plan devis-services.md
Frontière nord/sud les flux pair: externe — sautés par le pare-feu d'hôte — sont la politique de bordure scripts/devis_opnsense.py (make devis-opnsense) ; garde d'accès admin = preuve P24 frontiere-opnsense.md

⚠️ Deux directions de binding, assumées : app→app côté app (instancier), app→base côté base (registre, résolu en rôle pour que le secret ne quitte jamais le rôle). Ne pas unifier l'un dans l'autre sans raison. Cf. bindings-conception.md.

3. Maturité & dette

  • Maturité des rôles, échafaudages, rôles-catégories inertes : voir docs/catalogue-services.md « État d'implémentation » (source de vérité, tenue à jour).
  • Dette (audit 2026-07-03, revu le 2026-07-29) :
    • ✅ soldé — README de rôles : tous les rôles en ont un (les 12 manquants écrits le 2026-07-29 : serveur_debian, hosts_statiques, resoudre_base, resoudre_annuaire, serveur_dovecot, serveur_postfix, serveur_rspamd, client_backup, serveur_backup, client_resolveur, serveur_oauth2_proxy, serveur_icingaweb2).
    • ✅ soldé — expose est consommé au déploiement : plan/applications.yml → filtre expositions_des_applications → vhosts nginx dérivés (roles/serveur_nginx/tasks/main.yml, template expositions.conf.j2, drapeau serveur_nginx_publier_expositions), + alias /etc/hosts posés par hosts_statiques,
      • SANs des certificats d'edge dérivés par scripts/instancier.py.
    • ⏳ ouvert — meta/liens.yml seulement sur serveur_postfix (mailstore, milter) : les autres liens app→app viendront.
    • ⏳ ouvert — requiert : câblé côté GUI (édition + validation valider_applications) mais pas consommé au déploiement ; c'est un indice de dépendance applicative. Les dépendances de groupes (celles qui pilotent l'ordre) vivent dans docs/dependances-groupes.yml + docs/couches-deploiement.yml, et sont bel et bien consommées par l'orchestrateur (scripts/orchestrer.py → playbooks/site.yml).

4. Discipline (pour ne plus re-déterrer)

Avant de concevoir ou d'ajouter un mécanisme :

  1. lire cette carte + le doc du sujet ;
  2. arpenter le code (grep) et lire les README des rôles concernés ;
  3. éprouver l'outil AVANT d'écrire le rôle qui l'enveloppe — une machine jetable hors plan se fabrique en deux minutes (make cloner-vm, cf. vm-lifecycle.md §4bis). C'est ce qui a évité les bugs de premier déploiement de rspamd, et ce qui a tranché le pivot Stalwart → Postfix/Dovecot. Elle est invisible au moteur : à détruire à la main ;
  4. étendre / factoriser l'existant plutôt qu'ajouter un chemin parallèle.

Un seul agent IA travaille dans le dépôt à la fois (Codex ou Claude) — cf. AGENTS.md.