Files
homelab-infra/ops/restore-tests/immich-runbook.md
T

129 lines
5.9 KiB
Markdown

# Immich Restore Runbook
## Status
Skript und Test-Compose sind vorbereitet. **Erster echter Lauf steht noch aus.**
Vor dem ersten Lauf muss Operator entscheiden:
- ist genug freier Platz unter `/mnt/user/backups/restore-lab/immich` vorhanden (Dump + Test-Postgres-Datadir + Upload-Dummy)?
- ist genug freier RAM/CPU verfuegbar, um Immich-Server + Test-Postgres parallel zur produktiven Last laufen zu lassen?
- soll der Lauf zuerst mit `--what-if` ausgefuehrt werden, dann mit `--keep-data` zur Zeitmessung?
## Vorbedingungen
- Borg-Quelle ist verfuegbar
- Borg-UI laeuft (`docker ps | grep borg-ui`)
- Borg-Passphrase-Datei vorhanden: `/mnt/user/appdata/secrets/borg_repo_passphrase.txt`
- aktueller Dump `immich.dump` ist Teil des letzten Borg-Archivs (siehe `pre-backup-dumps.sh`)
- Testpfade unter `/mnt/user/backups/restore-lab/` und `/mnt/user/backups/restore-reports/` sind freigegeben
- produktiver Immich-Stack laeuft (oder ist bewusst aus); der Test ist davon unabhaengig
## Bestaetigter Host-Stand (Soll)
- produktiver Immich-Server: `immich_server` Container mit Image `ghcr.io/immich-app/immich-server:release@sha256:c15bff75068effb03f4355997d03dc7e0fc58720c2b54ad6f7f10d1bc57efaa5`
- produktive Postgres: `immich_postgres` mit `tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52`
- produktive Foto-Pfade: `/mnt/user/photos/immich`, `/mnt/user/photos/family_archive`
- aktueller Dump-Pfad: `/mnt/user/backups/borg/dumps/latest/immich.dump`
- Secret: `/mnt/user/appdata/secrets/immich_postgres_password.txt` (wird vom Test **nicht** gebraucht; Test nutzt eigenes Test-Passwort)
## Bestaetigter Teststand
- noch kein echter Mini-Restore gelaufen
- Skript-Set vorbereitet:
- `ops/restore-tests/immich-compose.test.yml`
- `ops/restore-tests/immich-restore-test.sh`
- `ops/restore-tests/immich-restore-test.ps1` (Scaffold, kein Live-Run)
- `ops/restore-tests/immich-plan.md`
- `ops/restore-tests/immich-runbook.md`
## Erster Lauf - trockene Variante
```bash
bash /mnt/user/services/homelab-infra/ops/restore-tests/immich-restore-test.sh --what-if
```
Erwartete Ausgabe: nur Plan-Output, kein Docker-Start, kein Borg-Extract.
## Erster Lauf - echter Test (Operator-freigegeben)
```bash
# Optional: laufende Borg-Jobs pruefen, damit Borg-UI nicht parallel ausgelastet ist
docker exec borg-ui sqlite3 /data/borg.db \
"select status, archive_name, datetime(updated_at,'unixepoch') from backup_jobs order by id desc limit 5;"
# Lauf mit Datenerhalt fuer Zeitmessung
bash /mnt/user/services/homelab-infra/ops/restore-tests/immich-restore-test.sh --keep-data
```
Bei erfolgreichem Lauf:
- Report unter `/mnt/user/backups/restore-reports/immich-YYYY-MM-DD.md`
- Test-Container `restoretest-immich-*` sind nach Lauf bereits `down`
- Restore-Lab-Daten bleiben mit `--keep-data` erhalten; ohne Flag werden sie geloescht
## Smoke-Test-Pruefungen
Minimal erwartet im Report:
- `HTTP status after redirect: 200|302|303`
- `Login page marker: ok`
- `Asset count in test DB`: Zahl, oder `n/a` bei Schema-Drift
- `User count in test DB`: Zahl, oder `n/a` bei Schema-Drift
- Pre-Dump-Hook-Kette (`pg_dump -Fc`) und Restore-Kette (`pg_restore -Fc`) sind kompatibel
- pgvecto-rs Extension ist im Restore-DB sichtbar
Manuelle Folgepruefung (optional):
Das Skript stoppt die Test-Container auch bei `--keep-data`; dieses Flag erhaelt nur die Restore-Lab-Daten. Fuer eine manuelle Folgepruefung nach einem erfolgreichen `--keep-data`-Lauf die Testinstanz kurz wieder hochfahren und danach wieder stoppen:
```bash
docker compose -f /mnt/user/services/homelab-infra/ops/restore-tests/immich-compose.test.yml up -d \
restoretest-immich-postgres restoretest-immich-redis restoretest-immich-server
docker exec restoretest-immich-postgres psql -U immich -d immich -c "\dx"
docker exec restoretest-immich-postgres psql -U immich -d immich -tAc "select count(*) from assets;"
docker logs --tail 100 restoretest-immich-server
docker compose -f /mnt/user/services/homelab-infra/ops/restore-tests/immich-compose.test.yml down
```
## Cleanup nach Lauf ohne `--keep-data`
Das Skript bereinigt:
- Test-Container via `docker compose down`
- Restore-Lab unter `/mnt/user/backups/restore-lab/immich`
- Extract-Cache unter `/mnt/user/appdata/borg-ui/restore/immich-extract`
**Vorsicht:** `rm -rf` arbeitet ausschliesslich auf dem festen Restore-Lab-Pfad. Produktive Immich-Pfade unter `/mnt/user/photos/*` werden vom Skript niemals beschrieben.
## Fehlerfaelle
| Symptom | Ursache | Massnahme |
|---|---|---|
| `pg_restore: error: could not find extension ... vectors` | Test-Postgres-Image nicht pgvecto-rs | Compose-Pin im Test-Compose pruefen |
| HTTP-Timeout nach 120 s | Immich-Migrations laufen noch | Wartezeit im Skript erhoehen oder Logs pruefen |
| `pg_isready` nie healthy | Test-Postgres bricht beim Start ab (Datadir-Konflikt) | Restore-Lab vor Lauf vollstaendig leer; `docker logs restoretest-immich-postgres` |
| Body matcht keine Marker | Immich UI hat sich versioniert; Marker-Liste anpassen | Marker im Skript erweitern (`grep -qiE`) |
| Disk-Space-Mangel | Dump + Postgres-Datadir + Extract-Cache | mehr Platz freigeben oder Lauf abbrechen |
## Schedule-Eintrag (geplant, noch nicht aktiv)
Aktuell in `ops/restore-tests/schedule.md` nur als "spaeter, eigener Sprint" gelistet.
Nach erstem erfolgreichen Lauf vorschlagen:
- quartalsweise (`0 9 1 1,4,7,10 *` o. ae.)
- ohne `--keep-data`
- Report wird automatisch von `monthly-random-restore.sh` mit eingelesen, sobald Immich dort eintragbar ist
## Festgelegte Entscheidungen
- Immich-Restore-Test nutzt isoliertes Test-Postgres mit gleichem Image wie Produktion.
- ML-Container wird im Smoke-Test **nicht** mitgestartet.
- Produktive Foto-Pfade werden **nicht** in den Test gemountet.
- Test-Daten werden nach erfolgreichem Lauf geloescht (`--keep-data` ueberschreibt das).
- Borg-Passphrase wird aus Host-Secret-Datei gelesen und nirgendwo geloggt.
- `ntfy` wird im ersten echten Lauf nicht eingebunden.