ajoute le stockage S3 des devoirs maison (bloc B, dernier chantier)

Dépôt de fichier en plus du texte libre pour les devoirs maison, stocké
sur Hetzner Object Storage (jamais sur le disque du serveur), masqué
côté élève tant que le bucket n'est pas configuré. Purge RGPD étendue
pour supprimer aussi les fichiers d'Object Storage. Ansible lit les
identifiants depuis un fichier que seul Adam peut créer sur le serveur
(runbook docs/runbooks/stockage-s3.md) ; le bloc B du CLAUDE.md est
maintenant complet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Adam Belkacemi 2026-10-14 09:52:15 +02:00
parent 79d4a06fdf
commit 6ea7a1cc16
16 changed files with 1022 additions and 59 deletions

View file

@ -0,0 +1,83 @@
# Runbook — Stockage S3 des devoirs maison
Les fichiers que les élèves joignent à leurs devoirs maison sont stockés sur
Hetzner Object Storage (S3-compatible), jamais sur le disque du serveur
(`app/Services/Stockage/StockageTravauxEleves.php`). Tant que le bucket n'est
pas configuré, le bouton de dépôt de fichier reste simplement masqué côté
élève (texte libre toujours disponible) — rien ne casse.
Claude ne peut ni créer le bucket ni générer les clés (CLAUDE.md : commandes
et dépenses jamais par Claude). Cette étape est entièrement à faire par Adam.
## 1. Créer le bucket (console Hetzner)
Dans le **projet Hetzner dédié à Paillasse** (jamais `tripoli-cloud`) :
1. Object Storage → créer un bucket, région au choix (ex. `fsn1`).
2. Activer le versioning sur le bucket (un fichier écrasé reste récupérable
quelques temps).
3. Générer une paire de clés d'accès **scopée à ce bucket seulement** (pas
une clé avec accès à tout le compte).
Vérifier les noms exacts des options dans la console/doc Hetzner au moment de
le faire : l'interface peut avoir changé depuis l'écriture de ce runbook.
## 2. Créer le fichier de secrets sur le serveur
Sur `163.172.4.195`, jamais dans Git, jamais collé dans une conversation avec
Claude :
```
ssh paillasse
sudo mkdir -p /etc/syllabus
sudo tee /etc/syllabus/s3-paillasse.yaml > /dev/null <<'EOF'
access_key: "COLLER_LA_CLE_ICI"
secret_key: "COLLER_LE_SECRET_ICI"
bucket: "nom-du-bucket"
region: "fsn1"
endpoint: "https://fsn1.your-objectstorage.com"
EOF
sudo chmod 600 /etc/syllabus/s3-paillasse.yaml
sudo chown root:root /etc/syllabus/s3-paillasse.yaml
```
Adapter `region`/`endpoint` à ce que la console Hetzner affiche pour le
bucket créé.
## 3. Déployer
Depuis le Mac :
```
cd ansible && script -q /dev/null ansible-playbook portail.yml -i inventory.ini
```
Le rôle `portail` (`roles/portail/tasks/03-code.yml`) lit ce fichier s'il
existe, écrit `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`/`AWS_BUCKET`/
`AWS_DEFAULT_REGION`/`AWS_ENDPOINT` dans `.env` et redémarre Horizon. S'il
n'existe pas encore, ce bloc ne fait rien.
## 4. Vérifier
```
cd /var/www/portail
sudo -u www-data HOME=/tmp php8.3 artisan tinker \
--execute="echo App\Services\Stockage\StockageTravauxEleves::disponible() ? 'ok' : 'non configure';"
```
Puis, en élève de test, ouvrir un devoir : le champ « Joindre un fichier »
doit apparaître. Déposer un petit fichier, vérifier côté prof qu'il apparaît
et se télécharge. Supprimer le compte de test ensuite.
## RGPD
Un fichier déposé est supprimé d'Object Storage dès que la classe qui le
contient est purgée (`classes:purger-archivees`, 90 jours après archivage) —
voir `app/Console/Commands/PurgerClassesArchivees.php`.
## Rotation des clés
Même logique que pour le compte de service OpenStack
([runbook dédié](compte-service-openstack.md)) : régénérer les clés dans la
console Hetzner, remplacer `access_key`/`secret_key` dans
`/etc/syllabus/s3-paillasse.yaml`, redéployer (étape 3).