6.2 KiB
Immich Restore Runbook
Status
Skript und Test-Compose sind vorbereitet. Erstlauf 2026-05-27 erfolgreich (SUCCESS, HTTP 200, 11977 Assets im Test-DB-Check). Report: /mnt/user/backups/restore-reports/immich-2026-05-27.md. Folgelaeufe je Quartal gemaess docs/RESTORE_DRILL_ROUTINE.md (Q2 = Immich).
Vor dem ersten Lauf muss Operator entscheiden:
- ist genug freier Platz unter
/mnt/user/backups/restore-lab/immichvorhanden (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-ifausgefuehrt werden, dann mit--keep-datazur 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.dumpist Teil des letzten Borg-Archivs (siehepre-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_serverContainer mit Imageghcr.io/immich-app/immich-server:release@sha256:c15bff75068effb03f4355997d03dc7e0fc58720c2b54ad6f7f10d1bc57efaa5 - produktive Postgres:
immich_postgresmitghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23 - 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.ymlops/restore-tests/immich-restore-test.shops/restore-tests/immich-restore-test.ps1(Scaffold, kein Live-Run)ops/restore-tests/immich-plan.mdops/restore-tests/immich-runbook.md
Erster Lauf - trockene Variante
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)
# 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 bereitsdown - Restore-Lab-Daten bleiben mit
--keep-dataerhalten; ohne Flag werden sie geloescht
Smoke-Test-Pruefungen
Minimal erwartet im Report:
HTTP status after redirect: 200|302|303Login page marker: okAsset count in test DB: Zahl, odern/abei Schema-DriftUser count in test DB: Zahl, odern/abei Schema-Drift- Pre-Dump-Hook-Kette (
pg_dump -Fc) und Restore-Kette (pg_restore -Fc) sind kompatibel - VectorChord-/pgvector-Extensions sind in der 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:
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 asset;"
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 ... vector/vchord |
Test-Postgres-Image passt nicht zur Produktion | 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.shmit 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-dataueberschreibt das). - Borg-Passphrase wird aus Host-Secret-Datei gelesen und nirgendwo geloggt.
ntfywird im ersten echten Lauf nicht eingebunden.