Set-OPS-Public/docs/carte-set-ops.md
Daniel Allaire 6a62f0a4c7 authentification : SSO Keycloak devant, secours par sudo, formulaire local fermé
Directive : toute authentification web passe par Keycloak, LDAP est la source
unique des comptes, chaque service garde un accès de secours par sudo sur
l'hôte. Les trois sont indissociables — la chaîne service → Keycloak → LDAP est
en série, donc sans secours une panne exclut tout le monde, y compris pour
réparer. Portée : le web seulement ; IMAP/SMTP se lient à LDAP directement et
SSH est en clé seule.

Posture <rôle>_connexion_locale, false par défaut. Le compte local existe — il
ne peut pas dépendre de Keycloak — mais son formulaire n'est plus proposé au
repos : ouvert en permanence, il contourne la politique de mot de passe, le MFA
et surtout la révocation centrale.

Vérifié auprès de l'amont, puis par rendu réel des gabarits dans les deux
postures :
- Grafana  GF_AUTH_DISABLE_LOGIN_FORM  → ferme ;
- Forgejo  ENABLE_INTERNAL_SIGNIN + ENABLE_BASIC_AUTHENTICATION → ferme, API
  Basic comprise. N'existe que depuis la v10 (ticket amont 7476) ; le rôle
  épingle 10.0.0 et un assert refuse la fermeture en deçà, car le réglage serait
  ignoré sans erreur ;
- Nextcloud hide_login_form → MASQUE seulement : ?direct=1 reste le chemin de
  secours documenté par l'amont. Écrit comme tel, sans prétendre à l'équivalence.

Défaut attrapé par le rendu : la condition Forgejo sans `| bool` n'émettait rien
dans aucune posture — une valeur en chaîne est vraie au sens Jinja, la connexion
locale serait restée ouverte en silence.

docs/authentification.md, décisions D-38 à D-41. ansible-lint (production) sans
échec, 28 preuves OK.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 16:50:36 -04:00

8.7 KiB

Carte d'orientation Set-OPS

À lire en premier. 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é (26 docs + 7 pièces d'audit + 21 unités de wiki, et un README par rôle). 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.

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)
Preuve / recette docs/audit/affirmations.md (registre), make prouverdocs/audit/preuve-<date>.md, docs/audit/plan-de-recette.md (généré du wiki), docs/audit/protocole-operateur-independant.md
Décisions d'architecture docs/decisions-architecture.md28 décisions, 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). Non éprouvé : spike avant génération
Migration de tenant docs/migration-tenant.md — recette en 8 étapes, 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/ — 21 unités (+ _Sidebar) 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/*.ymlhosts.yml généré scripts/instancier.py, scripts/inventory_rules.py 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.ymlderiver_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) 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 ANSIBLE_VAULT_PASSWORD_FILE / ~/.config/setops-vault-pass ; déréférencé par lookup('vars', <nom>)
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
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
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
Frontière nord/sud les flux pair: externesauté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_unbound, 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.
    • ouvertmeta/liens.yml seulement sur serveur_postfix (mailstore, milter) : les autres liens app→app viendront.
    • ouvertrequiert : 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.pyplaybooks/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. é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.