diff --git a/wiki/Bases-de-données.md b/wiki/Bases-de-données.md new file mode 100644 index 0000000..be9d10c --- /dev/null +++ b/wiki/Bases-de-données.md @@ -0,0 +1,71 @@ +# Bases de données + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. + +--- + +## ① Le concept *(générique)* + +Une **base de données relationnelle** stocke des données en **tables** (lignes/colonnes) reliées. +Modèle **client-serveur** : le serveur (PostgreSQL) détient les données ; les applications s'y +**connectent** par le réseau, avec un **compte** et un **mot de passe**, sur une **base** donnée. + +**Schéma** = la structure (tables, contraintes). **ACID** = les garanties de fiabilité des +transactions (Atomicité, Cohérence, Isolation, Durabilité). **Rôles/permissions** = qui peut lire/écrire. + +Bonne pratique : **une base + un compte dédiés par application** (isolation) — pas un compte +tout-puissant partagé. + +--- + +## ② Comment Set-OPS le fait + +`serveur_postgresql` (nœud `data-sql`) est le serveur partagé. L'élégance : un **registre** +déclaratif des bases (`plan/bases-donnees.yml`). Chaque entrée dit *quelle base, quel compte, quel +secret, pour quel consommateur* : + +``` +Registre ──> PostgreSQL crée la base + le compte propriétaire + ──> le rôle consommateur (Keycloak, Forgejo, Icinga…) LIT la même + entrée et bâtit sa connexion — via resoudre_base +``` + +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. + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| PostgreSQL | MySQL/MariaDB · SQLite · Oracle · SQL Server | +| une base/compte par app | pratique **universelle** d'isolation | +| secret en voûte | Vault · SOPS · secrets managers cloud | + +Tu as appris **le modèle client-serveur, le schéma, l'isolation par app, les secrets** — pas +« PostgreSQL ». + +--- + +## ④ À toi de jouer + +1. **Liste les bases** (sur data-sql-01) : + ```bash + sudo -u postgres psql -c '\l' # keycloak, forgejo, icingadb… + sudo -u postgres psql -c '\du' # les comptes propriétaires + ``` +2. **Vois l'isolation.** Chaque app a **sa** base et **son** compte — pas de compte partagé. +3. **Suis une liaison.** Ouvre `plan/bases-donnees.yml` : l'entrée `keycloak` (serveur, base, + propriétaire, secret) est *exactement* ce que le rôle `serveur_keycloak` va lire pour se connecter. +4. **Casse & répare.** Change le mot de passe d'un compte dans PostgreSQL (garde l'ancien !) sans + mettre à jour la voûte : l'app **ne se connecte plus**. Restaure : ça repart. Tu *sens* que la + connexion = *identité + secret cohérents des deux côtés*. + +--- + +## Pour aller plus loin *(dépôt)* +- Rôle : `roles/serveur_postgresql` ; résolveur partagé : `roles/resoudre_base`. +- Le registre : `instance/plan/bases-donnees.yml` ; validation : `scripts/bases_donnees.py verifier`. +- Sauvegarde (Tier 1, `pg_dumpall`) : unité **Sauvegardes**. diff --git a/wiki/Cache.md b/wiki/Cache.md new file mode 100644 index 0000000..6f72633 --- /dev/null +++ b/wiki/Cache.md @@ -0,0 +1,64 @@ +# Cache + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. + +--- + +## ① Le concept *(générique)* + +Un **cache** garde en **mémoire** (rapide) des données coûteuses à recalculer ou à relire (disque, +base, réseau). Modèle **clé-valeur** : `SET clé valeur`, `GET clé`. + +Comme la mémoire est limitée : +- **éviction** — quand c'est plein, on jette (souvent **LRU** : *Least Recently Used*) ; +- **TTL** — une valeur peut **expirer** après un délai. + +Règle d'or : **le cache n'est PAS la source de vérité**. Il est **éphémère** — on doit pouvoir le +**perdre sans drame** (la vraie donnée est ailleurs). Le vider = plus lent un instant, jamais faux. + +--- + +## ② Comment Set-OPS le fait + +`serveur_redis` (nœud `data-sql`) fournit un cache réseau. Points notables : +- **authentification obligatoire** (`requirepass`, secret en voûte) — il est exposé sur le réseau + interne, donc on ne laisse jamais un cache ouvert ; +- **`maxmemory` + politique `allkeys-lru`** — borne la mémoire, évince en LRU ; +- Icinga a son **propre** Redis dédié (`icingadb-redis`) — un cache par besoin, pas un fourre-tout. + +Conséquence directe : Redis est **Tier 3** (éphémère) — **on ne le sauvegarde pas**. C'est le +pendant parfait de l'unité *Sauvegardes* : on protège la donnée d'état, **pas** le cache. + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| Redis | Memcached · Valkey · KeyDB · caches cloud (ElastiCache…) | +| LRU + TTL | mécanismes **universels** d'éviction/expiration | +| cache éphémère ≠ source de vérité | principe valable partout | + +Tu as appris **le cache clé-valeur, l'éviction LRU, le TTL, l'éphémère** — pas « Redis ». + +--- + +## ④ À toi de jouer + +1. **Écris/lis avec authentification** (sur data-sql-01) : + ```bash + redis-cli -a "" SET essai:1 bonjour + redis-cli -a "" GET essai:1 + ``` +2. **Teste le TTL** : `redis-cli -a … SET court 1 EX 5` puis `GET court` avant/après 5 s — il **expire**. +3. **Vois la borne** : `redis-cli -a … CONFIG GET maxmemory` et `… maxmemory-policy` (LRU). +4. **Casse & répare.** Interroge **sans** mot de passe : `redis-cli GET essai:1` → **`NOAUTH`** + (refusé). Puis vide le cache (`FLUSHALL`) : rien ne casse dans l'écosystème — la vraie donnée est + en base. Tu *sens* qu'un cache est **jetable**. + +--- + +## Pour aller plus loin *(dépôt)* +- Rôle : `roles/serveur_redis`. +- Redis dédié d'Icinga : `roles/serveur_icinga` (`icingadb-redis`). +- Tiers de sauvegarde (Redis = Tier 3, non sauvegardé) : unité **Sauvegardes**. diff --git a/wiki/Courriel.md b/wiki/Courriel.md new file mode 100644 index 0000000..6e3da48 --- /dev/null +++ b/wiki/Courriel.md @@ -0,0 +1,72 @@ +# Courriel (SMTP / IMAP) + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. + +--- + +## ① Le concept *(générique)* + +Le courriel, c'est **trois rôles** distincts (souvent confondus) : +- **MTA** (*Mail Transfer Agent*) : transporte le courrier entre serveurs — protocole **SMTP** (`:25`). +- **MDA** (*Mail Delivery Agent*) : dépose le courrier dans la **boîte** et la sert — **IMAP** (`:993`). +- **MUA** (*Mail User Agent*) : ton client (Thunderbird, l'appli). + +Deux SMTP différents : +- **`:25`** = relais **serveur↔serveur** (pas d'authentification par mot de passe). +- **`:587` (soumission)** = un **client authentifié** *envoie* son courrier (**SMTP AUTH + STARTTLS**). + +**LMTP** = remise **locale** du MTA vers le magasin. **Déliverabilité** (vers l'externe) = un tout +autre problème : **DKIM** (signer), **SPF**, **DMARC**, réputation IP. + +--- + +## ② Comment Set-OPS le fait + +| Pièce | Rôle | +|---|---| +| **Postfix** (`serveur_postfix`, edge-mta) | le **MTA** : reçoit `:25`, valide le destinataire **contre LDAP**, remet en **LMTP**. | +| **Dovecot** (`serveur_dovecot`, infra-mail) | le **MDA/magasin** : boîtes `/var/vmail`, **IMAP** `:993`. | +| **rspamd** (`serveur_rspamd`) | antispam + **signature DKIM**. | + +La **boucle souveraine**, prouvée de bout en bout : +``` +Reçevoir : … ──> Postfix :25 ──> validation LDAP ──> LMTP ──> Dovecot ──> IMAP +Envoyer : client ──> :587 (AUTH+STARTTLS) ──> SASL Dovecot/LDAP ──> Postfix ──> remise +``` +Une **identité** (`testmail`, le mot de passe LDAP) sert IMAP *et* la soumission. Le tout **interne, +chiffré, sans jamais toucher Internet** (l'envoi vers l'externe = Étape B, déliverabilité). + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| Postfix / Dovecot | Exim · Sendmail · Exchange · tout serveur SMTP/IMAP | +| SMTP/IMAP/LMTP, `:587` | **protocoles standards** — identiques partout | +| DKIM/SPF/DMARC | universels pour la déliverabilité | + +Tu as appris **MTA/MDA/MUA, SMTP vs soumission, IMAP, la déliverabilité** — pas « Postfix ». + +--- + +## ④ À toi de jouer + +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' + ``` + `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 + destinataire** (il ne peut plus valider en LDAP). Rallume OpenLDAP : ça repart. Tu *sens* la + dépendance **requise** MTA → annuaire. + +--- + +## Pour aller plus loin *(dépôt)* +- Rôles : `roles/serveur_postfix`, `roles/serveur_dovecot`, `roles/serveur_rspamd`. +- Conception + Étape B (déliverabilité publique) : `docs/courriel-conception.md`. +- Notifications système des nœuds : `client_smtp` (relais vers le MTA). diff --git a/wiki/Infra-as-Code-et-idempotence.md b/wiki/Infra-as-Code-et-idempotence.md new file mode 100644 index 0000000..09a4fdd --- /dev/null +++ b/wiki/Infra-as-Code-et-idempotence.md @@ -0,0 +1,68 @@ +# Infra as Code & idempotence + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. + +--- + +## ① Le concept *(générique)* + +**Infra as Code (IaC)** : décrire l'infrastructure **dans du code** (versionné, revu, reproductible) +plutôt qu'à la main. Le serveur devient le **résultat d'un fichier**, pas d'une suite de clics oubliés. + +**Déclaratif vs impératif** : +- *impératif* = « fais ceci, puis cela » (une recette d'étapes) ; +- *déclaratif* = « voici l'**état voulu** » (le moteur trouve comment y arriver). + +**Idempotence** : appliquer la **même** description **N fois** donne le **même** résultat. La 1ʳᵉ +exécution change des choses ; les suivantes ne changent **rien** (`changed=0`). C'est ce qui rend +l'IaC **sûre à rejouer**. + +**Modèle plan → apply** : on décrit (plan), on **prévisualise** (dry-run), on **applique**. Tout est +en **contrôle de version** (git), donc auditable et réversible. + +--- + +## ② Comment Set-OPS le fait + +- **Ansible** = le moteur **déclaratif** (des *rôles* décrivant l'état voulu, idempotents). +- Le **plan** (`serveurs.yml`, `applications.yml`, `bases-donnees.yml`) décrit *quoi* déployer. +- `make instancier` **génère** l'inventaire statique depuis le plan. +- `make deployer` applique les rôles ; le `Vérifier` (dry-run) **prévisualise** d'abord. +- Tout vit dans **git** (ce dépôt) — reproductible, revu, réversible. + +Preuve d'idempotence, vue partout cette session : redéployer un rôle déjà en place → +**`changed=0`**. Et un refactor « neutre » (ex. le binding annuaire) → `changed=0` aussi : *même +état voulu = aucune modification*. + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| Ansible | Terraform · Puppet · Chef · SaltStack · OpenTofu | +| plan → dry-run → apply | `terraform plan/apply`, tout workflow IaC | +| idempotence | **propriété fondamentale** de toute IaC sérieuse | + +Tu as appris **le déclaratif, l'idempotence, plan→apply, l'infra versionnée** — pas « Ansible ». + +--- + +## ④ À toi de jouer + +1. **Sens l'idempotence.** Redéploie un rôle déjà en place (ex. via la GUI ou + `make deployer HOTE=…`) : la 2ᵉ fois, **`changed=0`**. Rien à faire = rien n'est touché. +2. **Le flux déclaratif.** Édite le plan (un serveur dans la GUI), `⚙ Appliquer le plan` + (instancier), puis `Vérifier` (dry-run) : tu **prévisualises** avant d'appliquer. +3. **La réversibilité.** `git diff` / `git checkout` sur le plan : l'état est **du code**, donc + annulable. +4. **Casse & répare.** Modifie à la main un fichier géré par un rôle (ex. un `.conf`), puis + redéploie : Ansible **rétablit l'état voulu** (le code gagne sur la dérive manuelle). Tu *sens* + que la source de vérité, c'est **le code**. + +--- + +## Pour aller plus loin *(dépôt)* +- Le flux : `make instancier` → `make instancier-appliquer` → `make deployer` (ou la GUI). +- Le plan : `instance/plan/` ; les rôles : `roles/` ; l'autorité : `AGENTS.md`. +- Relations déclaratives entre entités : unité **Liaisons (bindings)**. diff --git a/wiki/Liaisons-bindings.md b/wiki/Liaisons-bindings.md new file mode 100644 index 0000000..35d86a3 --- /dev/null +++ b/wiki/Liaisons-bindings.md @@ -0,0 +1,79 @@ +# Liaisons (bindings) + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. + +--- + +## ① Le concept *(générique)* + +Un système réel n'est pas fait de pièces isolées, mais de **relations** : cette app *utilise* cette +base, ce serveur *fait confiance* à cette AC, ce nœud *envoie ses logs* à ce collecteur. + +Deux façons de câbler ces relations : +- **En dur** — recopier l'adresse/le nom dans chaque config. Fragile : déplacer une pièce oblige à + éditer partout, et ça casse la portabilité. +- **En liaisons déclaratives** — on **déclare** « A est lié à B », et le **moteur résout** l'adresse + concrète au bon moment. Déplacer B ? On ne touche qu'un endroit. + +> **Analogie NetScaler (Citrix ADC)** : tu *bind* un *service* à un *vserver*, une *policy* à un +> *vserver*, un *monitor* à un *service*. Tu ne codes pas des IP en dur — tu **relies des entités**, +> et l'appareil fait le reste. Les liaisons de Set-OPS, c'est exactement ce modèle. + +Deux **axes** pour classer une liaison (indépendants) : +- **Niveau** : *app→app/base/domaine* (`liens`) ou *nœud→service de flotte* (`intégrations`). +- **Modalité** : **requise** (constitutive — sans elle, ça ne s'instancie pas) ou **optionnelle** + (élective — un choix, l'absence est légitime). + +--- + +## ② Comment Set-OPS le fait + +| Type | Où | Résolu en | Exemple | +|---|---|---|---| +| **`liens`** | `applications.yml` | **config** (host_vars, lookups) | Forgejo → sa base ; app → domaine exposé | +| **`intégrations`** | `serveurs.yml` | **groupe + agent client** | nœud → PKI, sauvegarde, métriques… | + +Les **résolveurs partagés** font le pont : `resoudre_base` (app→base) et `resoudre_annuaire` +(app→annuaire) lisent un **registre** et bâtissent la connexion — le secret restant déréférencé +**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). + +C'est **le** concept de Set-OPS : *tu déclares les liaisons, le moteur câble.* + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| liens/intégrations déclaratifs | **NetScaler bindings** · références de ressources Terraform | +| service ↔ backend | Kubernetes : Service↔Pods, Ingress↔Service | +| requis vs optionnel | dépendances *hard* vs *soft* (partout) | + +Tu as appris **la relation déclarative, la résolution par un moteur, requis vs optionnel** — pas un +produit. C'est un **modèle mental** qui vaut de NetScaler à Kubernetes. + +--- + +## ④ À toi de jouer + +1. **Lis une liaison.** Ouvre `instance/plan/applications.yml` : une app avec `expose:` (liaison + *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é. +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. + +--- + +## Pour aller plus loin *(dépôt)* +- Conception + **taxonomie (niveau × modalité)** : `docs/bindings-conception.md` (§11). +- Résolveurs : `roles/resoudre_base`, `roles/resoudre_annuaire` ; registres : `instance/plan/`. +- Toutes les autres unités sont, au fond, des liaisons en action. diff --git a/wiki/Métriques-et-journaux.md b/wiki/Métriques-et-journaux.md new file mode 100644 index 0000000..95773c2 --- /dev/null +++ b/wiki/Métriques-et-journaux.md @@ -0,0 +1,68 @@ +# Métriques & journaux + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. + +--- + +## ① Le concept *(générique)* + +**Observer** un système, c'est trois familles de données : +- **Métriques** : des **nombres dans le temps** (CPU, mémoire, requêtes/s) — des *séries temporelles*. +- **Journaux (logs)** : des **événements textuels** datés (« service démarré », « erreur X »). +- *(Traces : le parcours d'une requête — hors périmètre ici.)* + +Deux **modèles de collecte** opposés, à bien distinguer : +- **Pull / scrape** : le collecteur **va chercher** les métriques chez chaque nœud (qui les *expose*). +- **Push / ship** : chaque nœud **envoie** ses journaux vers un collecteur central. + +Le motif **agent/exporter** : sur chaque machine, un petit agent expose des métriques (*exporter*) +ou expédie des logs (*shipper*). Le serveur central agrège ; un tableau de bord **visualise**. + +--- + +## ② Comment Set-OPS le fait + +| Pièce | Modèle | Rôle | +|---|---|---| +| **Prometheus** (`serveur_prometheus`) | **PULL** | scrape `node_exporter` (installé par `client_metrique`) sur chaque nœud, port `:9100`. | +| **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. + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| Prometheus (pull) | tout Prometheus, VictoriaMetrics, la logique **scrape** | +| Loki (push) | ELK/Elasticsearch, Graylog, la logique **ship** | +| Grafana | Kibana, Datadog, Grafana Cloud | +| exporter/shipper | motif **universel** (node_exporter, Fluent Bit, Vector…) | + +Tu as appris **métriques vs logs, pull vs push, le motif agent** — pas « Prometheus ». + +--- + +## ④ À toi de jouer + +1. **Interroge les métriques** (sur obs-01) — combien de nœuds scrapés, tous **UP** ? + ```bash + curl -s 'http://localhost:9090/api/v1/query?query=up{job="node"}' | python3 -m json.tool | grep -E 'instance|"1"' + ``` +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. +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). + +--- + +## 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**. diff --git a/wiki/Reverse-proxy-et-TLS.md b/wiki/Reverse-proxy-et-TLS.md new file mode 100644 index 0000000..bfcbef4 --- /dev/null +++ b/wiki/Reverse-proxy-et-TLS.md @@ -0,0 +1,69 @@ +# Reverse-proxy & TLS + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. + +--- + +## ① Le concept *(générique)* + +Un **reverse-proxy** est un **point d'entrée unique** devant plusieurs services. Il : +- **route par nom** (`grafana.…` → tel backend, `forge.…` → tel autre) — via l'en-tête `Host` / **SNI** ; +- **termine le TLS** : il porte les certificats, parle HTTPS au client et (souvent) HTTP en interne ; +- centralise journaux, limites de débit, en-têtes de sécurité (et un **WAF** éventuel). + +**Terminaison TLS** = le chiffrement s'arrête au proxy ; derrière, le réseau interne est de confiance. +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 +génère **tout** : + +``` +expose ──> vhost nginx (route par nom) + ──> SAN ajouté au certificat de l'edge (step-ca) + ──> enregistrement A dans PowerDNS + ──> alias plancher /etc/hosts +``` + +Le client parle **HTTPS vérifié** à l'edge ; l'edge relaie en **HTTP** au backend interne (Grafana, +Forgejo, Keycloak…). Une seule ligne déclarative, toute la chaîne câblée. C'est une **liaison** +(*app → domaine*) — voir l'unité *Liaisons*. + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| nginx reverse-proxy | HAProxy · Traefik · Caddy · Apache · Envoy | +| edge + terminaison TLS | tout load-balancer / ingress cloud, un NetScaler ADC | +| routage par SNI/Host | mécanisme **standard** de tout proxy HTTP | + +Tu as appris **le reverse-proxy, le routage par nom, la terminaison TLS** — pas « nginx ». + +--- + +## ④ À toi de jouer + +1. **Route par nom.** Deux noms, un seul edge (`192.168.15.21`) : + ```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 + ``` + 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'`. +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**. + +--- + +## Pour aller plus loin *(dépôt)* +- Rôle : `roles/serveur_nginx` ; les sites se déclarent côté nginx (`serveur_nginx_sites`). +- Machinerie d'exposition : `expositions_des_applications` (dérive vhost + SAN + A + plancher). +- Frontière **publique** (au-delà de l'edge interne) : `docs/` + Étape B (OPNsense). diff --git a/wiki/Supervision-et-impact.md b/wiki/Supervision-et-impact.md new file mode 100644 index 0000000..a712294 --- /dev/null +++ b/wiki/Supervision-et-impact.md @@ -0,0 +1,65 @@ +# Supervision & impact + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. + +--- + +## ① Le concept *(générique)* + +**Observabilité** (métriques/logs) = **passive** : on regarde des données. **Supervision** = +**active** : le système **fait des tests** (« le port 443 répond-il ? le disque est-il plein ? »), +tient un **état** (OK / WARNING / CRITICAL) et **alerte** quand ça se dégrade. + +Distinction utile : Grafana te *montre* des tendances ; un moteur de supervision *décide* qu'un +service est en panne et *prévient*. Complémentaires, pas interchangeables. + +**Modélisation d'impact métier** (BPM) : agréger des checks techniques en **services de haut +niveau**. « Le service *Courriel* est-il sain ? » = (Postfix **ET** Dovecot **ET** l'annuaire). +On raisonne en **impact**, pas en cases isolées. + +--- + +## ② Comment Set-OPS le fait + +La pile Icinga, en trois étages : + +| Étage | Pièce | Rôle | +|---|---|---| +| **Moteur** | `serveur_icinga` (icinga2 + IcingaDB) | exécute les **checks**, tient l'**état**, alerte. | +| **UI** | `serveur_icingaweb2` | l'interface (états, acquittements, downtimes), **au SSO**. | +| **Impact** | module **BPM** | des **processus métier** qui roulent la santé de plusieurs checks en un état. | + +Ce que Grafana ne fait **pas** : le BPM. « Grafana peut-il remplacer le BPM ? » → **non** : l'un +*visualise des mesures*, l'autre *modélise l'impact métier*. On veut **les deux**. + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| Icinga | Nagios · Zabbix · Checkmk · Sensu | +| checks actifs + alerting | modèle **universel** de la supervision | +| BPM / impact | *business service monitoring* (concept répandu) | + +Tu as appris **supervision active vs observabilité passive, l'état, l'alerting, l'impact** — pas +« Icinga ». + +--- + +## ④ À toi de jouer + +1. **Ouvre Icinga Web 2** (`https://icinga.lab.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. +3. **Casse & répare.** Provoque l'échec d'un check (ex. arrête un service surveillé) : l'état passe + **CRITICAL**, et le **processus BPM** qui en dépend **rougit** (l'impact remonte). Répare : tout + reverdit. Tu *sens* la différence entre *mesurer* et *superviser/alerter*. + +--- + +## Pour aller plus loin *(dépôt)* +- Rôles : `roles/serveur_icinga` (moteur), `roles/serveur_icingaweb2` (UI + module BPM). +- SSO devant Icinga Web : `roles/serveur_oauth2_proxy` (passerelle) — unité **Identité & SSO**. +- Complément visuel : unité **Métriques & journaux** (Grafana). diff --git a/wiki/Sécurité-et-durcissement.md b/wiki/Sécurité-et-durcissement.md new file mode 100644 index 0000000..8abba36 --- /dev/null +++ b/wiki/Sécurité-et-durcissement.md @@ -0,0 +1,75 @@ +# Sécurité & durcissement + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. + +--- + +## ① Le concept *(générique)* + +Sécuriser un système, ce sont quelques principes qui se combinent : +- **Défense en profondeur** : plusieurs couches — si l'une cède, les autres tiennent. +- **Moindre privilège** : chacun (compte, service) n'a **que** les droits nécessaires. +- **Réduction de la surface d'attaque** : moins de services exposés = moins de portes. +- **Contrôle d'accès obligatoire (MAC)** : le noyau confine chaque programme (AppArmor/SELinux). +- **Audit** : tracer les événements sensibles pour pouvoir enquêter. +- **Anti-force-brute** : bloquer les tentatives répétées (fail2ban). +- **Pare-feu** : filtrer le trafic réseau. +- **Mises à jour** : combler les failles connues, automatiquement. + +Aucune de ces couches ne suffit seule. Ensemble, elles rendent l'intrusion **coûteuse**. + +--- + +## ② Comment Set-OPS le fait + +Le **durcissement fait partie du socle** — il tourne sur **chaque** nœud (via `serveur_durci`), +pas en option : + +| Couche | Rôle Set-OPS | +|---|---| +| MAC | `apparmor` | +| 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*) | +| Mises à jour | `unattended_upgrades` | +| 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. + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| AppArmor | SELinux · les *security modules* Linux | +| fail2ban / auditd / sysctl | outils **standards** de tout durcissement Linux | +| démarche par couches | **CIS Benchmarks**, ANSSI, guides d'OS — mêmes principes | + +Tu as appris **la défense en profondeur, le moindre privilège, MAC, l'audit** — pas « AppArmor ». + +--- + +## ④ À toi de jouer + +1. **Constate les couches** (sur n'importe quel nœud) : + ```bash + aa-status | head # AppArmor : profils chargés + systemctl is-active auditd fail2ban + sysctl net.ipv4.conf.all.rp_filter # un durcissement noyau parmi d'autres + ``` +2. **Moindre privilège** : `PermitRootLogin` est à `no`, l'accès se fait par le compte `ansible` + + clé SSH. Vérifie : `sshd -T | grep -E 'permitrootlogin|passwordauthentication'`. +3. **Casse & répare (avec prudence, en lab).** Assouplis **un** réglage sysctl, observe, puis + **remets-le**. Tu *sens* que chaque ligne de durcissement ferme une porte précise. + +--- + +## Pour aller plus loin *(dépôt)* +- Rôles du socle durci : `roles/apparmor`, `auditd`, `fail2ban_ssh`, `sysctl_hardening`, + `nftables_baseline`, `ssh_hardening`, `unattended_upgrades`… +- Actions destructives (SSH, pare-feu) exigent une **confirmation explicite** : voir `CLAUDE.md`/`AGENTS.md`. diff --git a/wiki/Virtualisation-et-clonage.md b/wiki/Virtualisation-et-clonage.md new file mode 100644 index 0000000..a0a6121 --- /dev/null +++ b/wiki/Virtualisation-et-clonage.md @@ -0,0 +1,69 @@ +# Virtualisation & clonage + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. + +--- + +## ① Le concept *(générique)* + +La **virtualisation** fait tourner plusieurs **machines virtuelles (VM)** — chacune avec son OS — +sur un seul serveur physique (l'**hyperviseur**). Isolation, densité, souplesse. + +**Image / golden template** : au lieu de réinstaller chaque VM, on prépare **une** image de +référence, propre et durcie, puis on la **clone**. Rapide et **reproductible**. + +**cloud-init** : au premier démarrage d'un clone, il lui donne son **identité initiale** (nom d'hôte, +IP, clé SSH, agrandissement du disque). C'est *l'amorçage*, pas la configuration complète. + +Idée-force : la VM devient **jetable/reconstructible**. Ce qui est précieux, c'est la **donnée** +(voir *Sauvegardes*), pas la machine. + +--- + +## ② 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**. +- 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). + +Séparation nette, à retenir : +``` +Proxmox + cloud-init ──> identité initiale de la VM +Set-OPS + Ansible ──> configuration réelle du serveur +``` +C'est *pour ça* que l'infra est reconstructible : cloner + reconfigurer = quelques minutes. + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| Proxmox (KVM) | VMware · Hyper-V · KVM/libvirt · nuage (EC2, GCE…) | +| golden template | AMI, image cloud, **Packer** | +| cloud-init | **standard** de toutes les images cloud | + +Tu as appris **VM/hyperviseur, image de référence, cloud-init, l'infra jetable** — pas « Proxmox ». + +--- + +## ④ À toi de jouer + +1. **Regarde un clone.** Dans la GUI (`make inventaire-ui`), un serveur *actif* a été **cloné** du + template (bouton « 🖥 Créer la VM »). Son VMID/IP sont **dérivés** de la nomenclature. +2. **Vois l'identité cloud-init.** Sur un nœud : `cloud-init query hostname`, `hostname -f`, et + l'agrandissement du disque racine (`df -h /`). +3. **Sépare les deux couches.** cloud-init a posé *l'identité* ; tout le reste (paquets, services, + durcissement) vient d'**Ansible**. Le template, lui, ne contient **aucune** donnée de clone. +4. **Casse & répare (mentalement + lab).** Supprime un nœud non critique et **reclone-le** depuis le + template, puis redéploie : il revient à l'identique. Tu *sens* que la machine est **reconstructible**. + +--- + +## Pour aller plus loin *(dépôt)* +- Playbooks Proxmox : `playbooks/proxmox/` ; rôle `cloud_init` ; préparation du modèle : `playbooks/modeles_vm/`. +- Golden template = actif central (jamais jetable, cloné pour chaque VM). +- Ce qui est précieux = la **donnée** : unité **Sauvegardes**. diff --git a/wiki/_Sidebar.md b/wiki/_Sidebar.md index ca1b399..2eb0cfa 100644 --- a/wiki/_Sidebar.md +++ b/wiki/_Sidebar.md @@ -4,28 +4,28 @@ **Unités d'apprentissage** *Fondations* -- [Identité & SSO](Identité-et-SSO) ✅ -- [PKI & confiance](PKI-et-confiance) ✅ -- [DNS & résolution de noms](DNS-et-résolution) ✅ +- [Identité & SSO](Identité-et-SSO) +- [PKI & confiance](PKI-et-confiance) +- [DNS & résolution de noms](DNS-et-résolution) *Communication* -- Reverse-proxy & TLS *(à venir)* -- Courriel (SMTP/IMAP) *(à venir)* +- [Reverse-proxy & TLS](Reverse-proxy-et-TLS) +- [Courriel (SMTP/IMAP)](Courriel) *Données* -- Bases de données *(à venir)* -- Cache *(à venir)* -- [Sauvegardes (3-2-1)](Sauvegardes) ✅ +- [Bases de données](Bases-de-données) +- [Cache](Cache) +- [Sauvegardes (3-2-1)](Sauvegardes) *Observabilité* -- Métriques & journaux *(à venir)* -- Supervision & impact *(à venir)* +- [Métriques & journaux](Métriques-et-journaux) +- [Supervision & impact](Supervision-et-impact) *Socle & méthode* -- Virtualisation & clonage *(à venir)* -- Sécurité & durcissement *(à venir)* -- Infra as Code & idempotence *(à venir)* -- Liaisons (bindings) *(à venir)* +- [Virtualisation & clonage](Virtualisation-et-clonage) +- [Sécurité & durcissement](Sécurité-et-durcissement) +- [Infra as Code & idempotence](Infra-as-Code-et-idempotence) +- [Liaisons (bindings)](Liaisons-bindings) **Opérations** - Runbooks *(à venir)*