Paillasse/docs/bilan.md
Adam Belkacemi 7b0a8583eb écrit le bilan de mission et note le maintien temporaire de sudo sans mot de passe (étape 16)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:04:00 +02:00

173 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Bilan de la mission de déploiement — Syllabus
Mission : `docs/prompt-deploiement-paillasse.md`, étapes 1 à 16, exécutée du
2026-10-07 au 2026-10-12 sur la Dedibox `163.172.4.195` (Debian 12, Xeon
D-1531, 32 Go, RAID 1). Le détail de chaque étape (commandes, problèmes,
explications) est dans `docs/journal.md` ; ce document en est la synthèse.
## Ce qui fonctionne, avec la preuve de chaque critère
| Étape | Critère | Preuve (journal) |
|---|---|---|
| 1. Reconnaissance | Inventaire, KVM, version de Kolla justifiée | `docs/inventaire-serveur.md` ; `/dev/kvm` présent ; Kolla 2025.2, seule série maintenue qui supporte Debian 12 (ADR 0001) |
| 2. Durcissement | Clé OK, mot de passe et root refusés, seuls 22/80/443 | `Permission denied (publickey)` pour le mot de passe et pour root ; `nmap` depuis le Mac : 22 seul ouvert (80/443 autorisés, rien n'écoutait encore) |
| 3. Sauvegardes | Une sauvegarde envoyée, un fichier restauré | `quotidienne-20261007.tar.zst.age` présente sur Dedibackup ; `etc/hostname` restauré dans `/tmp` (`sd-124443`) |
| 4. Réseau OpenStack | Après redémarrage : SSH, `dummy0`, veth, Internet | Redémarrage 11:37, SSH 11:39 ; interfaces et IP présentes ; ping 9.9.9.9 et DNS OK ; RAID `[UU]` |
| 5. Kolla | Services OK, aucune API joignable de l'extérieur | `openstack service list` et `compute service list` OK ; `nmap` sur tous les ports OpenStack + 1-1024 : 22 seul |
| 6. Console série | Invite affichée, commande exécutée | Script WebSocket : `localhost login:`, puis `whoami && hostname` → `eleve`, `localhost` |
| 7. Supervision | Une alerte de test reçue par Adam | Alerte injectée dans Alertmanager ; **reçue par Adam sur ntfy** |
| 8. Portail | Pest OK, élève fictif voit son tableau de bord | 11/11 tests ; `lea.m` connectée voit « Salut Léa » |
| 9. Console web | `ip a` dans le navigateur ; un autre élève refusé | Sortie de `ip a` par navigateur → Nginx → proxy Go → Nova ; autre élève : `403` ; écriture du prof ignorée côté serveur |
| 10. Heat, lab 08 | Stack `CREATE_COMPLETE`, terminaux ouverts | Stack créée en 26 s, 3 VM, topologie conforme au `lab.yaml` ; 3 terminaux ouverts ; expiration automatique vérifiée |
| 11. Stock et correction | < 5 s ; correct → réussi ; incorrect → échoué + message | 4,06 s (mesure pessimiste, voir étape 13) ; « Pas encore réussi » 6/10 avec les messages du lab, puis « Réussi » 10/10 ; 3 essais puis échec visible du prof, vérifiés |
| 12. HTTPS | Certificat valide, parcours prof → élève → lab → correction | Let's Encrypt, TLS 1.2/1.3, HSTS, CSP ; parcours en `https`/`wss` : 4,35 s, 6/10 puis 10/10 ; VM sans IP publique ni sortie |
| 13. Capacité et résistance | Chiffres écrits, restauration, retour seul après redémarrage | `docs/capacite.md` ; « RESTAURATION RÉUSSIE » (17 tables identiques) ; tout revenu seul en 11 min, parcours 10/10 ensuite ; ouverture mesurée à 2,80 / 2,85 / 2,85 s |
| 14. Légal et RGPD | Pages en ligne, purge prouvée par Pest | `/legal`, `/confidentialite` en 200, `/statut` → page de statut ; `PurgeRgpdTest` (5 tests) |
| 15. Visio | Prof + 2 élèves ; main levée → parole ; intrus refusé | Test Playwright à 3 navigateurs + intrus : « CRITÈRE DE L’ÉTAPE 15 : RÉUSSI » ; élève sans parole reste en sourdine ; intrus : « Authentication required » |
| 16. Nettoyage | Proposer le retrait de `90-adam` | Proposé avec ses conséquences ; **Adam a choisi de le garder jusqu'à la fin du bloc A** (voir risques) |
**État relevé le 2026-10-12 à la fin de la mission** : 0 unité systemd en
échec ; 53 conteneurs, 0 en mauvaise santé ; Nginx, PHP-FPM, Horizon, proxy
console, correcteur et relais d'alertes actifs ; `https://syllabuslab.fr` et
la page de statut en 200 ; certificat valable jusqu'au 2027-01-10 pour
`syllabuslab.fr`, `www`, `status` et `meet` ; une stack prête dans le stock
du lab 08 ; dernière sauvegarde le 2026-10-12 à 03:16, **test de restauration
automatique du 2026-10-12 à 04:30 réussi** ; 47 tests Pest et 4 tests Go.
## Temps réel passé par étape
Pas de chronométrage pendant la mission : ce sont des **fenêtres entre
commits**, pauses, attentes des réponses d'Adam et nuits comprises. Elles
majorent le temps de travail réel.
| Étape | Fenêtre | Durée | Ce qui a pris du temps |
|---|---|---|---|
| 1 | 2026-10-07, jusqu'à 06:54 | — | Accès SSH (passphrase de la clé) |
| 2 | 06:54 → 10:32 | ≈ 3 h 40 | Deux retours arrière du filet anti-coupure, auto-bannissement fail2ban (post-mortem) |
| 3 | 10:32 → 11:08 | ≈ 35 min | Identifiants Dedibackup corrigés par Adam |
| 4 | 11:08 → 11:40 | ≈ 30 min | Redémarrage avec accord |
| 5 | 11:40 → 15:57 | ≈ 4 h 15 | Deux `deploy` (ProxySQL contre MariaDB), tables IPv6 de Docker |
| 6 | 15:57 → 16:24 | ≈ 30 min | — |
| 7 | 16:24 → 21:20 | ≈ 5 h | Attente de l'adresse de notification, configuration oubliée sur le serveur (2 fois) |
| 8 | 21:20 → 10-08 02:01 | ≈ 4 h 40 | Taille du portail, deux guards, déploiement |
| 9 | 02:01 → 09:35 | ≈ 7 h 30 (nuit comprise) | — |
| 10 | 09:35 → 10:14, puis ADR jusqu'à 21:01 | ≈ 40 min + questions | Trust Heat refusé aux application credentials (ADR 0002) |
| 11 | 10-08 → 21:52 | > 1 h 30 (journal) | Trois défauts des étapes 8 et 9 trouvés par le parcours réel |
| 12 | 10-09 09:38 → 15:04 | ≈ 1 h + DNS de `status` | Faille XSS, `/cours` en 500 |
| 13 | 15:04 → 20:12 | ≈ 5 h | Test de capacité, sauvegarde du portail ajoutée, redémarrage |
| 14 | 20:12 → 22:18 | ≈ 2 h | Pages légales réécrites, polices auto-hébergées, retours d'Adam |
| 15 | 10-12 matin → 12:35 | une demi-journée | Pare-feu entre conteneurs (`br_netfilter`), rôles Jitsi |
| 16 et bilan | 10-12 après-midi | ≈ 1 h | — |
En tout : **six jours calendaires, dont environ quatre jours de travail**.
## Capacité mesurée
- **20 VM `eleve.petit` (1 vCPU, 768 Mo) en même temps**, sessions et stock chaud
compris : par exemple **une classe de 20 élèves** sur un lab à une VM, ou
**6 élèves** sur le lab 08 (3 VM chacun). Limite appliquée par Nova
(`reserved_host_memory_mb = 16500`) et par le portail (`LABS_CAPACITE_VM`).
- Pourquoi 20 : la mémoire est la limite (≈ 600 Mo par VM active, ≈ 250 Mo au
repos), pas le CPU (20 vCPU à 100 % → hôte à 89 %, correction en 0,6 s).
22 avant la visio, 20 depuis qu'1,5 Go est réservé à Jitsi.
- Ouverture d'un lab pris dans le stock : **2,8 s** (critère < 5 s). Lancement
à froid de 20 VM : 53 s en médiane, 75 s au p95. D'où le pré-remplissage
10 minutes avant une séance.
- Visio : non mesurée au-delà de 3 participants. Une classe de 30 en visio
est à tester au pilote (CPU de JVB, débit sortant).
Détails : `docs/capacite.md`.
## Dettes et risques connus
La liste complète, tenue à jour, est dans `docs/dette.md`. Les risques qui
comptent avant une vraie classe :
| Risque | Conséquence | Réponse |
|---|---|---|
| **Copie de la clé age non confirmée** | Si le serveur est perdu, aucune sauvegarde n'est déchiffrable | Adam (voir plus bas) |
| **Base OpenStack non sauvegardée** | Perte du serveur → projet, compte, gabarits et stacks à recréer à la main | `kolla-ansible mariadb_backup` dans la sauvegarde quotidienne |
| **Un seul serveur, pas de sonde extérieure** | Si le serveur tombe, aucune alerte, et la classe s'arrête | Sonde externe (à décider et commander par Adam) ; self-healing ne couvre pas la panne totale |
| **Visio sans TURN sur 443** | Sur un réseau scolaire qui bloque l'UDP : ni son ni image | coturn derrière 443 avant le pilote |
| **`sudo` sans mot de passe pour `adam`** | La clé SSH de Claude Code donne un accès root complet | Gardé par choix d'Adam jusqu'à la fin du bloc A ; retrait ensuite (commande prête ci-dessous) |
| Images Kuma non figée, Jitsi sans procédure de mise à jour | Mise à jour non testée au prochain redéploiement | Variables de version dans les rôles |
| Vitrine : Tailwind par CDN, scripts en ligne, Pyodide depuis jsDelivr | CSP de la vitrine moins stricte que celle de l'application | Compilation par Vite avant ouverture publique |
| Peu de vérifications dans un vrai navigateur | Hors visio et `/ide`, les pages n'ont été vérifiées qu'en HTML | Playwright est maintenant installé : l'étendre aux parcours clés |
| Kolla installé depuis une branche | Pas reproductible à l'identique | À régler lors de la montée de version |
Deux incidents de ma part, déjà traités : un secret d'application credential
de test affiché en clair (credential supprimée aussitôt) ; un déploiement en
échec pris pour un succès (règle depuis : toujours lire `PLAY RECAP`).
## Ce qu'Adam doit faire lui-même
**Secrets et sécurité**
1. **Copier la clé age hors du serveur et le prouver** : procédure dans
`docs/runbooks/sauvegardes.md` (déchiffrer `~/Desktop/test-cle-sauvegardes.age`
avec la copie). Ranger ensuite la copie dans un gestionnaire de mots de passe.
2. **Changer la passphrase SSH** si l'ancienne clé ou la même passphrase sert
ailleurs : elle avait été collée dans la conversation à l'étape 1.
3. **Retirer `/etc/sudoers.d/90-adam` à la fin du bloc A** (la clé de Claude
Code n'a pas de passphrase : ce fichier est la seule barrière entre elle et root). D'abord vérifier son mot de passe dans sa propre session
(`sudo -k && sudo -v`), garder cette session ouverte, puis :
`sudo rm /etc/sudoers.d/90-adam`. Les playbooks se lancent ensuite avec `-K`.
4. Faire tourner le mot de passe du compte `paillasse-service` une fois par an
(`docs/runbooks/compte-service-openstack.md`).
**Comptes et contenus**
5. Créer le premier vrai compte prof (le sien) sur `https://syllabuslab.fr/inscription`
et une vraie classe.
6. Compléter les CGU (article « Disponibilité et responsabilité ») et indiquer
un DPO s'il en désigne un.
7. Trancher les slogans « du lycée au master » et le sort des 32 pages d'aperçu.
8. Dire si l'ancien `storage/logs/laravel.log` peut être supprimé.
**Tests avec un prof**
9. Faire jouer une séance complète par un collègue prof, sur un vrai réseau
d'établissement : inscription des élèves (fiches et code de classe),
séance planifiée, lab 08, correction, visio (son et image à travers le
filtrage de l'établissement, c'est là que l'absence de TURN se verra),
archivage de la classe.
10. Vérifier dans son navigateur : `/ide` (Python et SQL), une console de lab,
la visio sur Chromebook ou vieux PC.
**Décisions et achats (jamais par Claude)**
11. Sonde de supervision hors du serveur (petite VM ailleurs, ou service
externe) et nom DNS `turn.syllabuslab.fr` pour la visio.
## Prochaines étapes du bloc A
### 1. Self-healing et post-mortem (semaine 6 du CLAUDE.md)
- Détecter et relancer : VM figée (l'agent invité ne répond plus → `nova
reboot --hard`), stack du stock en erreur (supprimée et recréée : déjà en
partie fait par le ménage du stock), service arrêté (`Restart=on-failure` sur
toutes les unités maison, à vérifier une par une), conteneur Kolla arrêté.
- Une panne provoquée par cas (`kill -STOP` du QEMU d'une VM du stock, arrêt
du correcteur, arrêt de `nova_compute`), réparée sans intervention, chacune
suivie d'un post-mortem dans `docs/postmortems/`.
- Avant : sauvegarde de la base OpenStack, sinon une réparation ratée n'a pas
de filet.
### 2. Montée de version d'OpenStack (semaine 7)
- Passer de la branche `stable/2025.2` à un tag (version figée), puis préparer
la série suivante. Attention : 2026.1 ne supporte plus Debian 12. Une montée
de version d'OpenStack passe donc d'abord par **Debian 13** (montée de
version de l'OS sur un serveur unique, à préparer avec le mode rescue).
- Runbook : sauvegarde des bases, `kolla-ansible upgrade` en service systemd,
vérifications (`capacite.py` réduit, `parcours-lab.py`, `visio-e2e.mjs`),
retour arrière. Retour d'expérience dans le journal.
### 3. Pilote avec une vraie classe (semaine 8)
- Prérequis : TURN 443, base OpenStack sauvegardée, clé age confirmée, sonde
extérieure, mentions légales complètes, test avec un collègue (point 9).
- Pendant : relever le temps d'ouverture réel (p95), la mémoire, la charge de
la visio, les corrections réussies et échouées, les mains levées.
- Après : retours des élèves et du prof, métriques dans `docs/capacite.md`,
liste des priorités du bloc B.