Publication du wiki depuis le depot (source: c9d31e9)
parent
b6167f2cf4
commit
4da68c7ecd
23 changed files with 923 additions and 123 deletions
|
|
@ -41,9 +41,18 @@ Déclaratif dans Set-OPS : `serveur_keycloak_realm_roles`, `_role_mapper_clients
|
|||
**zéro coupure SSO**. Une identité (`testmail`), et c'est **le rôle** — pas la connexion — qui décide
|
||||
d'Explore.
|
||||
|
||||
> **Raffinement souverain** : ici le rôle est assigné *explicitement* à testmail. L'idéal est de le
|
||||
> piloter par un **groupe d'annuaire** (LDAP → Keycloak → claim), pour que *l'appartenance* gouverne
|
||||
> l'autorisation. C'est le vrai « l'annuaire gouverne l'accès ».
|
||||
> **Ce « raffinement » est construit depuis le 2026-08-08.** Cette unité le présentait comme
|
||||
> un idéal à atteindre ; c'est le mécanisme en vigueur. Les **groupes LDAP** sont projetés
|
||||
> dans Keycloak et émis en claim (`roles/serveur_keycloak/tasks/groupes-ldap.yml` et
|
||||
> `claim-groupes.yml`), et chaque service déclare le groupe qu'il reconnaît dans son
|
||||
> `meta/acces.yml` — `sysadmin ⇒ Admin`, `personnel ⇒ Viewer` chez Grafana. C'est donc bien
|
||||
> **l'appartenance** qui gouverne, pas une assignation nominative.
|
||||
>
|
||||
> La règle qui va avec : **un service nomme un groupe, jamais une personne**. Nommer
|
||||
> quelqu'un créerait une dette qu'on découvre le jour du départ, service par service — et il
|
||||
> faudrait un déploiement pour révoquer. L'assignation explicite à `testmail` de l'exemple
|
||||
> ci-dessus reste utile pour *comprendre* la mécanique du claim ; ce n'est pas la façon dont
|
||||
> on donne un accès. Voir `docs/autorisation.md` §5.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,10 @@ Registre ──> PostgreSQL crée la base + le compte propriétaire
|
|||
|
||||
Le **secret** vit dans la **voûte** (Ansible Vault), déréférencé **au déploiement**, jamais en clair
|
||||
dans le plan. C'est une **liaison** *app → base*, de modalité **requise** (Keycloak sans sa base ne
|
||||
démarre pas). Consommateurs prouvés : Keycloak, Forgejo, IcingaDB.
|
||||
démarre pas). Le registre porte aujourd'hui **quatre bases** — `keycloak`, `forgejo`,
|
||||
`icingadb`, `nextcloud` — et **cinq rôles** incluent `resoudre_base` pour bâtir leur
|
||||
connexion : `serveur_keycloak`, `serveur_forgejo`, `serveur_icinga`, `serveur_icingaweb2`,
|
||||
`serveur_nextcloud`.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -54,10 +54,13 @@ Tu as appris **MTA/MDA/MUA, SMTP vs soumission, IMAP, la déliverabilité** —
|
|||
|
||||
1. **Envoie via la soumission `:587`** (client authentifié) :
|
||||
```bash
|
||||
swaks --server edge-mta-01.lab.chezlepro.internal:587 --tls \
|
||||
--auth LOGIN --auth-user testmail@lab.chezlepro.internal --auth-password MotDePasseTest123 \
|
||||
--from testmail@lab.chezlepro.internal --to testmail@lab.chezlepro.internal --header 'Subject: essai'
|
||||
swaks --server edge-mta-01.chezlepro.internal:587 --tls \
|
||||
--auth LOGIN --auth-user testmail@chezlepro.internal --auth-password "$MDP_ESSAI" \
|
||||
--from testmail@chezlepro.internal --to testmail@chezlepro.internal --header 'Subject: essai'
|
||||
```
|
||||
*(`MDP_ESSAI` se saisit à la main — `read -rs MDP_ESSAI`. Un mot de passe écrit ici
|
||||
partirait dans l'historique du shell et dans le dépôt public : ce document en portait un
|
||||
en clair jusqu'au 2026-09-06.)*
|
||||
`235 Authentication successful` puis `250 queued` = ① en action.
|
||||
2. **Lis la boîte** (le MDA) : `doveadm search -u testmail mailbox INBOX all | wc -l` sur infra-mail-01.
|
||||
3. **Casse & répare.** Coupe l'annuaire (arrête OpenLDAP), renvoie un courriel : Postfix **rejette le
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
## ① Le concept *(générique)*
|
||||
|
||||
Les machines se parlent par **adresses IP** ; les humains (et les configs) utilisent des **noms**.
|
||||
La **résolution de noms** fait le pont : `keycloak.lab…` → `192.168.15.21`.
|
||||
La **résolution de noms** fait le pont : `keycloak.chezlepro.internal` → `10.17.17.11`.
|
||||
|
||||
Plusieurs couches, de la plus locale à la plus globale :
|
||||
- **Fichier hosts** (`/etc/hosts`) : une table statique, locale, **consultée en premier**, **sans
|
||||
aucun réseau**. Increvable, mais manuelle.
|
||||
- **DNS autoritatif** : le serveur qui **détient la vérité** d'une zone (ex. `lab.chezlepro.internal`)
|
||||
- **DNS autoritatif** : le serveur qui **détient la vérité** d'une zone (ex. `chezlepro.internal`)
|
||||
et répond pour ses noms (enregistrements **A**, **SOA**…).
|
||||
- **DNS récursif (résolveur)** : celui que tes machines interrogent ; il **cherche pour toi**
|
||||
(cache local, puis interne, puis Internet).
|
||||
|
|
@ -28,14 +28,21 @@ chercher* la réponse pour toi »).
|
|||
|---|---|---|
|
||||
| **1. Le plancher** | `hosts_statiques` (socle) → `/etc/hosts` sur **chaque** nœud | résout **même DNS éteint**, dès le bootstrap. Le filet en dessous de tout. |
|
||||
| **2. Autoritatif** | `serveur_powerdns` (PowerDNS) | la zone interne, les enregistrements **A**. |
|
||||
| **3. Récursif local** | `client_unbound` (**opt-in**) | résolveur local : stub-zone → PowerDNS pour l'interne, récursion pour le reste. |
|
||||
| **3. Récursif** | `serveur_resolveur` — **un** Unbound pour tout le tenant | récurse depuis la racine, délègue la zone souveraine à PowerDNS. |
|
||||
| *(l'intégration)* | `client_resolveur` — **universelle**, sur chaque nœud | n'installe rien : écrit `/etc/resolv.conf` pour désigner le résolveur ci-dessus. |
|
||||
|
||||
> **Le récursif n'est plus « local », et il n'est plus optionnel.** Avant le 2026-08-24,
|
||||
> `client_resolveur` posait un Unbound sur *chaque* VM — N démons identiques pour un service
|
||||
> unique. Il n'installe plus rien, et son intégration est **universelle, sans aucune
|
||||
> exemption** : pas même l'hôte qui porte le résolveur, qui se sert lui-même.
|
||||
|
||||
Le **plancher** est le cœur pédagogique : parce que chaque nœud connaît *tout l'écosystème* par
|
||||
`/etc/hosts`, **rien ne dépend du DNS pour démarrer** — PowerDNS devient une *commodité*, pas un
|
||||
point de défaillance unique. On construit la robustesse **de bas en haut**.
|
||||
|
||||
C'est aussi ce que **tu** utilises depuis ta machine : mettre `192.168.15.21 keycloak.lab…` dans
|
||||
ton `/etc/hosts`, c'est exactement le même « plancher ».
|
||||
C'est aussi ce que **tu** utilises depuis ta machine : mettre
|
||||
`10.17.16.11 keycloak.chezlepro.internal` dans ton `/etc/hosts`, c'est exactement le même
|
||||
« plancher ».
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -56,23 +63,28 @@ Tu as appris **la hiérarchie de résolution** (hosts → récursif → autorita
|
|||
|
||||
1. **Le plancher, sans DNS.** Sur un nœud :
|
||||
```bash
|
||||
getent hosts keycloak.lab.chezlepro.internal # répond via /etc/hosts, zéro DNS
|
||||
getent hosts keycloak.chezlepro.internal # répond via /etc/hosts, zéro DNS
|
||||
grep chezlepro /etc/hosts | head
|
||||
```
|
||||
2. **Interroge l'autoritatif.** Demande à PowerDNS directement :
|
||||
```bash
|
||||
dig @infra-dns-01.lab.chezlepro.internal keycloak.lab.chezlepro.internal A +short
|
||||
dig @infra-dns-01.lab.chezlepro.internal lab.chezlepro.internal SOA +short
|
||||
dig @infra-dns-01.chezlepro.internal keycloak.chezlepro.internal A +short
|
||||
dig @infra-dns-01.chezlepro.internal chezlepro.internal SOA +short
|
||||
```
|
||||
3. **Vois les couches.** Compare `getent hosts` (plancher) et `dig` (DNS) : **deux chemins**, même IP.
|
||||
4. **Casse & répare.** Sur un nœud **sans** `client_unbound`, vide `/etc/hosts` de ses entrées
|
||||
`chezlepro` (garde une sauvegarde !) et coupe l'accès au DNS : la résolution interne **échoue**.
|
||||
Restaure `/etc/hosts` : ça remarche **sans DNS**. Tu viens de *sentir* pourquoi le plancher est le
|
||||
filet de sécurité.
|
||||
4. **Casse & répare.** Vide `/etc/hosts` de ses entrées `chezlepro` (garde une sauvegarde !)
|
||||
**et** pointe `/etc/resolv.conf` ailleurs : la résolution interne **échoue**. Restaure
|
||||
`/etc/hosts` seul : ça remarche **sans DNS**. Tu viens de *sentir* pourquoi le plancher
|
||||
est le filet de sécurité.
|
||||
5. **Le piège du récursif.** Demande un nom qui n'existe pas sous `internal.`, puis
|
||||
redemande un nom qui existe. Si le résolveur répond NXDOMAIN aux deux, tu viens de
|
||||
reproduire la panne de deux jours du 2026-09-02 : la racine étant signée, elle *prouve*
|
||||
que `internal.` n'existe pas, et Unbound étend ce « non » à tout ce qui est dessous —
|
||||
sans jamais interroger la stub-zone. Remède : `harden-below-nxdomain: no`.
|
||||
|
||||
---
|
||||
|
||||
## Pour aller plus loin *(dépôt)*
|
||||
- Rôles : `roles/hosts_statiques` (le plancher), `roles/serveur_powerdns`, `roles/client_unbound`.
|
||||
- Rôles : `roles/hosts_statiques` (le plancher), `roles/serveur_powerdns`, `roles/client_resolveur`.
|
||||
- Conception des 3 couches + frontière publique : `docs/dns-interne.md`.
|
||||
- Note : `client_unbound` est une **liaison optionnelle** (opt-in) — voir l'unité *Liaisons*.
|
||||
- Note : `client_resolveur` est une **intégration universelle** (elle suit l'existence de `serveur_resolveur`) — voir l'unité *Liaisons* et `docs/integrations-vm.md`.
|
||||
|
|
|
|||
139
Filiation-signatures-et-témoins.md
Normal file
139
Filiation-signatures-et-témoins.md
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
# Filiation, signatures et témoins
|
||||
|
||||
> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer.
|
||||
|
||||
Un écosystème Set-OPS peut en **engendrer** un autre. Dès qu'il y a une descendance, trois
|
||||
questions apparaissent, et aucune n'est technique au départ :
|
||||
|
||||
- **de qui** cet écosystème descend-il ?
|
||||
- **qui** a le droit de modifier ce dont il descend ?
|
||||
- comment le savoir **sans faire confiance** à celui qui héberge le code ?
|
||||
|
||||
---
|
||||
|
||||
## ① Le concept
|
||||
|
||||
### Git est déjà une chaîne de hachage
|
||||
|
||||
C'est la chose la plus utile à comprendre, et la moins connue. Chaque commit contient
|
||||
l'**empreinte** de son parent. Changer une ligne d'il y a trois mois change l'empreinte de
|
||||
ce commit — donc celle du suivant, et de tous les autres jusqu'à aujourd'hui.
|
||||
|
||||
```
|
||||
A ←── B ←── C ←── D modifier B casse C et D
|
||||
```
|
||||
|
||||
C'est un **arbre de Merkle** : la même structure de données qu'une blockchain. L'intégrité
|
||||
est déjà là, gratuitement, depuis 2005.
|
||||
|
||||
### Ce que la chaîne ne dit pas
|
||||
|
||||
**Qui a écrit.** `user.name` est purement déclaratif : n'importe qui peut signer « Daniel
|
||||
Allaire » et pousser. Rien ne lie ce nom à une personne.
|
||||
|
||||
C'est ce que corrigent les **signatures**. Avec une clé — la même clé SSH que pour se
|
||||
connecter — on scelle une étiquette ou un commit. Qui possède la **clé publique** peut
|
||||
vérifier ; qui ne possède pas la **clé privée** ne peut pas contrefaire.
|
||||
|
||||
Reste alors une question : *quelles clés ont le droit de signer ?* La réponse doit vivre
|
||||
**avec le code**, pas chez l'hébergeur — sinon on remplace la confiance en une personne par
|
||||
la confiance en une plateforme.
|
||||
|
||||
### Les témoins, ou pourquoi la fractale est le registre
|
||||
|
||||
Une signature prouve l'auteur, pas que l'histoire n'a pas été **remplacée**. Celui qui tient
|
||||
la forge peut réécrire et re-signer.
|
||||
|
||||
Contre ça, un seul remède : la **multiplicité**. Si chaque écosystème enfant porte une copie
|
||||
du code dont il descend, réécrire l'histoire suppose de convaincre **tous les descendants**.
|
||||
C'est exactement ce qu'une blockchain achète au prix d'une machinerie considérable — et
|
||||
qu'une lignée produit comme **effet secondaire de sa forme**.
|
||||
|
||||
> **Pourquoi pas une blockchain, alors ?** Elle résout un problème précis : *qui écrit
|
||||
> ensuite, quand personne ne fait confiance à personne et qu'il y a de l'argent en jeu.*
|
||||
> Ici : les membres sont connus, il n'y a pas d'argent dans la boucle, et une ancre de
|
||||
> confiance existe déjà. Une chaîne publique ajouterait une dépendance à un réseau
|
||||
> extérieur ; une chaîne privée, une base de données distribuée exigeant plusieurs
|
||||
> opérateurs — l'inverse de « un humain doit pouvoir la faire tourner ».
|
||||
|
||||
---
|
||||
|
||||
## ② Dans Set-OPS
|
||||
|
||||
### Les quatre dépôts du génome
|
||||
|
||||
Un écosystème ne se reproduit pas depuis ses machines. Il se reproduit depuis **quatre
|
||||
dépôts** — et `make genome` les nomme :
|
||||
|
||||
| Rôle | Ce qu'il porte |
|
||||
|---|---|
|
||||
| **moteur** | Set-OPS : les rôles, les preuves, le Makefile |
|
||||
| **instance** | le plan du tenant, sa voûte chiffrée |
|
||||
| **hébergeur** | l'`underlay.yml` du site : sa fabric physique |
|
||||
| **modèles** | les offres dont les instances sont tirées |
|
||||
|
||||
Perdre les VM coûte du temps. Perdre ces quatre-là coûte l'écosystème.
|
||||
|
||||
### Le registre des signataires
|
||||
|
||||
`.git-allowed-signers`, **versionné dans le dépôt** :
|
||||
|
||||
```
|
||||
allaire.dan@chezlepro.ca ssh-ed25519 AAAAC3NzaC1lZDI1...
|
||||
```
|
||||
|
||||
Qui clone peut vérifier sans rien demander à la forge. Retirer une ligne **révoque** le
|
||||
signataire pour la suite ; ce qui est déjà signé reste vérifiable — on ne réécrit pas le
|
||||
passé, on cesse d'accepter l'avenir.
|
||||
|
||||
### La parenté, inscrite
|
||||
|
||||
`make genome-inscrire` écrit `parente.yml` dans l'instance : de quel moteur elle descend,
|
||||
à quel **commit**, sous quelle **étiquette signée**.
|
||||
|
||||
```yaml
|
||||
moteur:
|
||||
remote: ssh://…/Set-OPS-Public.git
|
||||
commit: 742bcbf4b0e1322bfa5e0dee14c94bcad6898c53
|
||||
etiquette: v2026.08.21
|
||||
```
|
||||
|
||||
Sans ce fichier, un écosystème fabriqué aujourd'hui ne sait plus, dans un an, d'où il
|
||||
vient. Cinq enfants sans registre font cinq moteurs différents que plus personne ne sait
|
||||
rapprocher. **C'est la mutation sans mémoire, et c'est le seul vrai risque d'une lignée.**
|
||||
|
||||
La preuve **P40** vérifie que la parenté est inscrite, que chaque dépôt nommé se retrouve,
|
||||
que chaque commit inscrit **existe encore** — une histoire réécrite se voit là — et que
|
||||
chacun porte un *remote* : un dépôt qui n'existe qu'ici n'est pas une lignée, c'est un
|
||||
point unique de défaillance.
|
||||
|
||||
---
|
||||
|
||||
## ③ Transférable
|
||||
|
||||
Rien ici n'appartient à Set-OPS :
|
||||
|
||||
- **signature par clé SSH** : git 2.34+, partout, sans infrastructure ;
|
||||
- **`allowed_signers`** : le mécanisme natif d'OpenSSH ;
|
||||
- **journal de transparence** (Certificate Transparency, Sigstore) : la réponse mûre quand
|
||||
plusieurs organisations doivent constater les mêmes faits sans se faire confiance ;
|
||||
- **horodatage RFC 3161** : prouver qu'un document existait à une date.
|
||||
|
||||
Le jour où l'Alliance certifiera des écosystèmes, c'est un **journal de transparence**
|
||||
qu'il faudra — un registre append-only, auditable par un tiers — et non une blockchain.
|
||||
|
||||
---
|
||||
|
||||
## ④ À toi de jouer
|
||||
|
||||
1. `make genome` — quatre dépôts ? Lequel n'a pas de *remote* ? Celui-là n'existe qu'ici.
|
||||
2. `git verify-tag v2026.08.21` — que se passe-t-il si tu retires ta ligne de
|
||||
`.git-allowed-signers` ? (remets-la ensuite)
|
||||
3. `make genome-inscrire`, puis ouvre `parente.yml`. Dans un an, qu'est-ce que ce fichier
|
||||
te dira que ta mémoire ne dira plus ?
|
||||
4. Demande-toi où sont les **témoins** aujourd'hui. Combien de copies vivantes du moteur
|
||||
existent, sur combien de machines distinctes ? C'est la vraie mesure de la résistance de
|
||||
la lignée — pas la longueur des clés.
|
||||
|
||||
**Voir aussi** : [Multi-instance & fédération](Multi-instance-et-fédération),
|
||||
[La preuve](La-preuve), [Sauvegardes](Sauvegardes).
|
||||
382
Glossaire.md
382
Glossaire.md
|
|
@ -1,64 +1,366 @@
|
|||
# Glossaire
|
||||
|
||||
Les concepts-clés de Set-OPS, en une phrase chacun. Les mots *en italique* renvoient à une autre
|
||||
entrée. Le détail vit dans les **unités d'apprentissage** et le dépôt (`docs/`).
|
||||
Tout mot que Set-OPS te met sous les yeux se trouve ici. Chaque entrée dit **ce que c'est**,
|
||||
et pourquoi ce dépôt s'en sert — pas seulement sa définition.
|
||||
|
||||
Les mots *en italique* renvoient à une autre entrée ; les liens mènent à l'**unité
|
||||
d'apprentissage** qui développe la notion.
|
||||
|
||||
> **Règle de ce glossaire.** Un terme employé par le dépôt et absent d'ici est un défaut.
|
||||
> La preuve **P39** le vérifie. Ce qu'elle ne peut pas voir : un mot que personne n'a
|
||||
> pensé à déclarer — elle garde une liste, elle ne devine pas.
|
||||
|
||||
---
|
||||
|
||||
**Adressage dérivé** — Les IP, VLAN, VMID, sous-réseaux ne sont pas saisis : ils se **calculent**
|
||||
depuis le *seed*. Cf. [Le plan & l'adressage dérivé](Le-plan-et-l-adressage-dérivé).
|
||||
## Le plan, et ce qui en dérive
|
||||
|
||||
**Binding (liaison)** — Relation déclarative entre entités du plan (app→app, app→base) résolue par
|
||||
le moteur, sans coder de variables à la main. Cf. [Liaisons (bindings)](Liaisons-bindings).
|
||||
**Plan** — La source unique de vérité (`instance/plan/` : serveurs, applications, bases,
|
||||
domaines, nomenclature). On l'édite ; l'*inventaire* en est **généré**, jamais l'inverse.
|
||||
|
||||
**DIFF VIDE** — État sain où le *plan* reproduit **exactement** l'inventaire généré : la source de
|
||||
vérité et l'artefact concordent. Vérifié par `make instancier`.
|
||||
**Index (seed)** — Le **seul** intrant d'adressage d'une *instance*. Tout en descend :
|
||||
supernet `10.<index>.0.0/16`, *VLAN* `1000+index×10+zone`, *VMID*, *VNet*. Unique dans la
|
||||
*fédération*. Cf. [Le plan & l'adressage dérivé](Le-plan-et-l-adressage-dérivé).
|
||||
|
||||
**Fédération** — Ensemble des *instances* qui cohabitent sur une infrastructure partagée, chacune
|
||||
avec son *index* unique. Cf. [Multi-instance & fédération](Multi-instance-et-fédération).
|
||||
**Adressage dérivé** — Les adresses ne sont pas saisies, elles se **calculent**. Deux
|
||||
valeurs ne peuvent donc pas se contredire : il n'y en a qu'une, et le reste en découle.
|
||||
|
||||
**`federe: false`** — Drapeau marquant un *bac à sable* local, **exclu** du réseau convergé (il ne
|
||||
provisionne pas ses VLAN sur les switches de production).
|
||||
**Nomenclature** — Le registre du modèle réseau : *zones*, placement des fonctions, et
|
||||
l'*index*. Ne contient **aucune** adresse (preuve P20).
|
||||
|
||||
**Hôte fantôme** — Erreur de plan : une application posée sur un hôte **non déclaré** dans les
|
||||
serveurs. Refusé par la preuve **P06** et par la création de modèle.
|
||||
**Zone** — Un domaine de sécurité : un `/24` et un *VLAN*. Frontière, Identité, Données,
|
||||
Services-infra, Observabilité, Applications. Un pare-feu les sépare.
|
||||
|
||||
**Idempotence** — Rejouer la même description N fois donne le même résultat (`changed=0` après la
|
||||
1ʳᵉ fois). Cf. [Infra as Code & idempotence](Infra-as-Code-et-idempotence).
|
||||
**Supernet** — Le grand bloc d'adresses d'un tenant (`10.29.0.0/16`), dont ses *zones*
|
||||
découpent des tranches.
|
||||
|
||||
**Index (seed)** — Le **seul** intrant d'adressage d'une instance. Détermine supernet
|
||||
(`10.(10+index)`), VLAN (`1000+index×10+zone`), VMID. Unique par instance fédérée.
|
||||
**CIDR** — La notation `10.29.16.0/24` : une adresse, puis le nombre de bits **figés**.
|
||||
`/24` fige les trois premiers nombres — 254 machines possibles.
|
||||
|
||||
**Instance** — Un écosystème réel (un *tenant*) : `../OPS-<nom>`, avec ses valeurs concrètes
|
||||
(domaine, *voûte*, index). L'active est celle que pointe le symlink `instance/`.
|
||||
**DIFF VIDE** — État sain : le *plan* reproduit **exactement** l'*inventaire* appliqué.
|
||||
Vérifié par `make instancier`.
|
||||
|
||||
**ip-miroir** — Schéma de VMID à 9 chiffres où le numéro **contient** l'IP et le tenant
|
||||
(`VLAN·octet-hôte·séquence`) — lisible d'un coup d'œil.
|
||||
**Instance** — Un écosystème réel (`../OPS-<nom>`) : son domaine, son *index*, sa *voûte*.
|
||||
L'active est celle que pointe le lien `instance/`.
|
||||
|
||||
**Modèle** — Un *plan* **générique** réutilisable (valeurs *placeholder*, sans *voûte*), dans le
|
||||
dépôt privé `Set-OPS-Modeles`. Le socle public en est la preuve libre. On en crée une instance
|
||||
(`instance-creer`) ; on en fabrique un (`model-creer`).
|
||||
**Tenant** — Le même objet, vu depuis la *fédération* : un écosystème isolé parmi d'autres.
|
||||
|
||||
**Nomenclature** — Le registre du **modèle réseau** : zones, placement des fonctions, et le *seed*
|
||||
`index`. Ne contient **aucun** adressage (il en dérive — preuve P20).
|
||||
**Fédération** — L'ensemble des *instances* qui cohabitent sur une infrastructure
|
||||
partagée, chacune avec son *index*. Cf. [Multi-instance & fédération](Multi-instance-et-fédération).
|
||||
|
||||
**Le plancher** — La première couche de résolution de noms : `/etc/hosts` posé par le socle, avant
|
||||
même que le DNS soit debout. Cf. [DNS & résolution](DNS-et-résolution).
|
||||
**`federe: false`** — Drapeau qui **exclut** une instance des devis du site : ni *VLAN*, ni
|
||||
règles de frontière, ni *VNet* ne lui sont réservés. Pour un bac à sable local, ou pour un
|
||||
écosystème encore à l'état de plan.
|
||||
|
||||
**Plan** — La source unique de vérité (`instance/plan/` : serveurs, applications, bases, domaines,
|
||||
nomenclature). On l'édite ; l'inventaire en est **généré**, jamais l'inverse.
|
||||
**Modèle** — Un *plan* générique réutilisable, sans *voûte*. Le dépôt public en fournit
|
||||
**un** (`exemples/modeles/socle`) ; les modèles assemblés par offre — `forge`, `identite`,
|
||||
`collaboration`… — vivent dans le dépôt privé `Set-OPS-modeles`.
|
||||
|
||||
**Preuve (Pxx)** — Une vérification rejouable du harnais `make prouver` qui garde une classe
|
||||
**Socle** — Le modèle minimal public, **quatre VM** : DNS interne (PowerDNS), PKI
|
||||
(step-ca), edge TLS (nginx) et **magasin courriel** (Dovecot). C'est un magasin de boîtes,
|
||||
pas un relais : le MTA s'ajoute ensuite.
|
||||
|
||||
**Liaison (binding)** — Relation déclarée entre entités du plan (app→base, app→app),
|
||||
résolue par le moteur. Cf. [Liaisons (bindings)](Liaisons-bindings).
|
||||
|
||||
**Hôte fantôme** — Erreur de plan : une application posée sur un hôte non déclaré. Refusée
|
||||
par la preuve P06.
|
||||
|
||||
---
|
||||
|
||||
## Les machines
|
||||
|
||||
**VM** — Machine virtuelle : un ordinateur complet simulé par un *hyperviseur*.
|
||||
|
||||
**Hyperviseur** — La machine physique qui fait tourner les *VM*. Ici : Proxmox.
|
||||
|
||||
**Gabarit (template)** — Une VM **figée** qui sert de moule. Chaque machine de la flotte
|
||||
en est un clone. Le gabarit doré de Set-OPS s'appelle `modeleSetOPS`.
|
||||
|
||||
**Clone** — La copie du *gabarit* qui devient une machine réelle. Deux minutes, contre une
|
||||
installation complète.
|
||||
|
||||
**VMID** — Le numéro d'une VM sur le cluster. Set-OPS le **dérive** (schéma *ip-miroir*) au
|
||||
lieu de le tirer au hasard.
|
||||
|
||||
**ip-miroir** — Schéma où le *VMID* **contient** l'adresse IP et le tenant : le numéro se
|
||||
lit d'un coup d'œil.
|
||||
|
||||
**cloud-init** — Le mécanisme qui configure une VM **à sa toute première seconde** :
|
||||
adresse IP, nom, clé SSH. Sans lui, un clone naîtrait identique à son moule, jumeau de
|
||||
tous les autres.
|
||||
|
||||
**Snapshot** — Photo d'une VM à un instant. Utile pour revenir en arrière ; ce n'est
|
||||
**pas** une sauvegarde (elle vit sur le même stockage).
|
||||
|
||||
**systemd** — Le chef d'orchestre des services d'une machine Linux : il démarre, arrête et
|
||||
surveille. « Un service » veut dire « une unité systemd ».
|
||||
|
||||
---
|
||||
|
||||
## Ansible : décrire au lieu d'exécuter
|
||||
|
||||
**Ansible** — L'outil qui applique une **description** à des machines, par SSH. Cf.
|
||||
[Infra as Code & idempotence](Infra-as-Code-et-idempotence).
|
||||
|
||||
**Playbook** — Un fichier qui dit **quoi appliquer, à qui**. Ici : un par groupe
|
||||
(`playbooks/groupes/<groupe>.yml`).
|
||||
|
||||
**Rôle** — Le paquet qui sait installer et configurer **une** chose (`serveur_nginx`,
|
||||
`client_backup`). C'est l'unité réutilisable.
|
||||
|
||||
**Inventaire** — La liste des machines et de leurs groupes (`hosts.yml`). **Généré** depuis
|
||||
le plan : on ne l'édite jamais à la main.
|
||||
|
||||
**group_vars** — Les valeurs d'un groupe de machines, rangées par fichier. C'est là que
|
||||
vivent les *intrants* non secrets.
|
||||
|
||||
**Handler** — Une action qui ne se déclenche **que si** quelque chose a changé — typiquement
|
||||
recharger un service quand sa configuration a bougé.
|
||||
|
||||
**Idempotence** — Rejouer la même description dix fois donne le même résultat. La deuxième
|
||||
exécution ne change rien (`changed=0`). C'est ce qui rend une reconstruction sûre.
|
||||
|
||||
**Voûte (vault)** — Le fichier **chiffré** des secrets d'une instance. Jamais dans un
|
||||
modèle, jamais en clair. Seul le gabarit `vault.yml.example` — des **noms**, pas des
|
||||
valeurs — est versionné.
|
||||
|
||||
---
|
||||
|
||||
## Le réseau
|
||||
|
||||
→ Unité complète : [Le réseau des tenants](Le-réseau-des-tenants)
|
||||
|
||||
**Underlay** — Le réseau **physique** : câbles, commutateurs, adresses des hyperviseurs. Il
|
||||
ne connaît aucun tenant.
|
||||
|
||||
**Overlay** — Les réseaux **virtuels** des tenants, transportés par-dessus l'*underlay*.
|
||||
|
||||
**VLAN** — Une étiquette posée sur chaque trame pour séparer des réseaux qui partagent un
|
||||
câble. Limite : 4094 étiquettes, et chaque commutateur doit les connaître.
|
||||
|
||||
**VXLAN** — L'encapsulation : la trame d'un tenant voyage **dans une enveloppe**. Le réseau
|
||||
physique ne voit que des colis. L'enveloppe coûte **50 octets** — d'où le *MTU* 1450.
|
||||
|
||||
**EVPN** — Le mécanisme par lequel les hyperviseurs s'annoncent les machines qu'ils
|
||||
hébergent. Sans lui, la table des destinations serait tenue à la main.
|
||||
|
||||
**SDN** — *Software-Defined Networking* : le réseau se **décrit** et se pose par API, au
|
||||
lieu de se câbler à la main.
|
||||
|
||||
**VNet** — Le réseau virtuel d'**une zone** d'un tenant (`t29fron`) : le point où la carte
|
||||
d'une VM se branche.
|
||||
|
||||
**VRF** — Une table de routage **étanche**. Dans celle du tenant A, les réseaux du tenant B
|
||||
n'existent pas. Ce n'est pas une interdiction, c'est une ignorance.
|
||||
|
||||
**Strophe (FRR)** — Le bloc de configuration qu'on pose par tenant dans
|
||||
`/etc/frr/frr.conf.local`, sur chaque hyperviseur : sa **sortie** et son **puits**.
|
||||
|
||||
**FRR** — Le démon de routage des hyperviseurs (*FRRouting*).
|
||||
|
||||
**`nexthop-vrf`** — Emprunter **une seule** adresse à une autre table de routage, au lieu
|
||||
d'importer celle-ci en entier. La différence entre une porte et un mur abattu.
|
||||
|
||||
**Blackhole (puits)** — Une route qui **absorbe** le trafic vers les adresses non
|
||||
attribuées d'un tenant, pour qu'il ne parte pas errer ailleurs.
|
||||
|
||||
**MTU** — La plus grosse trame qu'un lien accepte. 1500 par défaut ; 1450 dans l'*overlay*
|
||||
(l'enveloppe VXLAN prend 50). Se tromper suspend les grosses réponses sans casser les
|
||||
petites — la panne la plus déroutante du domaine.
|
||||
|
||||
**SVI** — L'adresse de passerelle portée par un **commutateur** pour un VLAN. Set-OPS ne
|
||||
s'en sert plus : le routage des tenants vit sur l'hyperviseur (*VRF*).
|
||||
|
||||
**Pont (bridge)** — Le commutateur **virtuel** d'un hyperviseur (`vmbr1`). Les VM de la
|
||||
flotte se branchent sur leur *VNet*, pas sur un pont nu.
|
||||
|
||||
**IPAM** — Le registre qui attribue les adresses. Ici, c'est la **dérivation** : personne
|
||||
ne tient de liste.
|
||||
|
||||
**Spanning-tree (STP)** — Le protocole qui empêche une boucle de commutateurs de saturer le
|
||||
réseau. Il élit une racine ; c'est ce que désigne `routeur` dans l'*underlay*.
|
||||
|
||||
**MLAG** — Deux commutateurs qui se font passer pour un seul. Set-OPS n'en a pas — d'où
|
||||
les chemins doublés ailleurs (MPIO côté stockage, `active-backup` côté flotte). *(Cette
|
||||
entrée concluait « d'où un seul commutateur qui route » : plus aucun ne route. Le routage
|
||||
des tenants vit sur l'hyperviseur, cf. l'entrée* SVI *ci-dessus.)*
|
||||
|
||||
**nftables** — Le pare-feu **de chaque machine** Linux. Set-OPS le dérive du registre des
|
||||
flux.
|
||||
|
||||
**Policy drop** — Politique par défaut : *tout ce qui n'est pas autorisé est refusé*. Sans
|
||||
règles chargées, elle mure la machine — d'où l'importance de `make flux`.
|
||||
|
||||
**Frontière** — Le pare-feu de bordure (OPNsense), entre l'écosystème et l'extérieur. Hors
|
||||
flotte Ansible : piloté par API.
|
||||
|
||||
**FQDN** — Le nom complet d'une machine, `forge.genese.internal` — pas seulement `forge`.
|
||||
|
||||
---
|
||||
|
||||
## Les noms
|
||||
|
||||
→ Unité complète : [DNS & résolution](DNS-et-résolution)
|
||||
|
||||
**DNS** — L'annuaire qui traduit un nom en adresse.
|
||||
|
||||
**Le plancher** — La première couche de résolution : `/etc/hosts`, posé par le socle
|
||||
**avant** que le DNS existe. Sans lui, rien ne peut s'amorcer.
|
||||
|
||||
**Résolveur** — Le service qui pose les questions au DNS pour une machine (ici Unbound,
|
||||
local à chaque hôte).
|
||||
|
||||
**Reverse proxy** — Le portier : il reçoit toutes les requêtes web et les distribue au bon
|
||||
service derrière. Cf. [Reverse-proxy & TLS](Reverse-proxy-et-TLS).
|
||||
|
||||
**vhost** — La configuration d'**un site** dans le *reverse proxy* : quel nom, vers quel
|
||||
service.
|
||||
|
||||
**WAF** — Filtre qui inspecte les requêtes web et bloque les attaques connues.
|
||||
|
||||
**Edge** — La machine de bordure qui publie les services web (ici nginx).
|
||||
|
||||
---
|
||||
|
||||
## La confiance
|
||||
|
||||
→ Unité complète : [PKI & confiance](PKI-et-confiance)
|
||||
|
||||
**PKI** — L'ensemble qui fabrique et gère les certificats.
|
||||
|
||||
**CA (autorité de certification)** — Celle qui **signe** les certificats. Ici, `step-ca`,
|
||||
interne : l'écosystème est sa propre autorité.
|
||||
|
||||
**Certificat** — Une pièce d'identité pour une machine : ce nom, cette clé, signé par la
|
||||
*CA*.
|
||||
|
||||
**ACME** — Le protocole qui **automatise** la demande et le renouvellement d'un certificat.
|
||||
Personne ne le fait à la main.
|
||||
|
||||
**SAN** — Les noms qu'un certificat couvre. Set-OPS les **dérive** du plan.
|
||||
|
||||
**TLS** — Le chiffrement d'une connexion (le « s » de https).
|
||||
|
||||
**mTLS** — TLS **des deux côtés** : le client prouve aussi son identité. C'est le
|
||||
zéro-confiance entre serveurs.
|
||||
|
||||
---
|
||||
|
||||
## L'identité
|
||||
|
||||
→ Unité complète : [Identité & SSO](Identité-et-SSO)
|
||||
|
||||
**LDAP** — L'annuaire des personnes et des groupes : la source de vérité des identités.
|
||||
|
||||
**LDAPS** — LDAP chiffré.
|
||||
|
||||
**SSO** — *Single Sign-On* : une seule authentification pour toutes les applications.
|
||||
|
||||
**OIDC** — Le protocole moderne du *SSO* sur le web. C'est lui derrière « Se connecter
|
||||
avec… ».
|
||||
|
||||
**SAML** — L'ancêtre d'*OIDC*, encore répandu en entreprise.
|
||||
|
||||
**Realm** — Le « royaume » d'un serveur d'identité : un espace de comptes, de groupes et de
|
||||
règles. Un par écosystème.
|
||||
|
||||
**RBAC** — Donner des droits à des **rôles**, pas à des personnes. Cf.
|
||||
[Autorisation & RBAC](Autorisation-et-RBAC).
|
||||
|
||||
---
|
||||
|
||||
## Le courriel
|
||||
|
||||
→ Unité complète : [Courriel (SMTP/IMAP)](Courriel)
|
||||
|
||||
**SMTP** — Le protocole qui **transporte** un courriel d'un serveur à l'autre.
|
||||
|
||||
**MTA** — Le serveur qui fait ce transport (ici Postfix).
|
||||
|
||||
**IMAP** — Le protocole par lequel **tu lis** ta boîte, depuis ton téléphone ou ton client.
|
||||
|
||||
**LMTP** — Le dernier mètre : le MTA remet le message au serveur qui **détient** les boîtes
|
||||
(ici Dovecot).
|
||||
|
||||
**DKIM** — La signature qui prouve qu'un courriel vient bien de ton domaine.
|
||||
|
||||
---
|
||||
|
||||
## L'état, et sa preuve
|
||||
|
||||
**SQLite** — Une base de données qui tient dans **un fichier**, sans serveur ni compte.
|
||||
Suffisante pour une petite forge — c'est ce que portait patient 0, dont les machines
|
||||
n'existent plus. À l'inverse de
|
||||
*PostgreSQL*, qui est un service à part entière — un serveur, une zone, un secret.
|
||||
|
||||
**restic** — L'outil de sauvegarde chiffrée et dédupliquée. Cf. [Sauvegardes](Sauvegardes).
|
||||
|
||||
**Sauvegarde vs snapshot** — L'infrastructure se **reconstruit** depuis le code ; seul
|
||||
l'**état** (annuaire, bases, courriel, forge) se sauvegarde. Cf. [Sauvegardes](Sauvegardes).
|
||||
|
||||
**Devis** — Une commande qui **interroge le système réel** et montre l'écart avec le plan,
|
||||
sans rien écrire (`make sdn-plan`, `make placement-plan`).
|
||||
|
||||
**Preuve (Pxx)** — Une vérification rejouable de `make prouver` qui garde une classe
|
||||
d'erreur. Cf. [La preuve](La-preuve).
|
||||
|
||||
**Socle** — L'infrastructure de base souveraine (DNS, PKI, edge TLS, relais courriel) — le modèle
|
||||
minimal public, extensible.
|
||||
**Source unique** — Le principe qui traverse tout le dépôt : une information vit à **un**
|
||||
endroit, et tout le reste en dérive. Neuf copies d'une même règle ne vieillissent pas
|
||||
ensemble — et la divergence ne se voit jamais de l'intérieur d'une copie.
|
||||
|
||||
**Tenant** — Synonyme d'*instance* dans le contexte de la *fédération* : un écosystème isolé parmi
|
||||
d'autres.
|
||||
**Résolution d'instance** — Comment un script sait **quel écosystème** il regarde : la
|
||||
variable `SETOPS_INSTANCE`, sinon le lien `instance`. Une seule fonction y répond pour tout
|
||||
le moteur (`inventory_rules.instance_courante`) ; la preuve P41 refuse qu'on en réécrive
|
||||
une deuxième.
|
||||
|
||||
**Voûte (vault)** — Le fichier chiffré des secrets d'une instance (`vault.yml`, Ansible Vault).
|
||||
**Jamais** dans un *modèle* ni versionné ; seul le gabarit `vault.yml.example` l'est.
|
||||
**Harnais** — L'ensemble des preuves. Un `make prouver` vert veut dire : aucune des classes
|
||||
d'erreur connues n'est présente.
|
||||
|
||||
**Zone** — Un domaine de sécurité (un `/24` + un VLAN) : Frontière, Identité, Données,
|
||||
Services-infra, Observabilité, Applications. Un pare-feu les sépare.
|
||||
**Chèque vert sur un périmètre vide** — Le piège central de ce dépôt : une vérification qui
|
||||
réussit **sans rien avoir mesuré**. Une sauvegarde de zéro fichier, un devis qui lit un
|
||||
intrant périmé, une preuve qui ne peut pas échouer. À chaque « ✅ », se demander **sur
|
||||
quoi** il a porté.
|
||||
|
||||
**GUI** — La console web d'exploitation (`make inventaire-ui`). Cf.
|
||||
[Le GUI](Le-GUI-console-d-exploitation).
|
||||
|
||||
**CI** — La vérification automatique à chaque poussée (`make ci` la rejoue à l'identique).
|
||||
|
||||
---
|
||||
|
||||
## La filiation
|
||||
|
||||
→ Unité complète : [Filiation, signatures & témoins](Filiation-signatures-et-témoins)
|
||||
|
||||
**Génome** — Les **quatre dépôts** sans lesquels un écosystème ne peut pas être refabriqué :
|
||||
le *moteur*, l'*instance*, le dépôt de l'hébergeur, les *modèles*. `make genome` les nomme.
|
||||
|
||||
**Parenté** — Le fichier `parente.yml` d'une instance : de quel moteur elle descend, à quel
|
||||
*commit*, sous quelle *étiquette signée*. Sans lui, un écosystème ne sait plus d'où il vient.
|
||||
|
||||
**Commit** — Un instantané du dépôt, qui porte l'**empreinte** du précédent. Modifier le
|
||||
passé change toutes les empreintes suivantes : c'est ce qui rend une histoire vérifiable.
|
||||
|
||||
**Empreinte (hachage)** — Une courte signature calculée d'un contenu. Deux contenus
|
||||
différents n'ont pas la même — c'est ce qui permet de détecter une modification.
|
||||
|
||||
**Arbre de Merkle** — La structure où chaque élément porte l'empreinte du précédent. Git en
|
||||
est un ; une blockchain aussi. L'intégrité vient de là, pas d'une chaîne de blocs.
|
||||
|
||||
**Étiquette (tag)** — Un nom posé sur un état précis du dépôt (`v2026.08.21`). Signée, elle
|
||||
devient un point de repère **vérifiable** : « c'est de cet état-là que je descends ».
|
||||
|
||||
**Signature** — Le scellé posé avec une clé privée. Qui a la clé **publique** peut vérifier ;
|
||||
qui n'a pas la privée ne peut pas contrefaire. Sans elle, un nom d'auteur est déclaratif.
|
||||
|
||||
**`.git-allowed-signers`** — Le registre, **versionné**, des clés autorisées à signer cette
|
||||
lignée. Retirer une ligne révoque pour la suite ; le passé signé reste vérifiable.
|
||||
|
||||
**Témoin** — Une copie vivante et indépendante du *génome*. Réécrire l'histoire suppose de
|
||||
convaincre tous les témoins : c'est la lignée elle-même qui protège la lignée.
|
||||
|
||||
**Journal de transparence** — Un registre append-only, auditable par un tiers (Certificate
|
||||
Transparency, Sigstore). La réponse mûre quand plusieurs organisations doivent constater les
|
||||
mêmes faits sans se faire confiance — et l'alternative sobre à une blockchain.
|
||||
|
||||
**Horodatage (RFC 3161)** — Prouver qu'un document **existait** à une date, par un tiers.
|
||||
|
|
|
|||
2
Home.md
2
Home.md
|
|
@ -24,7 +24,7 @@ des **méthodes 100 % génériques**.
|
|||
| Section | Contenu |
|
||||
|---|---|
|
||||
| **Unités d'apprentissage** | Un fondamental TIC par page, toujours selon le même moule (ci-dessous). Des *services* (identité, PKI, courriel…) **et** de la *méthode* (le plan, le multi-instance, la preuve). |
|
||||
| **Opérations (runbooks)** | Procédures : ajouter un service, déployer un nœud, restaurer une sauvegarde… |
|
||||
| **Opérations (runbooks)** | Les procédures ne vivent **pas** ici : elles sont dans le dépôt, `docs/runbooks-exploitation.md`. Le wiki y pointe (même règle que la référence technique, ci-dessous). |
|
||||
| **[Glossaire](Glossaire)** | Les concepts-clés en une phrase (seed, bindings, le plancher, hôte fantôme, voûte…). |
|
||||
| **Référence technique** | Le *détail du « comment »* vit **dans le dépôt** (`docs/`, README des rôles) — ce wiki y **pointe**, ne le **recopie pas** (pour éviter la dérive). |
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ Trois pièces, un rôle chacun :
|
|||
| Pièce | Rôle | Concept incarné |
|
||||
|---|---|---|
|
||||
| **OpenLDAP** (`serveur_openldap`) | l'**annuaire** — la source de vérité. `testmail` y vit. | annuaire |
|
||||
| **Keycloak** (`serveur_keycloak`) | le **fournisseur d'identité** (IdP) SSO. Il **fédère** OpenLDAP (lit les comptes en LDAP, lecture seule). | SSO, OIDC, fédération |
|
||||
| **Keycloak** (`serveur_keycloak`) | le **fournisseur d'identité** (IdP) SSO. Il **fédère** OpenLDAP en mode **`WRITABLE`** : il écrit *à travers*, vers l'annuaire. | SSO, OIDC, fédération |
|
||||
| **oauth2-proxy** (`serveur_oauth2_proxy`) | une **passerelle** OIDC pour les apps **sans** OIDC natif. | motif *proxy d'authentification* |
|
||||
|
||||
Les applications se branchent de deux façons :
|
||||
|
|
@ -52,6 +52,16 @@ Grafana ──> crée la session : "tu es testmail" ✔
|
|||
Résultat : **une identité** (`testmail`, un seul mot de passe LDAP) ouvre **le courriel, Grafana,
|
||||
Forgejo et Icinga**. Change le mot de passe une fois, il change partout.
|
||||
|
||||
> **Pourquoi `WRITABLE` et pas « lecture seule ».** Cette unité a écrit « lecture seule »
|
||||
> jusqu'au 2026-09-06 ; ce serait plus prudent en apparence, et c'est un cul-de-sac. En
|
||||
> `READ_ONLY`, un changement de mot de passe échoue sur *« Federated storage is not
|
||||
> writable »* — or l'annuaire *exige* ce changement à la première connexion : la reprise du
|
||||
> sysadmin butait dessus (constaté le 2026-08-07). Et `UNSYNCED` serait pire : Keycloak
|
||||
> écrirait dans **sa** base, Dovecot et Postfix continueraient de valider l'ancien depuis
|
||||
> LDAP — une identité, deux mots de passe, exactement ce que la doctrine interdit.
|
||||
> `WRITABLE` écrit *à travers* : l'annuaire reste la source unique, Keycloak n'en est qu'un
|
||||
> client.
|
||||
|
||||
---
|
||||
|
||||
## ③ Pourquoi c'est transférable
|
||||
|
|
@ -74,14 +84,14 @@ Change les produits, le **schéma reste**. C'est ça, un savoir générique.
|
|||
|
||||
> Prérequis : accès au lab (VPN), `/etc/hosts` pointant les services sur l'edge.
|
||||
|
||||
1. **Vis le SSO.** Ouvre `https://grafana.lab.chezlepro.internal` → « *Se connecter avec
|
||||
1. **Vis le SSO.** Ouvre `https://grafana.chezlepro.internal` → « *Se connecter avec
|
||||
Chezlepro* » → `testmail`. Puis ouvre Forgejo, puis Icinga : **tu n'es reconnecté nulle part**.
|
||||
2. **Observe le flux.** Rouvre Grafana en navigation privée, ouvre les outils dév (F12 → Réseau) :
|
||||
repère la **redirection vers Keycloak**, puis le **retour avec un `code=`**. C'est ① en action.
|
||||
3. **Interroge l'annuaire (la source de vérité).** Sur un nœud avec `ldap-utils` :
|
||||
```bash
|
||||
ldapsearch -x -H ldaps://id-ldap-01.lab.chezlepro.internal \
|
||||
-b ou=people,dc=lab,dc=chezlepro,dc=internal '(uid=testmail)'
|
||||
ldapsearch -x -H ldaps://idm-01.chezlepro.internal \
|
||||
-b ou=people,dc=chezlepro,dc=internal '(uid=testmail)'
|
||||
```
|
||||
Tu vois l'entrée que Keycloak **fédère** — il ne l'a pas recopiée.
|
||||
4. **Casse & répare (la fédération).** Dans la console admin Keycloak → *User Federation* →
|
||||
|
|
|
|||
47
La-preuve.md
47
La-preuve.md
|
|
@ -26,7 +26,7 @@ Trois idées la portent :
|
|||
|
||||
- **Le registre** : `docs/audit/affirmations.md` — chaque affirmation du dépôt (README, docs,
|
||||
aide `make`, GUI) reliée à une preuve et un statut (✅/🟡/❌/⚪).
|
||||
- **Le harnais** : `make prouver` rejoue les preuves automatisables (**P01–P34**) et écrit
|
||||
- **Le harnais** : `make prouver` rejoue les preuves automatisables (**P01–P60**, sans trou dans la série) et écrit
|
||||
`docs/audit/preuve-<date>.md`. `make verifier` les inclut : il **échoue** si une preuve échoue.
|
||||
- **Chaque preuve garde une classe d'erreur.** Extrait :
|
||||
|
||||
|
|
@ -42,6 +42,7 @@ Trois idées la portent :
|
|||
| P31 | une capacité du dépôt **non expliquée** (script muet, cible sans aide, rôle sans README) |
|
||||
| P32 | un intrant qu'un rôle **exige** et que l'instance ne fournit pas |
|
||||
| P33 | deux rôles co-localisés qui **revendiquent le même port** |
|
||||
| P35 | une application dont le rôle **exige une base** sans entrée au plan — sinon l'écart n'apparaît qu'après quarante minutes de déploiement |
|
||||
| P34 | un document qui ne **déclare pas son lecteur** — il finirait rangé par sujet, donc introuvable |
|
||||
|
||||
> **Ce que ces preuves ne font pas, et il faut le savoir avant de leur faire confiance.** Elles
|
||||
|
|
@ -86,6 +87,50 @@ harnais de Set-OPS ».
|
|||
|
||||
---
|
||||
|
||||
## Le défaut le plus dangereux n'est pas l'erreur, c'est la **copie**
|
||||
|
||||
Set-OPS pilote plusieurs écosystèmes. Avant d'agir, chaque script doit donc savoir
|
||||
**lequel il regarde** — par le lien `instance`, ou par la variable `SETOPS_INSTANCE`.
|
||||
|
||||
En août 2026, **neuf scripts avaient chacun écrit leur propre réponse** à cette question.
|
||||
Trois lignes chacun. Aucune n'était fausse en soi.
|
||||
|
||||
Le problème n'est pas l'erreur : c'est que **neuf copies ne vieillissent pas ensemble**.
|
||||
Quand on améliore l'une, les huit autres ne le savent pas. Et personne ne peut le voir,
|
||||
parce que de l'intérieur d'un fichier, la copie locale a toujours l'air correcte.
|
||||
|
||||
### Ce que ça donnait
|
||||
|
||||
`make placement-plan` visait patient 0 et répondait :
|
||||
|
||||
```
|
||||
Devis du placement — tenant « instance »
|
||||
noeud asgard · stockage TrueNAS · gabarit 99998 → CONFORME
|
||||
```
|
||||
|
||||
C'était vrai — **sur l'autre écosystème**. Sa copie lisait le lien au lieu de la variable.
|
||||
Comme les deux tenants portaient les mêmes valeurs de placement, le verdict semblait
|
||||
juste. C'est très exactement la circonstance où une erreur ne se voit pas.
|
||||
|
||||
Cinq défauts de cette famille sont sortis en cinq jours. Tous dans des outils qui
|
||||
**constatent** — preuves et devis — jamais dans ceux qui agissent. C'est moins grave et
|
||||
plus insidieux : un outil qui agit mal, on le voit ; un outil qui mesure mal dit
|
||||
« conforme », et on passe à la suite.
|
||||
|
||||
### La réponse
|
||||
|
||||
Une **source unique** : une fonction, dans un fichier, que tous appellent. Si elle est
|
||||
fausse, elle l'est partout d'un coup — donc visible, donc corrigée une fois.
|
||||
|
||||
Et une preuve, **P41**, qui refuse la prochaine copie. Elle en a trouvé une dixième le
|
||||
jour de son écriture, dans le fichier des preuves lui-même.
|
||||
|
||||
> **C'est la même leçon que `proxmox-hebergeur.yml`** : les nœuds et stockages du cluster
|
||||
> recopiés chez chaque tenant avaient divergé. Une source, pas N copies — pour les données
|
||||
> comme pour le code.
|
||||
|
||||
---
|
||||
|
||||
## Pour aller plus loin *(dépôt)*
|
||||
- Le mode d'emploi : `docs/audit/README.md`.
|
||||
- Le registre : `docs/audit/affirmations.md` ; le harnais : `scripts/prouver.py`.
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ Le **plan** (`instance/plan/`) est la source unique. Cinq registres :
|
|||
|
||||
| Élément | Formule (modèle 6 zones) |
|
||||
|---|---|
|
||||
| Supernet | `10.(10+index).0.0/16` |
|
||||
| Sous-réseau de zone | `10.(10+index).(15+zone).0/24` |
|
||||
| Supernet | `10.<index>.0.0/16` |
|
||||
| Sous-réseau de zone | `10.<index>.(15+zone).0/24` |
|
||||
| Passerelle | `…(15+zone).1` |
|
||||
| VLAN sur le trunk | `1000 + index×10 + zone` |
|
||||
| VMID | `VLAN·octet-hôte·séquence` (9 chiffres) |
|
||||
|
|
|
|||
165
Le-réseau-des-tenants.md
Normal file
165
Le-réseau-des-tenants.md
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
# Le réseau des tenants — du câble au VRF
|
||||
|
||||
> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer.
|
||||
|
||||
C'est la partie de Set-OPS qui emploie le plus de mots obscurs — *underlay*, *VXLAN*,
|
||||
*VNet*, *VRF*, *strophe FRR*. Aucun n'est là par goût du jargon : chacun répond à un
|
||||
problème précis, et on peut les rencontrer dans l'ordre où ils sont apparus.
|
||||
|
||||
---
|
||||
|
||||
## ① Le concept
|
||||
|
||||
### Le problème de départ : deux clients sur le même fil
|
||||
|
||||
Deux organisations hébergées sur le même matériel ne doivent pas se voir. Or leurs
|
||||
machines partagent des câbles, des commutateurs, des hyperviseurs. Il faut donc
|
||||
**séparer ce qui est physiquement mélangé**.
|
||||
|
||||
### Première réponse : le VLAN
|
||||
|
||||
Un **VLAN** colle une étiquette (un nombre) sur chaque trame. Deux machines n'échangent
|
||||
que si leurs étiquettes correspondent. C'est simple, ça marche, et c'est vieux de trente
|
||||
ans.
|
||||
|
||||
Deux limites :
|
||||
|
||||
- l'étiquette tient sur 12 bits — **4094 VLAN**, pas un de plus ;
|
||||
- chaque commutateur du chemin doit connaître chaque VLAN. Ajouter un client, c'est
|
||||
toucher à la configuration de tout le monde.
|
||||
|
||||
### Deuxième réponse : l'encapsulation
|
||||
|
||||
**VXLAN** prend la trame d'un tenant, la met **dans une enveloppe** et l'expédie comme
|
||||
un colis ordinaire d'un hyperviseur à l'autre. Le réseau physique ne voit passer que des
|
||||
colis — il n'a plus besoin de connaître les clients.
|
||||
|
||||
Deux vocabulaires en découlent, et c'est la distinction la plus utile de cette page :
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **underlay** | le réseau **physique** : les câbles, les commutateurs, les adresses des hyperviseurs. Il ne connaît aucun tenant. |
|
||||
| **overlay** | les réseaux **virtuels** des tenants, transportés dans des enveloppes par-dessus l'underlay. |
|
||||
|
||||
L'enveloppe coûte **50 octets**. C'est toute l'explication du `mtu_overlay: 1450` :
|
||||
1450 + 50 = 1500, la taille standard d'une trame. Se tromper là ne casse rien
|
||||
franchement — les petites requêtes passent, les grosses réponses restent suspendues.
|
||||
C'est la panne la plus déroutante du domaine.
|
||||
|
||||
### Qui distribue les enveloppes : EVPN
|
||||
|
||||
Pour expédier un colis, il faut savoir **où** l'envoyer. **EVPN** est le mécanisme par
|
||||
lequel les hyperviseurs s'annoncent mutuellement les machines qu'ils hébergent. Sans
|
||||
lui, il faudrait tenir cette table à la main.
|
||||
|
||||
### Le VRF : une table de routage étanche
|
||||
|
||||
Un routeur ordinaire a **une** table de routage. Un **VRF** lui en donne plusieurs,
|
||||
hermétiques : dans la table du tenant A, les réseaux du tenant B **n'existent pas**. Ce
|
||||
n'est pas une règle de pare-feu qu'on pourrait oublier — c'est une ignorance
|
||||
structurelle.
|
||||
|
||||
C'est la différence entre *« je t'interdis d'y aller »* et *« la route n'existe pas »*.
|
||||
|
||||
---
|
||||
|
||||
## ② Dans Set-OPS
|
||||
|
||||
### Ce que tu écris, et ce qui se calcule
|
||||
|
||||
Tu écris **un nombre** : `index`. Tout le reste en découle.
|
||||
|
||||
```
|
||||
index: 29
|
||||
↓
|
||||
supernet 10.29.0.0/16
|
||||
VLAN 1000 + 29×10 + zone → 1291, 1292, 1293…
|
||||
zone SDN t29
|
||||
VNet t29fron, t29serv, t29donn, t29appl
|
||||
sous-réseau 10.29.16.0/24, 10.29.17.0/24 …
|
||||
```
|
||||
|
||||
Un **VNet** est le réseau virtuel d'**une zone** d'un tenant : le point où les cartes
|
||||
réseau des VM se branchent. Une VM de la zone Frontière du tenant 29 se branche sur
|
||||
`t29fron`, et nulle part ailleurs.
|
||||
|
||||
### Trois commandes, trois questions
|
||||
|
||||
| Commande | Question à laquelle elle répond |
|
||||
|---|---|
|
||||
| `make underlay` | mon réseau **physique** est-il cohérent, et n'empiète-t-il pas sur les tenants ? |
|
||||
| `make sdn-plan` | ce que le cluster porte **diffère-t-il** de ce que le plan décrit ? (aucune écriture) |
|
||||
| `make sdn-appliquer` | pose la différence — et **retire ce qui est périmé** |
|
||||
|
||||
`sdn-plan` avant `sdn-appliquer`, toujours. La seconde écrit sur le cluster et sur les
|
||||
hyperviseurs ; la première ne fait que regarder.
|
||||
|
||||
### La strophe FRR
|
||||
|
||||
**FRR** est le démon de routage des hyperviseurs. Set-OPS lui pose un bloc par tenant —
|
||||
ce que le dépôt appelle une **strophe** — dans `/etc/frr/frr.conf.local`, sur chaque
|
||||
nœud de sortie :
|
||||
|
||||
```
|
||||
vrf vrf_t29
|
||||
ip route 0.0.0.0/0 10.0.4.1 nexthop-vrf default
|
||||
ip route 10.29.0.0/16 blackhole
|
||||
exit-vrf
|
||||
```
|
||||
|
||||
**La première ligne, c'est la sortie.** Tout ce qui ne concerne pas le tenant part vers
|
||||
la frontière. `nexthop-vrf default` **emprunte une seule adresse** à la table principale
|
||||
au lieu de l'importer en entier : importer aurait fait entrer dans le VRF le transport
|
||||
VXLAN, le plan de gestion et les VLAN hérités — et permis de contourner la frontière.
|
||||
|
||||
**La deuxième ligne, c'est un puits.** Elle attrape les adresses **non attribuées** du
|
||||
tenant. Elle est moins précise que les `/24` des VNets, donc le trafic légitime ne la
|
||||
voit jamais.
|
||||
|
||||
Sans ce puits (mesuré le 2026-08-09) : une adresse inexistante ne trouvait aucune route
|
||||
locale, sortait par le défaut, revenait de la frontière vers l'hyperviseur, atterrissait
|
||||
dans la table **principale** — et repartait vers la passerelle du réseau
|
||||
d'**administration**. Deux conséquences : le trafic d'un tenant pouvait atteindre le
|
||||
plan de gestion **par une faute de frappe**, et `connect()` réussissait vers n'importe
|
||||
quelle adresse inexistante. Ce qu'on avait longtemps pris pour une protection de la
|
||||
frontière n'était qu'une route manquante ici.
|
||||
|
||||
> **Le fichier ne se sauvegarde pas : il se régénère.** Il porte son avertissement en
|
||||
> tête — *« NE PAS ÉDITER À LA MAIN »*. La source de vérité est le plan.
|
||||
|
||||
---
|
||||
|
||||
## ③ Transférable
|
||||
|
||||
Rien de tout ça n'appartient à Set-OPS. Ce sont les briques de n'importe quel réseau
|
||||
multi-locataire :
|
||||
|
||||
- **underlay / overlay** : le vocabulaire de tous les centres de données depuis 2015 ;
|
||||
- **VXLAN + EVPN** : la même paire chez tous les hébergeurs, du garage à AWS ;
|
||||
- **VRF** : présent sur tout routeur professionnel, et sur Linux depuis 2016 ;
|
||||
- **le puits (`blackhole`)** : une pratique standard d'anti-fuite.
|
||||
|
||||
Ce que Set-OPS ajoute n'est pas de la technologie, c'est une **dérivation** : ailleurs,
|
||||
ces objets se saisissent à la main, un par un, dans quatre interfaces différentes. Ici,
|
||||
ils descendent tous d'un seul nombre — donc ils ne peuvent pas se contredire.
|
||||
|
||||
---
|
||||
|
||||
## ④ À toi de jouer
|
||||
|
||||
1. **Lis ton réseau physique** : `make underlay`. Repère les VLAN sous 1000 (l'underlay)
|
||||
et les MTU. Pourquoi le transport doit-il être à 1500 quand l'overlay est à 1450 ?
|
||||
2. **Regarde sans écrire** : `make sdn-plan`. Si le cluster dit déjà ce que le plan dit,
|
||||
la sortie tient en une ligne.
|
||||
3. **Trouve la sortie d'un tenant** : dans `make devis-sdn`, repère la strophe FRR et
|
||||
l'adresse du prochain saut. À quel équipement appartient-elle ?
|
||||
4. **Change `index` dans un modèle** (jamais en production) et régénère : combien de
|
||||
valeurs ont bougé ? C'est la mesure exacte de ce que la dérivation t'épargne.
|
||||
|
||||
**Pour aller plus loin** : `docs/sdn-evpn.md` dans le dépôt (référence technique),
|
||||
[Le plan & l'adressage dérivé](Le-plan-et-l-adressage-dérivé),
|
||||
[Multi-instance & fédération](Multi-instance-et-fédération).
|
||||
|
||||
> *Le lien vers `docs/` était relatif (`../docs/…`) : il fonctionne dans le dépôt et
|
||||
> **casse une fois le wiki publié**, la forge ne recevant que le contenu de `wiki/`. C'est
|
||||
> pourquoi le corpus cite `docs/` en **texte**, jamais en lien — une seule page dérogeait.*
|
||||
|
|
@ -38,8 +38,16 @@ Les **résolveurs partagés** font le pont : `resoudre_base` (app→base) et `re
|
|||
**dans le rôle**, jamais en clair.
|
||||
|
||||
La **modalité** structure la robustesse : une liaison **requise** absente → le moteur **refuse
|
||||
d'instancier** (ex. une base sans serveur SQL). Une **optionnelle** absente → silence (ex. un nœud
|
||||
sans `client_journal` marche très bien).
|
||||
d'instancier** (ex. une base sans serveur SQL). Une **optionnelle** absente → silence (ex. un
|
||||
nœud sans `client_backup` : il ne détient pas d'état, il n'a rien à sauvegarder).
|
||||
|
||||
> **Attention à une troisième catégorie, qui n'est ni l'une ni l'autre : l'universelle.**
|
||||
> `client_pki`, `client_metrique`, `client_journal`, `client_resolveur` et
|
||||
> `client_artefacts` ne se déclarent **pas** — tout hôte les reçoit par dérivation, et
|
||||
> **P26** refuse qu'un hôte y échappe. Cette unité citait `client_journal` en exemple
|
||||
> d'optionnelle jusqu'au 2026-09-06 : c'est l'inverse. Le plan portait 28 lignes qui
|
||||
> disaient « oui » à quelque chose de vrai pour tous ; elles n'existaient que pour être
|
||||
> oubliées, et quatre l'avaient été.
|
||||
|
||||
C'est **le** concept de Set-OPS : *tu déclares les liaisons, le moteur câble.*
|
||||
|
||||
|
|
@ -64,9 +72,11 @@ produit. C'est un **modèle mental** qui vaut de NetScaler à Kubernetes.
|
|||
*app→domaine*), et `serveurs.yml` : un nœud avec `integrations:` (liaison *nœud→service*).
|
||||
2. **Vois-la se résoudre.** Après `make instancier`, regarde l'inventaire généré : la cible est
|
||||
devenue une **valeur concrète** (FQDN, groupe) — le moteur a câblé.
|
||||
3. **Requise vs optionnelle.** Compare : retirer `client_journal` d'un nœud → aucun problème
|
||||
(optionnelle). Déclarer une base **sans** serveur → `make instancier`/la validation **échoue**
|
||||
(requise). Tu *sens* la différence de modalité.
|
||||
3. **Requise, optionnelle, universelle.** Compare les trois : retirer `client_backup` d'un
|
||||
nœud sans état → aucun problème (**optionnelle**). Déclarer une base **sans** serveur →
|
||||
`make instancier` **échoue** (**requise**). Essayer de recopier `client_metrique` dans
|
||||
`serveurs.yml` → le plan **refuse** (**universelle** : elle est dérivée, la recopier
|
||||
créerait une seconde source qui finirait par diverger).
|
||||
4. **Casse & répare.** Casse une liaison requise (ex. réfère une base à un serveur inexistant),
|
||||
relance l'instanciation : **échec clair** *avant* tout déploiement. Corrige : ça passe. Le moteur
|
||||
attrape le câblage manquant à ta place.
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@ rien à inscrire nulle part. Déposer une instance à côté des autres suffit.
|
|||
|
||||
**Le seed garantit l'unicité.** Chaque tenant a un `index` distinct → adressage dérivé sans
|
||||
chevauchement possible : VLAN `1000+index×10+zone` (les VLAN de deux index différents ne peuvent
|
||||
*mathématiquement* pas se croiser). Plafond : **245** écosystèmes fédérés (borne IPv4).
|
||||
*mathématiquement* pas se croiser). Plafond : le **2ᵉ octet IPv4**, soit un index de **0 à
|
||||
255** — en évitant 0, où vivent les réseaux de service du site. *(Cette unité annonçait 245,
|
||||
un reste de l'époque où l'adressage valait `10.<10+index>` ; ce décalage a été retiré le
|
||||
2026-08-12, justement pour qu'on lise l'index directement dans l'adresse.)*
|
||||
|
||||
**Gérer la flotte :**
|
||||
- `make instances` — la vue d'ensemble : qui existe, l'active (★), index, VLAN, **collision** ;
|
||||
|
|
@ -91,15 +94,23 @@ d'aucun `index`. On la décrit dans `underlay.yml`, qui vit dans le dépôt de *
|
|||
plan par `instance/`. Ce lien ne suit pas `make instance-utiliser` : la fabric reste celle de
|
||||
l'hébergeur, quel que soit le tenant actif. Gabarit : `underlay.yml.example`.
|
||||
|
||||
| Underlay | VLAN | Sous-réseau | Fabric |
|
||||
|---|---|---|---|
|
||||
| management (commutateurs, Proxmox, OOB) | 10 | `10.0.0.0/24` | principale |
|
||||
| **transit** vers la frontière | 40 | `10.0.4.0/29` | principale |
|
||||
| stockage / iSCSI | 20 | `10.0.1.0/24` | stockage |
|
||||
| ceph-public | 30 | `10.0.2.0/24` | stockage |
|
||||
| ceph-cluster | 31 | `10.0.3.0/24` | stockage |
|
||||
> **Ne pas recopier de table ici.** Cette unité en portait une, figée, et **aucune de ses
|
||||
> cinq lignes n'était encore vraie** après la bascule d'adressage de la fabric (D-77/D-78,
|
||||
> terminée le 2026-08-22). Un underlay n'est pas un modèle : c'est la description d'un
|
||||
> matériel particulier, propre à un hébergeur. On le **demande** :
|
||||
>
|
||||
> ```bash
|
||||
> make underlay # affiche l'underlay monté, et le valide
|
||||
> ```
|
||||
>
|
||||
> Ce qu'on y trouve chez l'hébergeur de référence, à titre d'illustration seulement : un
|
||||
> plan d'**administration** sans VLAN (segment physique, `10.17.0.0/24`), le **contrôle de
|
||||
> la grappe** à part (`vmbr0`, `192.168.11.0/24`), un **transit** vers la frontière, un
|
||||
> réseau de **transport VXLAN**, trois réseaux de **stockage** sur leur propre fabric en
|
||||
> MTU 9000, et les **zones du site lui-même** — l'hébergeur est aussi un exploitant, ses
|
||||
> machines vivent là.
|
||||
|
||||
Deux choses à retenir de cette table.
|
||||
Deux choses à retenir, qui ne dépendent d'aucune table.
|
||||
|
||||
**Les fabrics.** Tous les réseaux ne partagent pas les mêmes câbles. Le stockage jumbo peut
|
||||
vivre sur ses propres commutateurs ; le devis de l'une ne déclare alors rien de l'autre, et le
|
||||
|
|
@ -116,13 +127,19 @@ route vers tous les tenants par ce même saut, il ne peut donc dériver d'aucun
|
|||
> elle n'est joignable. On cherche une règle de pare-feu ; c'est une route manquante à l'autre
|
||||
> bout.
|
||||
|
||||
En mode `sdn`, ces réseaux transportent du VXLAN : leur **MTU doit atteindre 1550** au minimum,
|
||||
sinon le ping passe et les transferts échouent. `make underlay` le refuse.
|
||||
En mode `sdn`, le transport porte du VXLAN : le **MTU des réseaux de la fabric du routeur**
|
||||
doit valoir l'overlay déclaré **plus 50 octets** d'encapsulation. `make underlay` le
|
||||
**refuse** en dessous, et le dit — sous ce seuil, le ping passe et les transferts échouent,
|
||||
la panne la plus coûteuse à diagnostiquer de cette couche.
|
||||
|
||||
`make underlay` l'affiche et le **valide** : VLAN < 1000 et sous-réseaux hors des supernets
|
||||
tenant (`10.(10+index).0.0/16`) — **aucune collision possible** avec les overlays. `make
|
||||
devis-reseau` en émet la config (section 0) et l'ajoute au trunk. La **preuve P23** garde la
|
||||
règle ; elle est *sautée* si aucun `underlay.yml` n'est défini.
|
||||
`make underlay` l'affiche et le **valide** : VLAN < 1000, et pas de chevauchement
|
||||
**accidentel** avec un supernet de tenant. « Accidentel », parce qu'il en existe un
|
||||
**voulu** : le plan d'administration de l'hébergeur occupe la **bande basse** du `/16` d'un
|
||||
tenant (D-77). Les zones d'un tenant commencent au 3ᵉ octet 16 ; la bande 0-15 lui est
|
||||
libre. Ce n'est pas une collision, mais il faut le **déclarer** (`bande_basse_de:`) — sinon
|
||||
le validateur ne peut pas faire la différence, et il refuse. `make devis-reseau` en émet la
|
||||
config (section 0) et l'ajoute au trunk. La **preuve P23** garde la règle ; elle est
|
||||
*sautée* si aucun `underlay.yml` n'est défini.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -28,9 +28,19 @@ ou expédie des logs (*shipper*). Le serveur central agrège ; un tableau de bor
|
|||
| **Loki** (`serveur_loki`) | **PUSH** | reçoit les journaux `journald` expédiés par `client_journal`. |
|
||||
| **Grafana** (`serveur_grafana`) | — | tableaux de bord au-dessus des **deux** (au SSO). |
|
||||
|
||||
Le point-clé prouvé cette session : un serveur d'observabilité **sans agents** ne voit que
|
||||
lui-même. En déployant `client_metrique`/`client_journal` (des **liaisons nœud, optionnelles**),
|
||||
Grafana voit **toute la flotte**. *Serveur ≠ agent* : les deux sont nécessaires.
|
||||
Le point-clé : un serveur d'observabilité **sans agents** ne voit que lui-même. Avec
|
||||
`client_metrique`/`client_journal` sur les nœuds, Grafana voit **toute la flotte**.
|
||||
*Serveur ≠ agent* : les deux sont nécessaires.
|
||||
|
||||
> **Ces deux liaisons ne sont PAS optionnelles**, contrairement à ce que cette unité a dit
|
||||
> jusqu'au 2026-09-06. Elles portent `universelle: true` dans leur `meta/integration.yml` :
|
||||
> tout hôte les reçoit **par dérivation**, sans qu'on écrive une ligne au plan, et **P26**
|
||||
> refuse qu'un hôte y échappe. C'est exactement la leçon du paragraphe ci-dessus, tirée à
|
||||
> son terme : le plan portait 28 lignes qui disaient « oui » à quelque chose de vrai pour
|
||||
> tous — elles n'existaient que pour être oubliées, et quatre l'avaient été. Deux serveurs
|
||||
> n'étaient alors ni supervisés ni journalisés, et **une machine non supervisée ne
|
||||
> proteste pas**. Aujourd'hui on ne peut plus oublier : il faut **exempter**, et dire
|
||||
> pourquoi.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -55,7 +65,7 @@ Tu as appris **métriques vs logs, pull vs push, le motif agent** — pas « Pro
|
|||
```
|
||||
2. **Vois les journaux** : `curl -s http://localhost:3100/loki/api/v1/label/host/values` → les nœuds
|
||||
qui expédient leurs logs.
|
||||
3. **Ouvre Grafana** (`https://grafana.lab.chezlepro.internal`) — métriques *et* logs au même endroit.
|
||||
3. **Ouvre Grafana** (`https://grafana.chezlepro.internal`) — métriques *et* logs au même endroit.
|
||||
4. **Casse & répare.** Arrête `prometheus-node-exporter` sur un nœud : dans Prometheus, sa cible passe
|
||||
**`up=0`** (DOWN). Redémarre : elle repasse UP. Tu *sens* que c'est **l'agent** qui nourrit le
|
||||
serveur (modèle pull).
|
||||
|
|
@ -65,4 +75,4 @@ Tu as appris **métriques vs logs, pull vs push, le motif agent** — pas « Pro
|
|||
## Pour aller plus loin *(dépôt)*
|
||||
- Rôles : `roles/serveur_prometheus`, `roles/serveur_loki`, `roles/serveur_grafana`.
|
||||
- Agents : `roles/client_metrique` (node_exporter), `roles/client_journal` (→ Loki).
|
||||
- Ces agents sont des **liaisons optionnelles** : unité **Liaisons**.
|
||||
- Ces agents sont des **intégrations universelles** (posées par dérivation, gardées par P26) : unités **Liaisons** et `docs/integrations-vm.md`.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
**Chiffrement asymétrique** : une **paire de clés** — une **privée** (secrète) et une **publique**
|
||||
(partageable). Ce que l'une chiffre, l'autre le déchiffre. La privée **signe**, la publique **vérifie**.
|
||||
|
||||
**Un certificat** = une clé publique + une identité (« ce serveur est `id-ldap-01` »), le tout
|
||||
**Un certificat** = une clé publique + une identité (« ce serveur est `idm-01` »), le tout
|
||||
**signé** par une autorité. Il répond à : *« à qui est-ce que je parle, vraiment ? »*
|
||||
|
||||
**L'autorité de certification (AC / CA)** signe les certificats. On lui fait confiance, donc on fait
|
||||
|
|
@ -29,7 +29,7 @@ confiance à toute la chaîne.
|
|||
| Pièce | Rôle | Concept incarné |
|
||||
|---|---|---|
|
||||
| **step-ca** (`serveur_step_ca`) | l'**autorité de certification** interne (racine + intermédiaire, base des émissions). | AC, chaîne de confiance |
|
||||
| **client_pki** (`client_pki`) | intégration : un nœud **obtient un certificat** de l'AC (via ACME) et **fait confiance à la racine**. | émission ACME, magasin de confiance |
|
||||
| **client_pki** (`client_pki`) | intégration **universelle** : tout nœud **obtient un certificat** de l'AC (via ACME) et **fait confiance à la racine**. Elle ne se déclare pas — elle est dérivée, et **P26** refuse qu'un hôte y échappe. Seule exemption, dérivée : l'hôte qui *est* l'AC, qui ne s'enrôle pas auprès d'elle-même. | émission ACME, magasin de confiance |
|
||||
|
||||
Le motif : chaque service qui doit prouver son identité (LDAPS d'OpenLDAP, HTTPS de l'edge…)
|
||||
reçoit un **certificat d'hôte** signé par step-ca ; la **racine** est déposée dans le **magasin de
|
||||
|
|
@ -68,7 +68,7 @@ Encrypt, Vault, une AC d'entreprise : le schéma est **identique**.
|
|||
`OK` = la racine valide bien le certificat du serveur. C'est ① en action.
|
||||
3. **Vois-le servir en vrai.** Le LDAPS d'OpenLDAP utilise ce certificat :
|
||||
```bash
|
||||
openssl s_client -connect id-ldap-01.lab.chezlepro.internal:636 \
|
||||
openssl s_client -connect idm-01.chezlepro.internal:636 \
|
||||
-CAfile /etc/step/certs/root_ca.crt </dev/null 2>/dev/null | grep -E 'Verify return code'
|
||||
```
|
||||
`0 (ok)` = confiance vérifiée.
|
||||
|
|
@ -92,13 +92,25 @@ fiable. Et attention à un piège vécu en vrai :
|
|||
|
||||
Diagnostic-réflexe : **comparer le cert servi au cert fichier**.
|
||||
```bash
|
||||
echo | openssl s_client -connect EDGE:443 -servername keycloak.lab… 2>/dev/null | openssl x509 -noout -enddate # SERVI
|
||||
echo | openssl s_client -connect EDGE:443 -servername keycloak.chezlepro.internal 2>/dev/null | openssl x509 -noout -enddate # SERVI
|
||||
openssl x509 -in /etc/step/certs/EDGE.crt -noout -enddate # FICHIER
|
||||
```
|
||||
Dans Set-OPS, `client_pki_reload_services` (par nœud) fait recharger les **vrais** consommateurs
|
||||
après chaque renouvellement — edge→nginx, mail→postfix/dovecot, annuaire→slapd. Fix d'urgence si
|
||||
ça arrive : `systemctl reload nginx` sur l'edge.
|
||||
|
||||
Ce diagnostic est **outillé** depuis le 2026-08-08 : `make certificats-plan` compare, pour
|
||||
toute la flotte, ce que le disque porte à ce que la mémoire sert. Il a trouvé quelque chose
|
||||
à sa première exécution — sur `infra-pki-01`, **l'autorité elle-même**, le certificat était
|
||||
expiré depuis plus de huit heures et le renouvellement échouait toutes les quatorze minutes
|
||||
sur `'step ca renew' requires the '--ca-url' flag`. Rien ne le signalait, et le harnais
|
||||
était entièrement vert.
|
||||
|
||||
> **Ne compare pas les empreintes, regarde l'échéance de ce qui est SERVI.** Avec des certs
|
||||
> de 24 h renouvelés toutes les ~14 minutes, une empreinte servie *différente* de celle sur
|
||||
> disque est l'état **normal** : un contrôle par empreinte crierait en permanence, et on
|
||||
> apprendrait à l'ignorer.
|
||||
|
||||
**Casse & répare** : sur l'edge, arrête le timer `cert-renewer@…`, laisse le cert expirer (ou
|
||||
force une horloge), observe le login SSO casser (échec TLS de l'échange OIDC), puis recharge nginx
|
||||
→ tout revient. Tu *sens* que la PKI ne vit que si le renouvellement **et** le rechargement tournent.
|
||||
|
|
|
|||
|
|
@ -47,11 +47,24 @@ Détail de ce que chaque devis vérifie — et de ce qu'il ne vérifie pas : `do
|
|||
Un prérequis et trois pièges, tous à la première connexion. Le runbook complet est dans
|
||||
`docs/autorisation.md` **§6** ; voici l'ordre et la raison de chaque geste.
|
||||
|
||||
**1. La clé de voûte.** Le mot de passe de la voûte est lu depuis
|
||||
`ANSIBLE_VAULT_PASSWORD_FILE` (`~/.config/setops-vault-pass` par défaut). **Sans ce fichier,
|
||||
rien n'est possible** — ni les devis ci-dessus, ni un déploiement. C'est la première chose à
|
||||
sauvegarder hors de la machine, avec les `vault.yml` de chaque instance, qui ne sont pas
|
||||
versionnés.
|
||||
**1. La clé de voûte — une voûte, une clé.** Chaque dépôt a **sa** clé, nommée d'après lui :
|
||||
`~/.config/setops-vault-<dépôt-en-minuscules>`. Il n'y a **rien à exporter** — le `Makefile`
|
||||
les rassemble seul (`scripts/voutes.py` → `ANSIBLE_VAULT_IDENTITY_LIST`). Pour voir ce que
|
||||
cette machine peut ouvrir :
|
||||
|
||||
```
|
||||
python3 scripts/voutes.py etat
|
||||
```
|
||||
|
||||
**Sans la clé de ton écosystème, rien n'est possible** — ni les devis ci-dessus, ni un
|
||||
déploiement. C'est la première chose à sortir de la machine (`make cles-exporter`, cf.
|
||||
`docs/sortir-les-cles-du-poste.md`), avec les `vault.yml` de chaque instance, qui ne sont
|
||||
pas versionnés.
|
||||
|
||||
> Ce paragraphe a désigné un `ANSIBLE_VAULT_PASSWORD_FILE` unique jusqu'au 2026-09-06. Ce
|
||||
> n'est plus le mécanisme, et la raison compte : un seul mot de passe ouvrait alors *toutes*
|
||||
> les voûtes de la flotte, celle de l'hébergeur comprise. Compromettre le plus petit
|
||||
> locataire, c'était obtenir les secrets de tous.
|
||||
|
||||
**2. Le mot de passe d'amorçage, à changer avant tout le reste** (§6.1). L'annuaire refuse
|
||||
toute opération tant qu'il n'est pas changé, sauf le changement lui-même. Ce n'est pas
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Un seul endroit gère les certificats → simple et cohérent.
|
|||
## ② Comment Set-OPS le fait
|
||||
|
||||
`serveur_nginx` déployé sur l'**edge** (`infra-edge`) est le reverse-proxy. Le point élégant :
|
||||
l'**exposition est auto-dérivée**. Déclarer `expose: [icinga.lab.chezlepro.internal]` sur une app
|
||||
l'**exposition est auto-dérivée**. Déclarer `expose: [icinga.chezlepro.internal]` sur une app
|
||||
génère **tout** :
|
||||
|
||||
```
|
||||
|
|
@ -49,14 +49,14 @@ Tu as appris **le reverse-proxy, le routage par nom, la terminaison TLS** — pa
|
|||
|
||||
## ④ À toi de jouer
|
||||
|
||||
1. **Route par nom.** Deux noms, un seul edge (`192.168.15.21`) :
|
||||
1. **Route par nom.** Deux noms, un seul edge (`10.17.16.11`) :
|
||||
```bash
|
||||
curl -sI --resolve grafana.lab.chezlepro.internal:443:192.168.15.21 \
|
||||
--cacert /etc/step/certs/root_ca.crt https://grafana.lab.chezlepro.internal/ | head -1
|
||||
curl -sI --resolve grafana.chezlepro.internal:443:10.17.16.11 \
|
||||
--cacert /etc/step/certs/root_ca.crt https://grafana.chezlepro.internal/ | head -1
|
||||
```
|
||||
Change `grafana` en `forge` : même IP, **backend différent**. C'est le routage par SNI.
|
||||
2. **Vois la terminaison TLS.** Le certificat présenté est celui de l'**edge** (avec les SAN des
|
||||
exposés) : `openssl s_client -connect 192.168.15.21:443 -servername grafana.lab… | openssl x509 -noout -text | grep -A1 'Subject Alternative'`.
|
||||
exposés) : `openssl s_client -connect 10.17.16.11:443 -servername grafana.chezlepro.internal | openssl x509 -noout -text | grep -A1 'Subject Alternative'`.
|
||||
3. **Casse & répare.** Arrête le backend (ex. `systemctl stop grafana-server` sur obs-01) et rouvre
|
||||
Grafana : l'edge répond **502 Bad Gateway** (le proxy est là, le service non). Redémarre : ça
|
||||
remarche. Tu distingues **le proxy** de **ce qu'il sert**.
|
||||
|
|
|
|||
|
|
@ -32,8 +32,16 @@ Choix fondateur : **sauvegarder la donnée** (l'infra est reconstructible par le
|
|||
| Pièce | Rôle |
|
||||
|---|---|
|
||||
| **restic** | l'outil : chiffrement côté client, déduplication, rétention. |
|
||||
| **`serveur_backup`** | la **cible** hors-nœud (un dépôt restic par nœud). |
|
||||
| **`client_backup`** | intégration par nœud : **jobs déclaratifs** (dump + chemins), timer quotidien, rétention. |
|
||||
| **`serveur_backup`** | la **cible** hors-nœud (un dépôt restic par nœud) — depuis le 2026-09-01, chez l'**hébergeur** (`site-backup-01`), un compte Unix par écosystème. |
|
||||
| **`client_backup`** | intégration par nœud : **jobs déclaratifs** (dump + chemins), timer quotidien, rétention — et, depuis le 2026-09-02, **vérification de son propre dépôt distant**. |
|
||||
|
||||
> **Qui vérifie a changé.** Le dépôt était le seul à voir ce qui arrivait vraiment : un
|
||||
> nœud sait qu'il a *lancé* sa sauvegarde, pas qu'elle a *abouti*. C'était juste tant que
|
||||
> le dépôt vivait dans l'écosystème. Depuis que les écosystèmes déposent chez leur
|
||||
> **hébergeur** — qui héberge du chiffré côté client et ne peut rien juger — la
|
||||
> vérification revient au seul qui détient la clé : **le nœud lui-même**. Il interroge son
|
||||
> dépôt *distant*, et non le fait d'avoir lancé un timer. Une unité verte sur un dépôt vide
|
||||
> est exactement ce qui a menti pendant un mois.
|
||||
|
||||
Ce qu'on protège, par **tiers** :
|
||||
- **Tier 0 (vital)** : les **clés de la CA** step-ca (`/etc/step-ca`) — l'ancre de confiance, irremplaçable.
|
||||
|
|
@ -64,12 +72,15 @@ Tu as appris **quoi sauvegarder, la règle 3-2-1, logique vs image, et surtout r
|
|||
```bash
|
||||
/usr/local/sbin/setops-sauvegarder.sh
|
||||
```
|
||||
2. **Liste les instantanés** (le dépôt vit hors-nœud) :
|
||||
2. **Liste les instantanés** (le dépôt vit hors-nœud, et hors de l'écosystème) :
|
||||
```bash
|
||||
export RESTIC_REPOSITORY=sftp:restic@backup-01.lab.chezlepro.internal:$(hostname)
|
||||
export RESTIC_PASSWORD_FILE=/etc/setops/restic.pass
|
||||
# NE PAS RECOPIER UNE ADRESSE ICI : la cible est une valeur du plan, et elle a
|
||||
# deja change. Le noeud la porte deja, gravee dans son propre script.
|
||||
eval "$(grep -E '^export RESTIC_' /usr/local/sbin/setops-sauvegarder.sh)"
|
||||
restic snapshots
|
||||
```
|
||||
*Le même dépôt est interrogé chaque nuit par `setops-verifier-mon-depot.sh`, qui
|
||||
rapporte à Icinga : c'est le nœud, seul détenteur de la clé, qui juge.*
|
||||
3. **Restaure — le vrai test.** Restaure dans un dossier temporaire et **compare** :
|
||||
```bash
|
||||
restic restore latest --target /tmp/rst
|
||||
|
|
@ -85,4 +96,9 @@ Tu as appris **quoi sauvegarder, la règle 3-2-1, logique vs image, et surtout r
|
|||
## Pour aller plus loin *(dépôt)*
|
||||
- Rôles : `roles/serveur_backup`, `roles/client_backup`.
|
||||
- Philosophie « donnée, pas VM » + les tiers : voir le CHANGELOG (entrée sauvegardes) et les jobs en host_vars.
|
||||
- Complément 3-2-1 (offsite) : reste à faire — c'est l'**Étape B** (frontière publique).
|
||||
- Le **1 hors-site** de la règle 3-2-1 : `make depot-hors-site VERS=<répertoire>`
|
||||
(`playbooks/maintenance/depot-hors-site.yml`). Il emporte le dépôt du site — celui de
|
||||
l'hébergeur **et** ceux des locataires, puisque c'est l'hébergeur qui a pris cette
|
||||
promesse. La copie est opaque, et l'empreinte est prise **à la source** puis recalculée
|
||||
sur la copie : sans cela on rentre chez soi avec un répertoire, pas avec une sauvegarde.
|
||||
Manœuvre exécutée le 2026-09-05 — 233 fichiers, 95,7 Mo, empreintes identiques une à une.
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ Tu as appris **supervision active vs observabilité passive, l'état, l'alerting
|
|||
|
||||
## ④ À toi de jouer
|
||||
|
||||
1. **Ouvre Icinga Web 2** (`https://icinga.lab.chezlepro.internal`, via le SSO) : la liste des hôtes
|
||||
1. **Ouvre Icinga Web 2** (`https://icinga.chezlepro.internal`, via le SSO) : la liste des hôtes
|
||||
et services **supervisés**, avec leur **état** (vert/jaune/rouge).
|
||||
2. **Vois l'impact.** Menu *Business Processes* → « **Supervision Chezlepro** » : un processus qui
|
||||
**agrège** des checks (load, procs, ping…) en un état roulé. C'est l'impact, pas une case.
|
||||
|
|
|
|||
|
|
@ -31,14 +31,28 @@ pas en option :
|
|||
| Audit | `auditd` |
|
||||
| Anti-force-brute SSH | `fail2ban_ssh` |
|
||||
| Durcissement noyau | `sysctl_hardening` |
|
||||
| Pare-feu | `nftables_baseline` (*installé et préparé, désactivé par défaut*) |
|
||||
| Pare-feu | `nftables_baseline` — **règles dérivées du registre des flux**, pas écrites à la main |
|
||||
| Mises à jour | `unattended_upgrades` |
|
||||
| Journaux | `journald` (rétention, persistance) |
|
||||
| Vidages mémoire | `core_dumps` (désactivés — un *core* peut contenir des secrets) |
|
||||
| Paquets | `hardening_packages` |
|
||||
| SSH | `ssh_baseline` + `ssh_hardening` (clé d'abord, `PermitRootLogin no`…) |
|
||||
| Moindre privilège | compte technique `ansible` + `sudo_ansible` (pas de root direct) |
|
||||
|
||||
Nuance importante : le **pare-feu** est *préparé mais pas activé* dans le template — on l'active sur
|
||||
un **clone/serveur final** avec des règles adaptées à son rôle (couper l'accès à l'aveugle = un
|
||||
risque). Prudence par conception.
|
||||
Le groupe `serveur_durci` compose **dix** de ces rôles en un seul geste ; `ssh_baseline` et
|
||||
`sudo_ansible` viennent du socle `serveur_debian`, en amont.
|
||||
|
||||
**Le pare-feu : préparé dans le gabarit, armé sur la flotte.** `nftables_baseline` vaut
|
||||
`false` par défaut *dans le rôle* — couper l'accès à l'aveugle pendant la construction d'un
|
||||
gabarit serait un risque gratuit. Mais l'instance le met à `true` pour `hotes_actifs` : sur
|
||||
une machine réelle, **le pare-feu tourne**.
|
||||
|
||||
Et ses règles ne s'écrivent pas à la main. Chaque rôle déclare dans son `meta/flux.yml` ce
|
||||
qu'il écoute et ce à quoi il se connecte ; `scripts/resoudre_flux.py` en dérive le jeu de
|
||||
règles, en `policy drop` par défaut. Le **même** registre alimente le pare-feu de
|
||||
l'hyperviseur et la frontière OPNsense : trois couches qui ne *peuvent pas* se contredire,
|
||||
parce qu'elles descendent d'une seule décision. C'est la défense en profondeur du §① prise
|
||||
au mot — sans le coût habituel, qui est de tenir trois politiques cohérentes à la main.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,11 @@ Idée-force : la VM devient **jetable/reconstructible**. Ce qui est précieux, c
|
|||
## ② Comment Set-OPS le fait
|
||||
|
||||
- **Proxmox** = l'hyperviseur (cluster).
|
||||
- Un **golden template** (`basiqueChezlepro`) : Debian minimal, durci, avec le compte technique
|
||||
`ansible`, qemu-guest-agent, cloud-init… — préparé **une fois**.
|
||||
- Un **golden template** (`modeleSetOPS`) : Debian minimal, durci, avec le compte technique
|
||||
`ansible`, qemu-guest-agent, cloud-init… — préparé **une fois**. *(Cette unité l'appelait
|
||||
`basiqueChezlepro` jusqu'au 2026-09-06 : c'est l'ancien nom. Le nom en vigueur est celui
|
||||
qu'enregistre `make config` sous `proxmox_clone_source_nom`, et il doit correspondre au
|
||||
nom réel du template dans Proxmox — sinon le clonage ne trouve pas sa source.)*
|
||||
- Chaque nœud = un **clone** du template. `cloud-init` pose l'identité (hostname, IP dérivée de la
|
||||
nomenclature, clé SSH).
|
||||
- **Puis** Set-OPS/Ansible fait la **vraie** configuration (les rôles).
|
||||
|
|
|
|||
|
|
@ -45,6 +45,20 @@ make postgresql-plan le chiffrement est-il imposé, et à quels réseaux
|
|||
make courriel-plan Postfix → LDAP → LMTP → Dovecot → IMAP, file d'attente comprise
|
||||
```
|
||||
|
||||
Le même patron a ensuite été porté **sous** les services, au monde physique — mêmes pièces,
|
||||
même refus d'écrire :
|
||||
|
||||
```
|
||||
make frontiere-plan les règles de la frontière OPNsense contre leur devis
|
||||
make proxmox-fw-plan le pare-feu est-ouest de l'hyperviseur contre le registre des flux
|
||||
make sdn-plan la zone EVPN, ses VNets et la sortie des VRF
|
||||
make underlay-plan l'underlay déclaré contre ce que le cluster porte vraiment
|
||||
make placement-plan chaque VM est-elle là où le plan la met
|
||||
```
|
||||
|
||||
*(Deux mesures voisines ne comparent à rien et ne portent donc pas le suffixe `-plan` :
|
||||
`make mtu-mesurer` et `make versions-mesurer` relèvent un état, sans devis en face.)*
|
||||
|
||||
| Pièce | Rôle |
|
||||
|---|---|
|
||||
| un **playbook** (`playbooks/maintenance/devis-*.yml`) | **relève** le déclaré et le réel, dépose un JSON |
|
||||
|
|
@ -86,8 +100,9 @@ l'éprouver dans les deux sens, en cassant volontairement ce qu'il surveille.
|
|||
|
||||
## ④ À toi de jouer
|
||||
|
||||
1. Lance les cinq devis sur ta flotte. Note le temps que ça prend : quelques minutes pour ce qui
|
||||
demandait une journée d'enquête à la main.
|
||||
1. Lance les **dix** devis sur ta flotte — les cinq de service, puis les cinq
|
||||
d'infrastructure. Note le temps que ça prend : quelques minutes pour ce qui demandait une
|
||||
journée d'enquête à la main.
|
||||
2. **Casse quelque chose exprès** — arrête un service publié, change un port — et relance le
|
||||
devis concerné. S'il ne dit rien, c'est *lui* qu'il faut réparer, pas le service.
|
||||
3. Cherche, dans ton propre outillage, une vérification qui n'a **jamais** échoué. Demande-toi si
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
- [DNS & résolution de noms](DNS-et-résolution)
|
||||
|
||||
*Communication*
|
||||
- [Le réseau des tenants](Le-réseau-des-tenants)
|
||||
- [Reverse-proxy & TLS](Reverse-proxy-et-TLS)
|
||||
- [Courriel (SMTP/IMAP)](Courriel)
|
||||
|
||||
|
|
@ -36,6 +37,7 @@
|
|||
*Flotte & preuve*
|
||||
- [Multi-instance & fédération](Multi-instance-et-fédération)
|
||||
- [La preuve](La-preuve)
|
||||
- [Filiation, signatures & témoins](Filiation-signatures-et-témoins)
|
||||
- [Vérifier le déployé](Vérifier-le-déployé)
|
||||
|
||||
**Opérations**
|
||||
|
|
|
|||
Loading…
Reference in a new issue