docs: consolidate restore documentation into ops/restore-tests

- merge RESTORE_HANDBOOK.md into ops/restore-tests/README.md (single
  operations doc; restore status lives only in RESTORE_MATRIX maturity
  table)
- RESTORE_MATRIX.md: extract embedded runbook drafts (261 -> 141 lines);
  unraid-flash and tailscale stubs become ops/restore-tests runbooks,
  adguard/redis checklists superseded by validated scripts
- delete six historical pre-first-run *-plan.md files (runbook + script
  are the source of truth since the validated first runs)
- SERVICES_RECOVERY: drop completed task table; DISASTER_RECOVERY:
  point related docs and section 11 to MASTER_TODO/schedule

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 07:11:16 +02:00
parent 489a429316
commit 1fcdb68221
16 changed files with 231 additions and 978 deletions
+63 -87
View File
@@ -1,109 +1,85 @@
# Restore Tests
# Restore-Tests - Betrieb und Werkzeuge
Kontrollierte Restore-Tests fuer `homelab-infra`.
Typ: Runbook/Tool-Doku · Stand: 2026-06-11 · Status: aktiv
Ziel:
Kontrollierte Restore-Tests fuer `homelab-infra`. Dieses Dokument ist das
**einzige** Betriebsdokument fuer Restore-Tests (das fruehere
`docs/RESTORE_HANDBOOK.md` ist hierin aufgegangen). Verwandt:
- Backups durch echte Test-Restores verifizieren
- produktive Pfade nicht beschreiben
- Testlaeufe spaeter weitgehend automatisieren
- `docs/RESTORE_MATRIX.md` - Restore-Quellen, Secrets, Smoke-Tests und **Test-Reifegrad je Dienst** (einziger Status-Ort)
- `docs/DISASTER_RECOVERY.md` - echter Wiederanlauf
- `schedule.md` - Kadenz, Cron-Ausdruecke und Shell-Guards
- `unraid-user-scripts.md` - Unraid-User-Script-Vorlagen fuer die Host-Jobs
## Grundregeln
- Restore-Quelle bleibt im Backup-Bereich, z. B. `/mnt/user/backups/borg`
- Test-Restores laufen nur in `/mnt/user/backups/restore-lab`
- Reports landen in `/mnt/user/backups/restore-reports`
- Test-Container nutzen das Praefix `restoretest-`
- keine produktiven Volumes schreibend mounten
- keine produktiven Domains fuer Testinstanzen uebernehmen
- Restore-Quelle bleibt das produktive Borg-Repo bei Hetzner; Zugriff ueber den vorhandenen `borg-ui`-Container
- Passphrase kommt aus `/mnt/user/appdata/secrets/borg_repo_passphrase.txt`, nie aus UI-Interna
- Testdaten landen nur unter `/mnt/user/backups/restore-lab/<dienst>`; bei Fehlschlag wird nach `_failed/` verschoben statt geloescht
- Reports landen unter `/mnt/user/backups/restore-reports`
- Testcontainer nutzen das Praefix `restoretest-`, localhost-Ports, keine produktive Domain, keine Traefik-Route
- keine produktiven Volumes schreibend mounten, keine produktiven Pfade beschreiben
- keine Restore-Automatik fuer neue Dienste ohne bewusste Freigabe
## Geplante Struktur
## Erfolgskriterien
- `schedule.md`: Intervalle und Verantwortlichkeiten
- `common.sh`: gemeinsame Helfer fuer Borg-Lookup, Borg-Extract und Compose-Cleanup; prueft vor Borg-Operationen auch `borg-ui:/data/borg.db` und `borg-ui:/local/secrets/borg_repo_passphrase.txt`
- `vaultwarden-restore-test.ps1`: erster Mini-Restore-Ablauf
- `vaultwarden-restore-test.sh`: hosttauglicher Vaultwarden-Restore-Job
- `vaultwarden-plan.md`: konkreter Vaultwarden-Testplan
- `vaultwarden-compose.test.yml`: isolierte Testinstanz fuer Vaultwarden
- `gitea-restore-test.ps1`: Gitea-Mini-Restore-Ablauf
- `gitea-restore-test.sh`: hosttauglicher Gitea-Restore-Job
- `gitea-plan.md`: konkreter Gitea-Testplan
- `gitea-compose.test.yml`: isolierte Testinstanz fuer Gitea
- `paperless-restore-test.ps1`: Paperless-Mini-Restore-Ablauf
- `paperless-restore-test.sh`: hosttauglicher Paperless-Restore-Job
- `paperless-plan.md`: konkreter Paperless-Testplan
- `paperless-compose.test.yml`: isolierte Testinstanz fuer Paperless inkl. Test-Postgres und Test-Redis
- `immich-restore-test.ps1`: Immich-Mini-Restore-Ablauf als Plan-/Windows-Scaffold
- `immich-restore-test.sh`: hosttauglicher Immich-Restore-Job, erster echter Lauf noch offen
- `immich-plan.md`: konkreter Immich-Testplan
- `immich-runbook.md`: Operator-Runbook fuer den ersten Immich-Lauf
- `immich-compose.test.yml`: isolierte Testinstanz fuer Immich inkl. VectorChord/pgvector-Test-Postgres und Test-Redis
- `authelia-restore-test.sh`: Authelia-Restore-Job (Config-Smoke; Erstlauf 2026-06-03 erfolgreich)
- `authelia-compose.test.yml`: isolierte Testinstanz fuer Authelia inkl. Test-Postgres, Filesystem-Notifier (kein echter SMTP-Versand)
- `authelia-plan.md`: konkreter Authelia-Testplan
- `authelia-runbook.md`: Operator-Runbook fuer den ersten Authelia-Lauf
- `adguard-restore-test.sh`: AdGuard-Home-Restore-Job (Config + isolierter Container + HTTP/DNS-Smoke; Erstlauf 2026-06-06 erfolgreich)
- `adguard-compose.test.yml`: isolierte AdGuard-Testinstanz auf localhost-Ports `13001` und `15353`
- `redis-restore-test.sh`: Redis-8-Restore-Job (Pre-Cutover-Artefakt + isolierter Container + PING/INFO/DBSIZE; Erstlauf 2026-06-06 erfolgreich)
- `redis-compose.test.yml`: isolierte Redis-8-Testinstanz auf localhost-Port `16379`
- `nextcloud-restore-test.sh`: Nextcloud-Restore-Job (Scaffold; **blockiert** durch Unraid shfs-chmod-Inkompatibilitaet - siehe unten)
- `nextcloud-compose.test.yml`: isolierte Testinstanz fuer Nextcloud inkl. Test-Postgres und Test-Redis
Ein Restore-Test gilt nur dann als erfolgreich, wenn Quelle lesbar war, Daten
im Restore-Lab ankamen, der Testcontainer startete, der **fachliche**
Smoke-Test gelang und ein Report geschrieben wurde. "Container laeuft" allein
reicht nicht.
- `check-restore-freshness.ps1`: woechentlicher Frische-Check fuer Dumps und Reports
- `run-restore-checks.ps1`: einfacher Dispatcher fuer Restore-Jobs
- `check-restore-freshness.sh`: hosttauglicher Frische-Check
- `negative-freshness-alert-test.sh`: sicherer Negativtest fuer den Frische-Alarmweg; nutzt synthetische leere Testpfade unter `/mnt/user/backups/restore-lab/freshness-negative`, veraendert keine produktiven Dumps und sendet bei erkanntem Fehler einen Test-Alert nach `homelab-alerts`
- `run-restore-checks.sh`: hosttauglicher Dispatcher
- `common.sh`: gemeinsame Host-Helferfunktionen
- `automation-plan.md`: Host-Job- und Automatisierungsmodell
## Aufbau des Verzeichnisses
## Automatisierungsmodell
Pro Dienst existieren bis zu drei Artefakte:
- Ausfuehrung: Unraid User Script / Host-Job
- Logik: Repo-Skripte in diesem Verzeichnis
- Ergebnis: Markdown-Report
- Meldung: `ntfy`
- Hermes: optional nur fuer Zusammenfassung und Auswertung
- `<dienst>-restore-test.sh` - automatisierter Host-Job (produktive Wahrheit)
- `<dienst>-compose.test.yml` - isolierte Testinstanz
- `<dienst>-runbook.md` - manueller Ablauf bzw. Besonderheiten
Wichtig:
Dazu zentrale Helfer:
- die Bash-Skripte `*.sh` sind die produktive Host-Variante
- `check-restore-freshness.ps1` und die `*.ps1`-Dateien bleiben als lokale Plan-/Hilfsvariante nutzbar
- im Windows-Clone fehlen die `/mnt/user/...`-Pfade naturgemaess
- `run-restore-checks.sh` - Dispatcher (Host), `run-restore-checks.ps1` (lokale Planvariante)
- `run-restore-job-with-ntfy.sh` - Wrapper: Erfolg -> `homelab-info`, Fehler -> `homelab-alerts`
- `check-restore-freshness.sh` / `.ps1` - woechentlicher Frische-Check fuer Dumps und Reports (prueft pg-Dumps per `pg_restore --list`)
- `negative-freshness-alert-test.sh` - sicherer Negativtest des Alarmwegs (synthetischer Leerpfad, quartalsweise)
- `common.sh` - gemeinsame Borg-/Compose-Helfer
- `automation-plan.md` - Host-Job- und Automatisierungsmodell
## Validiertes Grundmuster
## Betriebsmodus
Stand nach dem ersten echten Vaultwarden-Test:
Stand 2026-06-11 ist der Betrieb auf V1+ (validierte Bash-Host-Jobs mit ntfy):
- Borg-Quelle bleibt das produktive Remote-Repo bei Hetzner
- Borg-Zugriff laeuft praktisch ueber den vorhandenen `borg-ui`-Container
- SSH-Trust wird ueber `known_hosts` im `borg-ui`-Container hergestellt
- die Borg-Passphrase kommt fuer Restore-Tests aus einer Host-Secret-Datei
- Restore-Ziel liegt immer getrennt unter `/mnt/user/backups/restore-lab`
- Reports liegen unter `/mnt/user/backups/restore-reports`
- Testinstanzen bekommen keine produktive Domain und keine Traefik-Route
- Host-Jobs laufen als Unraid User Scripts vom Repo-Spiegel `/mnt/user/services/homelab-infra`
- Kadenz und Cron-Ausdruecke: `schedule.md` (woechentlicher Frische-Check, monatliche/quartalsweise Dienst-Rotation, monatlicher Zufalls-Restore)
- Job-Vorlagen: `unraid-user-scripts.md`
Das ist das bevorzugte Muster fuer weitere dateibasierte Restore-Tests wie `gitea`.
## Schnellstart
Fuer datenbankgestuetzte Dienste wie `paperless` kommt zusaetzlich ein isolierter Dump-Restore in Test-Postgres dazu.
```bash
# Frische-Check
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh freshness
## Status
# Dienst-Restore-Check (vaultwarden|gitea|paperless|immich|authelia|adguard|redis|komodo-bootstrap|nextcloud)
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh <dienst>
Aktuell ist das erste validierte Muster vorhanden.
# Negativtest des Alarmwegs (quartalsweise)
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh freshness-negative
- echter Vaultwarden-Restore am 2026-05-07 erfolgreich verifiziert
- echter Gitea-Restore am 2026-05-07 erfolgreich verifiziert
- echter Paperless-Restore am 2026-05-07 erfolgreich verifiziert
- Immich-Restore-Test am 2026-05-27 erfolgreich verifiziert; Test-Postgres wurde nach der VectorChord-Migration am 2026-05-31 auf das produktive Immich-Postgres-Image umgestellt
- Authelia-Restore-Smoke am 2026-06-03 erfolgreich verifiziert; bewusst ohne produktiven Dump-Restore wegen Storage-Encryption-Key-Kopplung
- AdGuard-Home-Restore-Smoke am 2026-06-06 erfolgreich verifiziert; Borg-Config-Restore, HTTP `/control/status` 401, DNS-Smoke ok, 7 Filterlisten-Eintraege, Report `/mnt/user/backups/restore-reports/adguard-2026-06-06.md`
- Redis-8-Restore-Smoke am 2026-06-06 erfolgreich verifiziert; Pre-Cutover-Artefakt, Redis 8.8, PING ok, AOF aktiv, DBSIZE 1, Report `/mnt/user/backups/restore-reports/redis-2026-06-06.md`
- Bash-Dispatcher und Bash-Restore-Jobs am 2026-05-07 erfolgreich hostseitig verifiziert
- Restore-Lab und Report-Pfade auf dem Host angelegt
- `ntfy`-Wrapper ist fuer Host-Jobs verfuegbar
- Frische-Negativtest ist als sicherer Host-Job verfuegbar und am 2026-06-06 auf Unraid validiert: `ops/restore-tests/run-restore-checks.sh freshness-negative`. Ergebnis: synthetischer leerer Dump-Pfad erzeugte 10 Criticals, Test-Alert ging nach `homelab-alerts`, produktive Dump-Pfade blieben unangetastet. Report: `/mnt/user/backups/restore-reports/freshness-negative-2026-06-06-130320.md`.
- Nextcloud-Restore-Test: Scaffold existiert, aber **blockiert**. Nextcloud 33 fuehrt zur Laufzeit `chmod()` auf Dateien unter `/var/www/html` aus (`OC_Util.php:486`). Auf Unraids FUSE/shfs User-Shares ist `chmod` strukturell nicht moeglich, was zu permanenter 503 fuehrt. Loesungsoptionen: (a) Restore-Lab auf ein Cache-Drive statt User Share legen, (b) Docker-Volumes statt Bind-Mounts verwenden, (c) tmpfs-Mount fuer html/ + `rsync` der Borg-Daten hinein. Bis dahin ist Nextcloud als Backlog-Item dokumentiert.
- Komodo-Mongo-Daten-Restore am 2026-06-03 erfolgreich: 86904 Dokumente (inkl. 32 Stacks), Report `/mnt/user/backups/restore-reports/komodo-mongo-restore-2026-06-03.md`
- naechste grosse Kandidaten sind Mailarchiver und Mealie; Nextcloud bleibt blockiert (shfs-chmod)
# Mit ntfy-Meldung
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-job-with-ntfy.sh freshness homelab-info
```
Vor dem ersten echten Testlauf je neuem Dienst muessen Zielpfade, Quellpfade und Bereinigungsschritte bewusst freigegeben werden.
## Status je Dienst
Einziger Status-Ort ist die **Reifegrad-Tabelle** in `docs/RESTORE_MATRIX.md`
(letzter Test, Typ, naechster Lauf). Hier nur Besonderheiten:
- **Nextcloud:** Test am 2026-06-03 erfolgreich, aber mit Unraid-shfs-Eigenheit: Nextcloud fuehrt `chmod()` unter `/var/www/html` aus, was auf FUSE/shfs scheitert. Das Skript patcht `check_data_directory_permissions: false` und legt den `.ncdata`-Marker an.
- **Authelia:** bewusst Config-Smoke ohne produktiven Dump-Restore (Storage-Encryption-Key-Kopplung).
- **Immich:** Foto-Dateien-Restore ist bewusst nicht Teil des Smokes (separater DR-Drill); Test-Postgres nutzt das produktive VectorChord-Image.
- **Unraid-Flash / Tailscale:** noch ohne vollstaendigen Erstlauf - `unraid-flash-runbook.md`, `tailscale-runbook.md`; offene Schritte in `docs/MASTER_TODO.md`.
## Naechste Ausbaustufen
1. Hermes-Zusammenfassung ueber vorhandene Reports (geparkt mit Hermes)
2. Report-Rotation: Reports werden dauerhaft aufbewahrt; bei wachsender Anzahl jaehrlich nach `_archive/YYYY/` verschieben. Der Frische-Check warnt ab `MAX_REPORT_AGE_DAYS=45`, loescht aber nie automatisch.