**Nom du produit : Syllabus** (ancien nom de travail : Paillasse).
- Tout ce que voient les utilisateurs (pages, titres, e-mails, mentions légales) dit **Syllabus**, avec les logos `design/images/logo-syllabus.png` et `design/images/logo-syllabus-icone.png`.
- Les noms techniques internes restent tels quels : le dépôt `Paillasse`, le dossier `paillasse-contenus/`, l'image `paillasse-debian`, le projet OpenStack `paillasse`. Ne les renomme pas.
- Si tu trouves « Paillasse » dans un texte visible, remplace-le par « Syllabus ».
Tu vas déployer **Syllabus** de bout en bout sur un serveur bare metal, jusqu'à une version utilisable par une vraie classe.
**Syllabus** : une plateforme de labs Linux et réseau pour les écoles. Chaque élève a une vraie VM Debian, avec une console dans le navigateur et une correction automatique par scripts. Pas d'IA dans le produit.
- Xeon D-1531 (6 cœurs / 12 threads), **32 Go de RAM**, 2 × 250 Go SSD en RAID 1 (`/` fait 226 Go).
- **Une seule IP publique** : `163.172.4.195`.
- Debian `12`, installé par Adam depuis la console Dedibox.
- Accès SSH : `ssh adam@163.172.4.195`, avec la clé dédiée `~/.ssh/id_ed25519_claude`. Crée l'alias `paillasse` dans `~/.ssh/config`, avec `IdentitiesOnly yes` pour n'utiliser que cette clé.
-`sudo` fonctionne sans mot de passe pour `adam` (fichier `/etc/sudoers.d/90-adam`).
- Sauvegardes : **Dedibackup 100 Go** (FTP, joignable uniquement depuis le serveur). Adam a déposé les identifiants dans `/root/.dedibackup` (`chmod 600`). Ne les affiche jamais.
**Image et labs** : suis la section « Image commune » de `paillasse-contenus/README.md`, et crée ce que demandent les labs 04 et 07 (étape `preparation`, `/opt/labs/07/lycee.sql`, `/opt/paquets/`).
**La forge** : `ssh://git@forge.adam.belkacemi.me:2222/adam/Paillasse.git`. Tu n'y fais que `git push` : aucune connexion SSH à la machine qui l'héberge.
**Le domaine** : pas encore acheté. Fais les étapes 1 à 11 sans domaine (accès par IP ou tunnel SSH). Avant l'étape 12, arrête-toi et demande-moi le domaine.
- toute modification du **réseau**, du **pare-feu** ou de **SSH** ;
- redémarrage du serveur.
4.**Anti-coupure SSH** : avant toute modification du réseau, du pare-feu ou de SSH, programme un retour automatique à l'ancienne configuration dans 5 minutes (par exemple avec `systemd-run --on-active=5min`), puis annule-le une fois l'accès vérifié depuis une **nouvelle** session SSH.
- Suppression automatique 90 jours après l'archivage d'une classe.
7.**Tout est du code** :
- chaque configuration passe par un rôle Ansible idempotent dans `ansible/` ;
- une commande tapée à la main pour explorer doit ensuite être codifiée ;
- relancer un playbook ne doit rien casser.
8.**Vérifie les versions dans la documentation officielle**, jamais de mémoire : Kolla-Ansible, OS supportés, Laravel, PHP, Go. Utilise Context7 ou le web.
9.**Documentation en français** (docs, commentaires, messages de commit).
---
## 2. Méthode de travail
### Pour chaque étape
1. Annonce l'étape et son critère de réussite.
2. Fais le travail.
3.**Vérifie le critère par un test réel** et montre la sortie.
4. Écris dans `docs/journal.md` :
- ce qui a été fait ;
- les commandes clés ;
- les problèmes rencontrés et leur solution ;
- un paragraphe **« Comprendre »** de 3 à 6 phrases, qui explique simplement le pourquoi à Adam.
5.`git commit`, puis `git push`.
6. Passe à l'étape suivante sans attendre, sauf si une règle de la section 1 impose l'accord d'Adam.
### Limite de temps
**1 h 30 maximum par étape.** Si elle est dépassée :
- arrête-toi ;
- écris le blocage dans `docs/journal.md` (symptôme, pistes essayées, hypothèses) ;
- propose 2 options à Adam et attends sa décision.
### Arborescence du dépôt
```
ansible/ inventaire, playbooks, rôles
kolla/ globals.yml, inventaire all-in-one (passwords.yml : chiffré ou hors Git)
openstack/ modèles Heat, flavors, scripts de construction d'images
- pare-feu nftables : seuls **22, 80 et 443** ouverts sur l'IP publique.
- Attention : `kolla-ansible bootstrap-servers` peut désactiver le pare-feu. Prévois-le dès maintenant (réglage Kolla adapté, ou rôle nftables rejoué après Kolla).
**Critère :**
- connexion par clé OK ;
- connexion par mot de passe refusée, root refusé ;
- Identifiants dans `/root/.dedibackup` (variables `DEDIBACKUP_HOST`, `DEDIBACKUP_USER`, `DEDIBACKUP_PASS`). La clé privée age ne quitte jamais le serveur : rappelle-moi d'en garder une copie hors du serveur.
### Étape 4 : Réseau pour OpenStack (accord d'Adam obligatoire)
L'objectif est de ne jamais mettre Neutron sur l'interface publique.
- Crée une interface `dummy0` avec une IP privée (par exemple `10.10.0.1/24`). Elle servira à `network_interface` et `kolla_internal_vip_address` (Kolla sans HAProxy).
- Crée une paire veth. `neutron_external_interface` utilise un bout de la paire. L'autre bout porte la passerelle du réseau externe OpenStack, avec un NAT masquerade nftables.
- Rends le tout persistant avec systemd-networkd et le rôle Ansible `reseau-openstack`.
- Applique la règle anti-coupure SSH, puis **redémarre, avec l'accord d'Adam**.
**Critère :** après redémarrage, le SSH répond, `dummy0` et la paire veth sont présents, et Internet reste joignable depuis le serveur.
### Étape 5 : Kolla-Ansible tout-en-un
- Dans un venv Python : la version de Kolla-Ansible choisie à l'étape 1, puis `kolla-ansible install-deps`.
- Dans `kolla/globals.yml` (**vérifie les noms exacts dans la doc de la version**), les idées sont :
2. Construis l'image `paillasse-debian` avec `virt-customize`, à partir de l'image cloud Debian 12 officielle, en suivant la section « Image commune » de `paillasse-contenus/README.md`.
5. Démarre une VM et récupère l'adresse de sa console série avec l'API Nova `remote-consoles` (protocole `serial`).
**Critère :** un petit script (websocat ou Python) connecté au WebSocket de la console série affiche l'invite de connexion, et une commande tapée s'exécute.
### Étape 7 : Supervision et alertes
- Prometheus, node_exporter et Grafana : ceux de Kolla si possible.
- Uptime Kuma en conteneur Docker, écoutant sur `127.0.0.1`.
- Alertes : disque > 80 %, RAM > 90 %, service OpenStack arrêté, dernière sauvegarde de plus de 26 h, serveur injoignable.
- **Laravel avec Blade et Vite**, dans `portail/`.
- **Design** :
- le dossier `design/` est la référence exacte. Il contient déjà des vues Blade (`design/resources/views/`) et des routes (`design/routes/web.php`) : reprends-les **telles quelles** ;
- le JS existant (`design/js/`, dont `paillasse-terminal.js`) et le CSS (`design/css/`) sont conservés ;
- compare chaque page avec une capture Playwright de `design/`, et corrige jusqu'à ce qu'elles soient identiques ;
- si `design/` est absent, arrête-toi et demande-le-moi.
### Étape 15 : Visio de classe (seulement après validation des étapes 1 à 11)
- Jitsi auto-hébergé, derrière Nginx.
- Accès par **jeton JWT** émis par Laravel : seuls les élèves de la classe entrent, avec un nom non modifiable.
- Le prof est seul modérateur. Tout le monde arrive micro et caméra coupés, et seul le prof donne la parole.
- Main levée synchronisée avec celle de l'app, salle d'attente, chat désactivé par défaut.
- Reprends exactement `design/apercu-visio.html` et `design/resources/views/visio.blade.php`.
**Critère :** un prof et deux élèves fictifs rejoignent la visio ; un élève lève la main, le prof lui donne la parole, et un intrus sans jeton ne peut pas entrer.