Carte SD de pi2 (117 Go) à 94 % → DiskPressure → pgbouncer expulsé et non replanifiable (épinglé sur pi2) → crowdsec-lapi en CrashLoop (dial tcp pgbouncer.tools:5432: connection refused, 120 redémarrages) → bouncer Traefik en erreur → routers désactivés → kadans.arcodange.fr et lien.arcodange.fr en 404 (404 page not found, le 404 par défaut de Traefik).
Relevé sur la carte SD : gitea/data/gitea/packages = 58 Go. Détail par paquet (base de Gitea, lecture seule) :
Une version par push de CI depuis le 14/07, soit ~0,9 Go/jour, sans aucune règle de nettoyage (package_cleanup_rule vide).
Ce que fait cette PR
Rôle gitea_packages_retention, joué par 03_cicd.yml sur l'hôte gitea. Il déclare les règles de nettoyage ; c'est Gitea qui les applique chaque nuit (cleanup_packages, active par défaut), sans redémarrage de la forge.
Gitea 1.27 n'a aucune route API pour ces règles (swagger relu). Le rôle fait donc un upsert idempotent dans package_cleanup_rule.
Le schéma est vérifié avant d'écrire : une montée de Gitea qui change la table fait échouer le rôle au lieu d'écrire à côté.
Règle arcodange/container : ^kadans(-[a-z-]+)?/sha256:[0-9a-f]{64}$, avec le nom complet. Elle ne vise que les empreintes sans étiquette des images kadans, au-delà des 20 plus récentes ET de 7 jours.
Aucune étiquette n'est visée. Gitea saute de lui-même latest et tout manifeste encore référencé par un index étiqueté.
postgres-postgis, *-build-cache et cms-deps ne sont pas touchés : leurs étiquettes servent de base à d'autres builds.
GITEA__actions__ARTIFACT_RETENTION_DAYS: 14 (défaut 90 ; 3,3 Go d'artefacts).
GITEA__actions__ZOMBIE_TASK_TIMEOUT: 60m entre dans le dépôt : il n'existait qu'à la main dans data/gitea/conf/app.ini.
⚠ Ces deux variables ne s'appliquent qu'au prochain redéploiement de Gitea (setup/gitea.yml). Ce n'est pas le but de cette PR.
Preuves
SQL joué dans une transaction annulée sur la vraie base :
premier passage ecrite, second inchangee (idempotent) ;
ligne relue : 1|container|20|7|^kadans…$|t|t ;
après rollback, 0 règle.
Simulation en lecture seule de la logique de Gitea (hors références, que Gitea saute en plus) : 774 versions de kadans et 105 de kadans-api seraient retirées.
Étiquettes gardées, toutes :
kadans : latest, main, fix-cmd ;
latest et main de kadans-api, kadans-admin, kadans-jobs, kadans-jobs-analyses, kadans-jobs-vignettes.
L'image déployée (kadans:latest@sha256:860f39…) est l'index latest/main actuel. Ses deux enfants (5818cb…, e01bb5…) sont référencés, donc sautés.
ansible-playbook playbooks/03_cicd.yml --syntax-check : rc=0. --list-tasks montre le play et ses 3 tâches.
Appliquer (humain)
La collection est installée par copie dans ~/.ansible/collections : il faut la réinstaller après la fusion. Ensuite :
uv run ansible-playbook -i inventory playbooks/03_cicd.yml --limit gitea
--limit gitea ne joue que la rétention : le play des runners exclut gitea, donc il ne redéploie rien.
Pour libérer tout de suite sans attendre minuit : Administration du site → Maintenance → Tâches cron → « Cleanup packages » → Lancer.
## Incident (2026-09-18 13 h 11 → 19)
Carte SD de pi2 (117 Go) à **94 %** → `DiskPressure` → pgbouncer expulsé et **non replanifiable** (épinglé sur pi2) → `crowdsec-lapi` en CrashLoop (`dial tcp pgbouncer.tools:5432: connection refused`, 120 redémarrages) → bouncer Traefik en erreur → routers désactivés → **kadans.arcodange.fr et lien.arcodange.fr en 404** (`404 page not found`, le 404 par défaut de Traefik).
Relevé sur la carte SD : `gitea/data/gitea/packages` = **58 Go**. Détail par paquet (base de Gitea, lecture seule) :
| paquet | versions | taille |
|---|---|---|
| arcodange/container/kadans | 935 | 61 Go (blobs partagés comptés par version) |
| arcodange-org/container/cms-deps | 38 | 10 Go |
| arcodange-org/container/cms | 57 | 3,8 Go |
| arcodange/container/dance-lessons-coach-build-cache | 10 | 3,7 Go |
| arcodange/container/kadans-api | 125 | 407 Mo |
Une version par push de CI depuis le 14/07, soit **~0,9 Go/jour**, sans aucune règle de nettoyage (`package_cleanup_rule` vide).
## Ce que fait cette PR
- **Rôle `gitea_packages_retention`**, joué par `03_cicd.yml` sur l'hôte `gitea`. Il **déclare** les règles de nettoyage ; c'est Gitea qui les applique chaque nuit (`cleanup_packages`, active par défaut), **sans redémarrage de la forge**.
- Gitea 1.27 n'a **aucune route API** pour ces règles (swagger relu). Le rôle fait donc un upsert idempotent dans `package_cleanup_rule`.
- Le **schéma est vérifié** avant d'écrire : une montée de Gitea qui change la table fait échouer le rôle au lieu d'écrire à côté.
- **Règle `arcodange/container`** : `^kadans(-[a-z-]+)?/sha256:[0-9a-f]{64}$`, avec le nom complet. Elle ne vise que les empreintes **sans étiquette** des images kadans, au-delà des **20 plus récentes** ET de **7 jours**.
- Aucune étiquette n'est visée. Gitea saute de lui-même `latest` et tout manifeste encore référencé par un index étiqueté.
- `postgres-postgis`, `*-build-cache` et `cms-deps` ne sont **pas touchés** : leurs étiquettes servent de base à d'autres builds.
- **`GITEA__actions__ARTIFACT_RETENTION_DAYS: 14`** (défaut 90 ; 3,3 Go d'artefacts).
- **`GITEA__actions__ZOMBIE_TASK_TIMEOUT: 60m`** entre dans le dépôt : il n'existait qu'à la main dans `data/gitea/conf/app.ini`.
- ⚠ Ces deux variables ne s'appliquent qu'au **prochain redéploiement de Gitea** (`setup/gitea.yml`). Ce n'est pas le but de cette PR.
## Preuves
- **SQL joué dans une transaction annulée** sur la vraie base :
- premier passage `ecrite`, second `inchangee` (idempotent) ;
- ligne relue : `1|container|20|7|^kadans…$|t|t` ;
- après `rollback`, 0 règle.
- **Simulation en lecture seule** de la logique de Gitea (hors références, que Gitea saute en plus) : **774** versions de `kadans` et **105** de `kadans-api` seraient retirées.
- **Étiquettes gardées**, toutes :
- `kadans` : `latest`, `main`, `fix-cmd` ;
- `latest` et `main` de `kadans-api`, `kadans-admin`, `kadans-jobs`, `kadans-jobs-analyses`, `kadans-jobs-vignettes`.
- **L'image déployée** (`kadans:latest@sha256:860f39…`) **est** l'index `latest`/`main` actuel. Ses deux enfants (`5818cb…`, `e01bb5…`) sont référencés, donc sautés.
- `ansible-playbook playbooks/03_cicd.yml --syntax-check` : rc=0. `--list-tasks` montre le play et ses 3 tâches.
## Appliquer (humain)
La collection est installée par **copie** dans `~/.ansible/collections` : il faut la réinstaller après la fusion. Ensuite :
```
uv run ansible-playbook -i inventory playbooks/03_cicd.yml --limit gitea
```
`--limit gitea` ne joue **que** la rétention : le play des runners exclut `gitea`, donc il ne redéploie rien.
**Pour libérer tout de suite** sans attendre minuit : Administration du site → Maintenance → Tâches cron → « Cleanup packages » → Lancer.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Incident 2026-09-18 → 19 : pi2 en DiskPressure (carte SD 117 Go à 94 %),
pgbouncer expulsé et non replanifiable (épinglé sur pi2), la LAPI CrowdSec en
CrashLoop faute de base, le bouncer Traefik en erreur → kadans.arcodange.fr et
lien.arcodange.fr en 404. Le registre gardait 935 versions de arcodange/kadans
(61 Go), une par push de CI depuis le 14/07, ~0,9 Go/jour.
- rôle gitea_packages_retention : déclare les règles de nettoyage dans
package_cleanup_rule (Gitea 1.27 n'a pas de route API pour elles), upsert
idempotent, schéma vérifié avant d'écrire ; Gitea les applique chaque nuit
(cleanup_packages), aucun redémarrage ;
- règle arcodange/container : seules les empreintes sha256: sans étiquette des
images kadans*, au-delà des 20 plus récentes ET de 7 jours ; aucune étiquette
visée (latest, main, fix-cmd restent) ;
- GITEA__actions__ARTIFACT_RETENTION_DAYS=14 (défaut 90, 3,3 Go), et
ZOMBIE_TASK_TIMEOUT=60m versé dans le dépôt (il n'existait qu'à la main
dans app.ini) — ces deux-là au prochain redéploiement de Gitea.
Co-Authored-By: Claude Opus 5 <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Incident (2026-09-18 13 h 11 → 19)
Carte SD de pi2 (117 Go) à 94 % →
DiskPressure→ pgbouncer expulsé et non replanifiable (épinglé sur pi2) →crowdsec-lapien CrashLoop (dial tcp pgbouncer.tools:5432: connection refused, 120 redémarrages) → bouncer Traefik en erreur → routers désactivés → kadans.arcodange.fr et lien.arcodange.fr en 404 (404 page not found, le 404 par défaut de Traefik).Relevé sur la carte SD :
gitea/data/gitea/packages= 58 Go. Détail par paquet (base de Gitea, lecture seule) :Une version par push de CI depuis le 14/07, soit ~0,9 Go/jour, sans aucune règle de nettoyage (
package_cleanup_rulevide).Ce que fait cette PR
gitea_packages_retention, joué par03_cicd.ymlsur l'hôtegitea. Il déclare les règles de nettoyage ; c'est Gitea qui les applique chaque nuit (cleanup_packages, active par défaut), sans redémarrage de la forge.package_cleanup_rule.arcodange/container:^kadans(-[a-z-]+)?/sha256:[0-9a-f]{64}$, avec le nom complet. Elle ne vise que les empreintes sans étiquette des images kadans, au-delà des 20 plus récentes ET de 7 jours.latestet tout manifeste encore référencé par un index étiqueté.postgres-postgis,*-build-cacheetcms-depsne sont pas touchés : leurs étiquettes servent de base à d'autres builds.GITEA__actions__ARTIFACT_RETENTION_DAYS: 14(défaut 90 ; 3,3 Go d'artefacts).GITEA__actions__ZOMBIE_TASK_TIMEOUT: 60mentre dans le dépôt : il n'existait qu'à la main dansdata/gitea/conf/app.ini.setup/gitea.yml). Ce n'est pas le but de cette PR.Preuves
ecrite, secondinchangee(idempotent) ;1|container|20|7|^kadans…$|t|t;rollback, 0 règle.kadanset 105 dekadans-apiseraient retirées.kadans:latest,main,fix-cmd;latestetmaindekadans-api,kadans-admin,kadans-jobs,kadans-jobs-analyses,kadans-jobs-vignettes.kadans:latest@sha256:860f39…) est l'indexlatest/mainactuel. Ses deux enfants (5818cb…,e01bb5…) sont référencés, donc sautés.ansible-playbook playbooks/03_cicd.yml --syntax-check: rc=0.--list-tasksmontre le play et ses 3 tâches.Appliquer (humain)
La collection est installée par copie dans
~/.ansible/collections: il faut la réinstaller après la fusion. Ensuite :--limit giteane joue que la rétention : le play des runners exclutgitea, donc il ne redéploie rien.Pour libérer tout de suite sans attendre minuit : Administration du site → Maintenance → Tâches cron → « Cleanup packages » → Lancer.
🤖 Generated with Claude Code