# Immich Restore Test Plan ## Ziel Nachweisen, dass `immich.dump` aus dem produktiven Borg-Archiv in einer isolierten Testumgebung wieder einspielbar ist und Immich-Server damit anlaufen, einloggen und Asset-Metadaten anzeigen kann. Bewusst **nicht** Teil dieses Tests: - Wiederherstellung produktiver Foto-Dateien aus `/mnt/user/photos/immich` und `/mnt/user/photos/family_archive`. Der Smoke-Test bleibt DB-/UI-zentriert. - Machine-Learning-Container. Spart Image-Pull-Zeit und Resource-Last; ML-Features sind im Smoke-Test nicht erforderlich. - Echte Browser-Login-Sequenz. Smoke-Test prueft nur, dass die Login-Seite ausgeliefert wird und die DB-Tabellen `asset` und `"user"` lesbar sind. ## Quelle - Backup-Quelle: produktives Borg-Archiv (`hetzner_borg_appdata_critical` oder lokales Mirror) - fachlich relevanter Dump im Archiv: - `local/borg-dumps/latest/immich.dump` - Erzeuger: `ops/borg-ui/scripts/pre-backup-dumps.sh`, Funktion `dump_pg_db immich_postgres ... immich immich` mit `pg_dump -Fc` - produktive Foto-Pfade werden im Smoke-Test bewusst **nicht** angefasst ## Test-Ziel - Restore-Lab: `/mnt/user/backups/restore-lab/immich` - Testdatenpfade: - `/mnt/user/backups/restore-lab/immich/postgres` (Test-Postgres-Datadir) - `/mnt/user/backups/restore-lab/immich/upload` (leeres Upload-Volume, Immich-Server braucht den Pfad nur als Mountpoint) - `/mnt/user/backups/restore-lab/immich/dumps/latest/immich.dump` (extrahierter Dump) - Testcontainer: - `restoretest-immich-server` - `restoretest-immich-postgres` (`ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0` - identisch zur Produktion, weil VectorChord-Backups ein Image mit VectorChord brauchen) - `restoretest-immich-redis` (`redis:8.8.0-alpine`, rebuildbar) - Testport Web: `127.0.0.1:12283:2283` - Report-Ziel: `/mnt/user/backups/restore-reports/immich-YYYY-MM-DD.md` ## Schutzregeln - produktive Pfade `/mnt/user/photos/immich` und `/mnt/user/photos/family_archive` werden **nicht** in den Test-Container gemountet - produktive Domain `immich.kaleschke.info` wird **nicht** uebernommen - keine Traefik-Labels fuer die Testinstanz - keine produktive `immich_postgres`-/`immich_redis`-Instanz fuer den Test verwenden - ML-Container bleibt weg - Testcontainer publishen nur auf `127.0.0.1`, nicht auf LAN- oder Tailscale-Interface - Borg-Passphrase wird aus `/mnt/user/appdata/secrets/borg_repo_passphrase.txt` gelesen und niemals in Logs, Reports oder Doku geschrieben ## Geplanter Ablauf 1. Restore-Ziel unter `/mnt/user/backups/restore-lab/immich` vorbereiten (postgres, upload, dumps/latest) 2. `local/borg-dumps/latest/immich.dump` aus dem aktuellsten Borg-Archiv extrahieren 3. Test-Postgres (Immich-Postgres mit VectorChord) und Test-Redis mit `ops/restore-tests/immich-compose.test.yml` starten 4. `immich.dump` in Test-Postgres importieren (`pg_restore -Fc --clean --if-exists --no-owner --no-privileges`) 5. Testinstanz `restoretest-immich-server` starten 6. lokalen Smoke-Test gegen `http://127.0.0.1:12283` ausfuehren und Asset/User-Count aus DB lesen 7. Report unter `/mnt/user/backups/restore-reports/immich-YYYY-MM-DD.md` schreiben 8. Testcontainer stoppen und Restore-Lab bereinigen ## Smoke-Test Minimal erfolgreich: - Test-Postgres startet `healthy` - `pg_restore -Fc` laeuft ohne Fehler durch - Immich-Server liefert HTTP `200`, `302` oder `303` auf `/` - Response enthaelt mindestens einen der Marker `Immich`, `Login`, `Signin` - `select count(*) from asset;` und `select count(*) from "user";` sind lesbar Optional spaeter: - Echte Login-Form via API ansprechen - VectorChord-/pgvector-Extensions explizit per `\dx` pruefen - Test mit gemountetem **read-only** Foto-Sample-Pfad und Thumbnail-Rendering - Test inkl. ML-Container, sobald genug Test-Ressourcen verfuegbar ## Bekannte Komplikationen | Risiko | Beschreibung | Mitigation | |---|---|---| | Dump-Groesse unbekannt | `pg_dump -Fc` der Immich-DB kann je nach Asset-/Face-Tabellen mehrere GB sein | Erster Lauf bewusst mit `--what-if`, anschliessend Operator-Test mit Zeitmessung | | `pg_restore`-Dauer unbekannt | Index-/Constraint-Aufbau und VectorChord-Index-Build koennen lange dauern | Test-Postgres mit Health-Polling startet; Lauf nicht abbrechen ohne `pg_restore`-Exit | | VectorChord-/pgvector-Extension-Mismatch | Wenn das Test-Postgres-Image nicht zu Produktion passt, kann der Restore oder Immich-Start fehlschlagen | Compose pinnt denselben Digest wie `apps/immich/docker-compose.yml` | | Immich-Server-Migrations beim Start | Immich fuehrt beim ersten Start DB-Migrations aus; das kann nach Restore noch laufen, bevor Web-UI antwortet | Smoke-Test pollt HTTP bis zu 120 s, bevor er als Fehler markiert | | Asset-Files fehlen | Der Test mountet kein Foto-Volume; Immich zeigt "missing" auf Asset-Detail-Seiten | Smoke-Test prueft nur Login-Page und DB-Counts, nicht Asset-Rendering | | ML-Endpoint unreachable | Immich-Server kann ML-Endpoint nicht erreichen | `IMMICH_MACHINE_LEARNING_URL` zeigt bewusst auf einen nicht erreichbaren Hostnamen; Login bleibt funktional, ML-Features bleiben deaktiviert | ## Noch offen vor dem ersten echten Lauf - Dump-Groesse `immich.dump` auf dem Host bestimmen (`ls -lh /mnt/user/backups/borg/dumps/latest/immich.dump`) - Erwartete Restore-Dauer durch ersten Lauf mit `--keep-data` messen - Pruefen, ob die Immich-Tabellen `assets`/`users` im aktuellen Schema noch existieren (Schema-Drift bei Major-Update wuerde die Asset-Count-Query brechen, das Skript faengt das tolerant ab) - Schedule-Eintrag in `ops/restore-tests/schedule.md`: aktuell ist Immich nur als "spaeter, eigener Sprint" gefuehrt. Erst nach erstem erfolgreichen Lauf in Schedule aufnehmen, z. B. quartalsweise.