docs: backup restic remis en place, cron Nextcloud réparé, plan de migration

- Backup : l'ancien Duplicity (2020) ne tournait plus ; remplacé par restic
  vers OVH Swift (script versionné dans backup/restic-backup.sh, cron 03:30),
  premier snapshot complet et restauration testés le 2026-10-03
- Nextcloud : cron en panne depuis le 2026-08-09 (DNS overlay perdu) corrigé ;
  rétention corbeille/versions à "auto, 30"
- Incident Gitea : vérification de non-réinfection, mouvement latéral et
  intégrité de l'hôte (rien trouvé)
- plan-migration.md : état des lieux, décisions à prendre, phases

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Pierre Martin
2026-10-03 13:32:31 +02:00
co-authored by Claude Opus 5.5
parent 7e5f15577a
commit f974203973
4 changed files with 349 additions and 2 deletions
+22
View File
@@ -108,6 +108,28 @@ Endpoints utiles :
- **Variables d'env CapRover de l'app `gitea`** (vérifié via `docker service inspect srv-captain--gitea`) : `DB_HOST`, `DB_PASSWD`, `DB_TYPE`, `DB_USER`, `RUN_MODE`. ⚠️ Aucune n'est au format `GITEA__<section>__<clé>` attendu par l'image officielle pour réinjecter dans `app.ini` au démarrage — elles sont donc **inertes** pour Gitea (c'est `app.ini` dans le volume qui fait foi). En cas de rotation de secret (mot de passe DB notamment), mettre à jour `app.ini` + redémarrer suffit fonctionnellement ; penser quand même à resynchroniser `DB_PASSWD` côté CapRover pour ne pas laisser une copie obsolète du secret.
- **⚠️ Voir `incidents/2026-09-14-gitea-cryptominer.md`** : l'API interne Gitea (`/api/internal/manager/add-logger`) a été exploitée pour injecter des `packObjectsHook` malveillants dans `.gitconfig`. Toujours vérifier ce fichier ne contient pas d'entrées `[uploadpack] packObjectsHook` inattendues.
## Backup
- **Système actuel (depuis le 2026-10-03)** : restic 0.19.1 (`/usr/local/bin/restic`) → OVH Swift, conteneur `sans-pub-restic` (même projet OVH que l'ancien backup, région GRA)
- Script : `/root/restic/backup.sh` (source versionnée : `backup/restic-backup.sh` dans ce dépôt), cron `/etc/cron.d/restic-backup` à 03:30
- Config : `/root/restic/env` (identifiants OVH) + `/root/restic/password` (mot de passe du dépôt) — `600`, **jamais afficher**. Le mot de passe doit aussi être dans Vaultwarden, sinon le backup est inutilisable si le serveur disparaît
- Contenu : dumps SQL de toutes les bases (`/var/backups/sans-pub-db/`, détection auto MySQL/MariaDB/PostgreSQL), volumes Docker (hors registres, previews et logs Nextcloud), `/captain/data` (hors registry), `/home/cloud/apps_data`, `/root/backup`, `/etc`. Les fichiers bruts d'une base sont exclus **seulement si son dump a réussi** (sinon sauvegardés en repli)
- Particularités des bases : `limesurvey-mariadb-db` n'accepte root qu'en TCP (`-h127.0.0.1`, le mot de passe de `root@localhost` est différent) ; `writefreely-db` a une table `mysql.proc` incompatible (dump sans `--routines`). Le script essaie automatiquement ces variantes
- Premier snapshot complet : 2026-10-03 (~53 Gio, ~45 Gio stockés) ; restauration testée (`restic dump` + comparaison SHA256)
- Rétention : 7 quotidiens, 4 hebdos, 6 mensuels ; `prune` + `check` (5 % des données) le dimanche
- Log : `/var/log/restic-backup.log` ; mail à `pierre@sans.pub` en cas d'échec (via SMTP de poste.io avec `curl -k` car son certificat a expiré, donc **pas d'alerte si le serveur entier tombe**)
- Consulter : `ssh sans.pub 'sudo bash -c ". /root/restic/env && restic snapshots"'`
- **Ancien système (arrêté)** : Duplicity (`tecnativa/duplicity`) configuré dans `/root/backup/` sur le serveur (`docker-compose.yaml` + `config.json`, nov. 2020) → OVH Public Cloud Archive `backup-principal` (données) + Swift `backup-principal-metadata` (manifestes), région GRA. Conteneur et image absents du serveur au 2026-10-03 : plus aucun backup automatique. Ces deux fichiers contiennent des secrets (identifiants OVH, passphrase de chiffrement) — ne jamais les afficher ni les versionner.
- Suites (Vaultwarden, alerte externe, rotation des identifiants OVH) : voir `plan-migration.md`, phase 0.
## Nextcloud — détails techniques
- **Cron** : service CapRover `nextcloud-cron` (image perso `img-captain-nextcloud-cron:4`, PHP 8.1, mai 2023 — Nextcloud lui-même tourne en PHP 8.3) qui monte le même volume `nextcloud-data` et lance `cron.php` toutes les 5 min. Mode `backgroundjobs_mode = cron`.
- Vérifier : `occ config:app:get core lastcron` (timestamp Unix, doit dater de < 10 min)
- ⚠️ Panne du 2026-08-09 au 2026-10-03 : le conteneur, non redémarré lors du redémarrage Docker du 2026-02-16, avait perdu la résolution DNS du réseau overlay (`getaddrinfo for srv-captain--nextcloud-db failed`). Corrigé par redémarrage via `appDefinitions/update` (définition complète renvoyée). Si ça se reproduit : même remède.
- **Rétention** (depuis le 2026-10-03) : `trashbin_retention_obligation` et `versions_retention_obligation` = `auto, 30` (suppression au plus tard après 30 jours ; avant, `auto` sans quota = jamais supprimé → corbeille de 28 Go)
- `occ` : `docker exec -u www-data <conteneur srv-captain--nextcloud.1> php occ ...`
## Suivi des tâches
Voir `todo.txt` (format todo.txt standard)