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:
+63
-87
@@ -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.
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
# Authelia Restore Test Plan
|
||||
|
||||
## Ziel
|
||||
|
||||
Nachweisen, dass die Authelia-Konfiguration aus dem produktiven Borg-Archiv in einer isolierten Testumgebung wieder lauffaehig ist und der HTTP-Health-Endpunkt antwortet, ohne dass dabei produktive Secrets, produktives Postgres oder produktiver SMTP-Versand beruehrt werden.
|
||||
|
||||
Bewusst **nicht** Teil dieses Tests:
|
||||
|
||||
- Restore mit produktiven Authelia-Secrets. Der Test nutzt ausschliesslich Wegwerf-Werte fuer `AUTHELIA_SESSION_SECRET`, `AUTHELIA_STORAGE_ENCRYPTION_KEY` und `AUTHELIA_STORAGE_POSTGRES_PASSWORD`. SMTP- und Legacy-JWT-Env-Werte werden bewusst nicht gesetzt, damit Authelia keinen `notifier.smtp`-Block oder deprecated `jwt_secret` aus Env erzeugt.
|
||||
- SMTP-Realanruf an GMX. Die minimale Test-Konfiguration setzt nur den Filesystem-Notifier.
|
||||
- Forward-Auth gegen Traefik. Test laeuft nur auf `127.0.0.1:19091`, keine Traefik-Route.
|
||||
- WebAuthn-/Duo-/OIDC-Identity-Provider-Endpunkte. Smoke prueft `/api/health`.
|
||||
- **pg_restore des produktiven `postgresql17-authelia.dump`**. Authelia verschluesselt Storage-Werte mit `AUTHELIA_STORAGE_ENCRYPTION_KEY`. Ein Restore mit produktiven Daten in eine Test-Instanz mit Wegwerf-Key schlaegt im Startup-Check **by design** fehl ("the configured encryption key does not appear to be valid for this database"). Frische des produktiven Dumps wird ueber `check-restore-freshness.sh` ueberwacht; Daten-Decrypt-Drill ist eine separate DR-Aufgabe und braucht eine eigene Sicherheits-Choreographie mit kontrollierter Schluessel-Verwendung. Beobachtet im Erstlauf 2026-06-03 (Commit-Reihe `cacf77b..8d71dfb`); seit dem 2026-06-03-Folgecommit ist der Dump-Restore explizit aus dem Smoke entfernt.
|
||||
|
||||
## Quelle
|
||||
|
||||
- Backup-Quelle: produktives Borg-Archiv (`hetzner_borg_appdata_critical`)
|
||||
- fachlich relevante Pfade im Archiv:
|
||||
- `local/appdata/authelia/config` (verpflichtend)
|
||||
- `local/borg-dumps/latest/postgresql17-authelia.dump` (existiert ggf. im Archiv; wird vom Smoke bewusst NICHT eingespielt, siehe oben)
|
||||
- produktive Secrets unter `/mnt/user/appdata/secrets/authelia_*.txt` werden **nicht** gemountet
|
||||
|
||||
## Test-Ziel
|
||||
|
||||
- Restore-Lab: `/mnt/user/backups/restore-lab/authelia`
|
||||
- Testdatenpfade:
|
||||
- `/mnt/user/backups/restore-lab/authelia/config` (restaurierte Originalkonfiguration + `configuration.yml.original`)
|
||||
- `/mnt/user/backups/restore-lab/authelia/test-config` (Runtime-Mount mit minimaler Test-`configuration.yml`)
|
||||
- `/mnt/user/backups/restore-lab/authelia/postgres` (Test-Postgres-Datadir)
|
||||
- `/mnt/user/backups/restore-lab/authelia/dumps/latest/postgresql17-authelia.dump` (falls extrahiert)
|
||||
- `/mnt/user/backups/restore-lab/authelia/test-config/notifier/notifications.txt` (Filesystem-Notifier-Ausgabe)
|
||||
- Testcontainer:
|
||||
- `restoretest-authelia` (Image-Pin wie Produktion)
|
||||
- `restoretest-authelia-postgres` (postgres:18.4, gleiche Major wie shared Postgres)
|
||||
- Testport: `127.0.0.1:19091:9091`
|
||||
- Report-Ziel: `/mnt/user/backups/restore-reports/authelia-YYYY-MM-DD.md`
|
||||
|
||||
## Schutzregeln
|
||||
|
||||
- produktive Pfade `/mnt/user/appdata/authelia/*` werden **nicht** beschrieben
|
||||
- produktive Secret-Dateien `/mnt/user/appdata/secrets/authelia_*.txt` werden **nicht** gemountet
|
||||
- produktive shared PostgreSQL 18 wird **nicht** angesprochen (`test-config/configuration.yml` definiert nur Test-Postgres)
|
||||
- echter SMTP-Versand wird **nicht** ausgeloest (`test-config/configuration.yml` definiert nur Filesystem-Notifier)
|
||||
- produktive Domain `auth.kaleschke.info` wird **nicht** uebernommen
|
||||
- Testcontainer publishen nur auf `127.0.0.1`, keine LAN-/Tailscale-Bindung
|
||||
- Borg-Passphrase wird aus `/mnt/user/appdata/secrets/borg_repo_passphrase.txt` gelesen und nirgendwo geloggt
|
||||
|
||||
## Geplanter Ablauf
|
||||
|
||||
1. Restore-Lab-Pfade leer anlegen
|
||||
2. `local/appdata/authelia/config` aus dem aktuellsten Borg-Archiv extrahieren
|
||||
3. minimale `test-config/configuration.yml` erzeugen; restaurierte Begleitdateien wie `users_database.yml` bleiben im Runtime-Mount, produktive externe Abhaengigkeiten werden nicht uebernommen; `notifier` auf Filesystem, `ntp.disable_startup_check: true`, `storage` auf Test-Postgres
|
||||
4. Test-Postgres mit `ops/restore-tests/authelia-compose.test.yml` **frisch** hochfahren (keine Daten aus Dump - siehe Encryption-Key-Begruendung oben)
|
||||
5. `authelia config validate` gegen `test-config/configuration.yml` laufen lassen
|
||||
6. `restoretest-authelia` starten und HTTP-Health `http://127.0.0.1:19091/api/health` pollen
|
||||
7. Report unter `/mnt/user/backups/restore-reports/authelia-YYYY-MM-DD.md` schreiben
|
||||
8. Testcontainer stoppen und Restore-Lab bereinigen (`--keep-data` ueberschreibt)
|
||||
|
||||
## Smoke-Test
|
||||
|
||||
Minimal erfolgreich:
|
||||
|
||||
- Borg-Extract der Authelia-Config gelingt
|
||||
- Test-Postgres startet `healthy`
|
||||
- `authelia config validate` laeuft ohne Fehler durch
|
||||
- HTTP `200` auf `/api/health` innerhalb 120 s
|
||||
|
||||
Optional spaeter:
|
||||
|
||||
- vollstaendigen Auth-Flow gegen Test-User aus `users_database.yml` durchspielen
|
||||
- WebAuthn-Endpunkt /api/secondfactor/webauthn pruefen
|
||||
- ForwardAuth-Pfad gegen Mock-Backend testen
|
||||
|
||||
## Bekannte Komplikationen
|
||||
|
||||
| Risiko | Beschreibung | Mitigation |
|
||||
|---|---|---|
|
||||
| Testkonfig-Schema-Drift | Authelia erwartet nach Upgrade andere Keys in der Minimal-Konfig | bei `config validate`-Fehler Test-Block im Skript anpassen |
|
||||
| SMTP-Startup-Check blockiert Start | Wenn Authelia trotz `disable_startup_check` SMTP probiert | Container-Logs lesen, ggf. Notifier-Block weiter haerten |
|
||||
| NTP-Lookup im Test-Netz | Container hat keinen DNS-Resolver fuer `time.cloudflare.com` | im Smoke per `ntp.disable_startup_check: true` deaktiviert |
|
||||
| Storage-Encryption-Key vs. Dump | siehe "Bewusst nicht Teil dieses Tests" - der Smoke laeuft FRISCH ohne Dump | by design - Daten-Decrypt-Drill ist separate Aufgabe |
|
||||
| identity_validation Schema-Drift | Aelteres/neueres Authelia-Schema erwartet andere Keys | Validate-Config Output lesen, ggf. Test-Block anpassen |
|
||||
| users_database.yml mit produktiven Hashes | Daten werden ins Restore-Lab kopiert, aber niemals gemountet auf produktive Domain | OK; Testpfad ist isoliert, kein Browser-Zugang ueber LAN |
|
||||
|
||||
## Status
|
||||
|
||||
- Skript- und Compose-Scaffold abgelegt am 2026-06-02
|
||||
- Erstlauf am 2026-06-03 erfolgreich: Config aus Borg, minimale Test-Konfiguration, frisches Test-Postgres, HTTP `/api/health` `200`, Report `/mnt/user/backups/restore-reports/authelia-2026-06-03.md`
|
||||
- Fuer die Rotation vorgesehen: zweiter Samstag in geraden Monaten, 07:30
|
||||
@@ -1,59 +0,0 @@
|
||||
# Gitea Restore Test Plan
|
||||
|
||||
## Ziel
|
||||
|
||||
Nachweisen, dass ein Gitea-Backup in einer isolierten Testumgebung wieder startbar ist und sowohl Web-UI als auch SSH-Port wieder verfuegbar sind.
|
||||
|
||||
## Quelle
|
||||
|
||||
- Backup-Quelle: Borg / Share-Backup
|
||||
- fachlich relevanter Datenpfad: `/mnt/user/services/gitea/data`
|
||||
- keine separaten Secret-Dateien dokumentiert
|
||||
|
||||
## Test-Ziel
|
||||
|
||||
- Restore-Lab: `/mnt/user/backups/restore-lab/gitea`
|
||||
- Testdatenpfad: `/mnt/user/backups/restore-lab/gitea/data`
|
||||
- Testcontainer: `restoretest-gitea`
|
||||
- Testports:
|
||||
- Web: `127.0.0.1:13000:3000`
|
||||
- SSH: `127.0.0.1:12222:22`
|
||||
- Report-Ziel: `/mnt/user/backups/restore-reports/gitea-YYYY-MM-DD.md`
|
||||
|
||||
## Schutzregeln
|
||||
|
||||
- produktiven Pfad `/mnt/user/services/gitea/data` nie beschreiben
|
||||
- produktive Domain `git.kaleschke.info` nicht fuer die Testinstanz uebernehmen
|
||||
- produktiven SSH-Port `222` nicht fuer die Testinstanz uebernehmen
|
||||
- keine Traefik-Labels fuer die Testinstanz
|
||||
- Testcontainer nur gegen Restore-Lab-Daten starten
|
||||
|
||||
## Geplanter Ablauf
|
||||
|
||||
1. Restore-Ziel unter `/mnt/user/backups/restore-lab/gitea` vorbereiten
|
||||
2. Gitea-Daten aus Backup in `restore-lab/gitea/data` wiederherstellen
|
||||
3. Testinstanz mit `ops/restore-tests/gitea-compose.test.yml` starten
|
||||
4. lokalen Smoke-Test gegen `http://127.0.0.1:13000` und `127.0.0.1:12222` ausfuehren
|
||||
5. Report unter `/mnt/user/backups/restore-reports/` schreiben
|
||||
6. Testcontainer stoppen und Testumgebung bereinigen oder bewusst stehen lassen
|
||||
|
||||
## Smoke-Test
|
||||
|
||||
Minimal erfolgreich:
|
||||
|
||||
- Container startet
|
||||
- Web-UI antwortet
|
||||
- mindestens ein bestehendes Repository-Verzeichnis ist im Restore-Lab sichtbar
|
||||
- SSH-Port reagiert auf Verbindungsaufbau
|
||||
|
||||
Optional spaeter:
|
||||
|
||||
- Login-Seite gezielt pruefen
|
||||
- SQLite-Datei `gitea.db` oder Nachfolger explizit bestaetigen
|
||||
- `gitea doctor` oder interner Healthcheck als Zusatz
|
||||
|
||||
## Noch offen vor dem ersten echten Lauf
|
||||
|
||||
- exakter Borg-Restore-Befehl bzw. Restore-Quelle auf dem Host
|
||||
- Bereinigungsstrategie fuer alte Restore-Lab-Daten
|
||||
- ob Reports spaeter zusaetzlich per `ntfy` referenziert werden
|
||||
@@ -1,89 +0,0 @@
|
||||
# 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.
|
||||
@@ -34,7 +34,6 @@ Vor dem ersten Lauf muss Operator entscheiden:
|
||||
- `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
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
# Komodo Bootstrap Trockenlauf - Plan
|
||||
|
||||
## Ziel
|
||||
|
||||
Nachweisen, dass `ops/komodo/docker-compose.yml` als Recovery-Anker fuer einen Komodo-Kaltstart tauglich ist, ohne den produktiven Komodo-Stack anzufassen.
|
||||
|
||||
Bewusst **nicht** Teil dieses Tests:
|
||||
|
||||
- Restore aus dem produktiven `komodo-mongo.archive.gz`-Dump (eigene Folgeaufgabe; dieser Test prueft nur das Compose-Bootstrap, nicht den Daten-Restore).
|
||||
- docker.sock-Mount fuer die Test-Periphery (die Test-Periphery darf nie produktive Container managen).
|
||||
- Traefik-Route oder Authelia-Anbindung (Test laeuft ausschliesslich auf `127.0.0.1:19120`).
|
||||
|
||||
## Quelle
|
||||
|
||||
- Bootstrap-Anker: `ops/komodo/docker-compose.yml` (Soll-Stand laut `docs/SERVICES_RECOVERY.md` Stufe A-F).
|
||||
- Image-Digests: identisch zur Produktion fuer komodo-core und komodo-periphery; Mongo-Image identisch.
|
||||
|
||||
## Test-Ziel
|
||||
|
||||
- Restore-Lab: `/mnt/user/backups/restore-lab/komodo`
|
||||
- Wegwerf-Pfade:
|
||||
- `/mnt/user/backups/restore-lab/komodo/mongo` (Test-Mongo-Datadir)
|
||||
- `/mnt/user/backups/restore-lab/komodo/core` (Repo-Cache)
|
||||
- `/mnt/user/backups/restore-lab/komodo/keys` (gemeinsamer Keys-Pfad fuer Core+Periphery)
|
||||
- `/mnt/user/backups/restore-lab/komodo/periphery` (Periphery-Etc)
|
||||
- Testcontainer:
|
||||
- `restoretest-komodo-mongo`
|
||||
- `restoretest-komodo-core` (Test-Port `127.0.0.1:19120`)
|
||||
- `restoretest-komodo-periphery` (ohne docker.sock)
|
||||
- Compose-Project: `restoretest-komodo` (isoliert von Produktions-Project `komodo`)
|
||||
- Report-Ziel: `/mnt/user/backups/restore-reports/komodo-bootstrap-YYYY-MM-DD.md`
|
||||
|
||||
## Schutzregeln
|
||||
|
||||
- produktive Datadirs `/mnt/user/appdata/komodo/{mongo,core,periphery}` werden **nicht** gemountet
|
||||
- produktive Container `komodo-mongo`, `komodo-core`, `komodo-periphery` werden **nicht** gestoppt
|
||||
- produktive `KOMODO_*`-Secrets werden **nicht** verwendet
|
||||
- Test-Compose enthaelt nur Wegwerf-Werte fuer `KOMODO_SECRET_KEY`, `KOMODO_WEBHOOK_SECRET`, `KOMODO_JWT_SECRET`, `KOMODO_PASSKEY` und Mongo-Root-Password
|
||||
- Test-Periphery laeuft ohne docker.sock-Mount und ohne `/mnt/user/services`-Mount
|
||||
- Test-Port nur auf `127.0.0.1:19120`, keine LAN-/Tailscale-Bindung
|
||||
|
||||
## Geplanter Ablauf
|
||||
|
||||
1. Restore-Lab-Pfade leer anlegen
|
||||
2. `docker compose config` auf dem Test-Compose validieren
|
||||
3. Mongo und Core hochfahren, auf Mongo-`healthy` warten
|
||||
4. HTTP-Smoke gegen `http://127.0.0.1:19120` (Login-Seite oder Auth-Redirect erwartet)
|
||||
5. Periphery dazustarten, kurz beobachten
|
||||
6. Mongo-`authenticated ping` mit Test-Credentials
|
||||
7. Report schreiben
|
||||
8. Cleanup `docker compose down -v` und Restore-Lab loeschen (ausser `--keep-data`)
|
||||
|
||||
## Smoke-Test
|
||||
|
||||
Minimal erfolgreich:
|
||||
|
||||
- `docker compose config` valid
|
||||
- Test-Mongo erreicht `healthy`
|
||||
- Mongo-Authentifizierung mit Test-Creds funktioniert (`db.adminCommand({ping:1}).ok = 1`)
|
||||
- Komodo-Core HTTP `200`, `302`, `303` oder `401` (alles ist ein valider Lebenszeichen)
|
||||
- Test-Periphery container state `running`
|
||||
|
||||
Optional spaeter:
|
||||
|
||||
- Periphery-Verbindung gegen Test-Core verifizieren (braucht Periphery-Konfig mit `core_url`)
|
||||
- Echtes Restore aus `komodo-mongo.archive.gz`-Dump in die Test-Mongo
|
||||
- Schreiben einer Wegwerf-Resource (Server/Stack) ueber die API
|
||||
|
||||
## Bekannte Komplikationen
|
||||
|
||||
| Risiko | Beschreibung | Mitigation |
|
||||
|---|---|---|
|
||||
| Image-Drift | Komodo-Images aktualisieren ihre Major-Tag-Digests | Compose pinnt denselben Digest wie Produktion; bei Image-Update auch Test-Compose nachziehen |
|
||||
| Port-Konflikt | wenn 19120 anderweitig belegt ist | nur `127.0.0.1`-Bind; bei Konflikt Port im Compose anpassen |
|
||||
| Volume-Reste | unterbrochener Lauf laesst Wegwerf-Datadir liegen | Skript loescht Restore-Lab vor jedem Lauf; `--keep-data` ueberschreibt das bewusst |
|
||||
| Periphery-Erreichbarkeit | Core sucht Periphery initial nicht aktiv | Test prueft nur Periphery `State.Status=running`; voller Handshake ist optional |
|
||||
|
||||
## Bestaetigte Laeufe
|
||||
|
||||
| Datum | Mode | Ergebnis | Report |
|
||||
|---|---|---|---|
|
||||
| 2026-05-30 | `--what-if` | Plan-Ausgabe wie erwartet | (kein Report, nur stdout) |
|
||||
| 2026-05-30 | `--keep-data` | `SUCCESS`, 5/5 Checks gruen, Core HTTP `200`, Mongo healthy in ~6 s | `/mnt/user/backups/restore-reports/komodo-bootstrap-2026-05-30.md` |
|
||||
|
||||
## Folgeschritte
|
||||
|
||||
- Quartals-Belegung: Komodo-Bootstrap passt zum DR-Sanity-Check (`ops/restore-tests/schedule.md` Q2/Q4) und kann ohne Borg-Archiv jederzeit wiederholt werden.
|
||||
- Optional fuer kuenftige Laeufe: echtes Restore aus `komodo-mongo.archive.gz` in die Test-Mongo, danach Schreiben einer Wegwerf-Resource ueber die API.
|
||||
@@ -1,72 +0,0 @@
|
||||
# Paperless Restore Test Plan
|
||||
|
||||
## Ziel
|
||||
|
||||
Nachweisen, dass ein Paperless-Backup in einer isolierten Testumgebung wieder startbar ist und sowohl Dokumentenpfade als auch PostgreSQL-Dump sauber zusammenlaufen.
|
||||
|
||||
## Quelle
|
||||
|
||||
- Backup-Quelle: Borg / Share-Backup
|
||||
- fachlich relevante Dateipfade:
|
||||
- `/mnt/user/appdata/paperless-ngx/data`
|
||||
- `/mnt/user/documents/paperless`
|
||||
- `/mnt/user/documents/paperless/export`
|
||||
- `/mnt/user/documents/scans_inbox`
|
||||
- fachlich relevanter Dump:
|
||||
- `/mnt/user/backups/borg/dumps/latest/postgresql17-paperless.dump`
|
||||
|
||||
## Test-Ziel
|
||||
|
||||
- Restore-Lab: `/mnt/user/backups/restore-lab/paperless`
|
||||
- Testdatenpfade:
|
||||
- `/mnt/user/backups/restore-lab/paperless/data`
|
||||
- `/mnt/user/backups/restore-lab/paperless/media`
|
||||
- `/mnt/user/backups/restore-lab/paperless/export`
|
||||
- `/mnt/user/backups/restore-lab/paperless/consume`
|
||||
- `/mnt/user/backups/restore-lab/paperless/postgres`
|
||||
- Testcontainer:
|
||||
- `restoretest-paperless`
|
||||
- `restoretest-paperless-postgres`
|
||||
- `restoretest-paperless-redis`
|
||||
- Testport Web: `127.0.0.1:18120:8000`
|
||||
- Report-Ziel: `/mnt/user/backups/restore-reports/paperless-YYYY-MM-DD.md`
|
||||
|
||||
## Schutzregeln
|
||||
|
||||
- produktive Pfade nie beschreiben
|
||||
- produktive Domain `paperless.kaleschke.info` nicht fuer die Testinstanz uebernehmen
|
||||
- keine Traefik-Labels fuer die Testinstanz
|
||||
- keine produktive PostgreSQL- oder Redis-Instanz fuer den Test verwenden
|
||||
- Testcontainer nur gegen Restore-Lab-Daten und isolierte Test-Backends starten
|
||||
|
||||
## Geplanter Ablauf
|
||||
|
||||
1. Restore-Ziel unter `/mnt/user/backups/restore-lab/paperless` vorbereiten
|
||||
2. Paperless-Dateipfade aus Borg in das Restore-Lab wiederherstellen
|
||||
3. Test-Postgres und Test-Redis mit `ops/restore-tests/paperless-compose.test.yml` starten
|
||||
4. `postgresql17-paperless.dump` in Test-Postgres importieren
|
||||
5. Testinstanz `restoretest-paperless` starten
|
||||
6. lokalen Smoke-Test gegen `http://127.0.0.1:18120` ausfuehren
|
||||
7. Report unter `/mnt/user/backups/restore-reports/` schreiben
|
||||
8. Testcontainer stoppen und Testumgebung bereinigen
|
||||
|
||||
## Smoke-Test
|
||||
|
||||
Minimal erfolgreich:
|
||||
|
||||
- Test-Postgres startet
|
||||
- Dump-Import gelingt
|
||||
- Paperless-Web-UI antwortet
|
||||
- mindestens ein Dokument liegt im Restore-Lab-Medienpfad
|
||||
|
||||
Optional spaeter:
|
||||
|
||||
- Login-Seite gezielt pruefen
|
||||
- Dokumentanzahl aus UI oder DB querpruefen
|
||||
- OCR-/Task-Worker-Status verifizieren
|
||||
|
||||
## Noch offen vor dem ersten echten Lauf
|
||||
|
||||
- exakter Borg-Restore-Befehl fuer alle vier Dateipfade
|
||||
- exakter `pg_restore`-Befehl im Test-Postgres
|
||||
- wie stark wir `consume` im ersten Lauf ueberhaupt brauchen
|
||||
@@ -0,0 +1,34 @@
|
||||
# Tailscale - Restore-Runbook
|
||||
|
||||
Typ: Runbook · Stand: 2026-06-11 · Status: aktiv (noch kein Erstlauf)
|
||||
|
||||
Restore-Pfad fuer den Tailscale-State. Wichtig: Tailscale laeuft als
|
||||
**natives Unraid-Plugin**; der funktionale State liegt unter
|
||||
`/boot/config/plugins/tailscale/state` und ist Teil des Flash-Backups
|
||||
(`docs/RESTORE_MATRIX.md` Tier 1).
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- Zugriff auf das Flash-Backup-Artefakt bzw. ein Borg-Archiv mit dem State-Pfad
|
||||
- Testpfad unter `/mnt/user/backups/restore-lab/tailscale` vorbereitet
|
||||
- **Achtung:** Der Tailscale-State ist maschinenspezifisch. Ein Restore auf den produktiven Host wuerde die laufende Verbindung verdraengen. Nur auf einem Wegwerf- oder Offline-Host testen.
|
||||
|
||||
## Artefakt-Validierung (ohne produktiven Host)
|
||||
|
||||
1. State-Verzeichnis in den Testpfad extrahieren
|
||||
2. Erwartete Dateien pruefen: `tailscaled.state` vorhanden
|
||||
3. Dateisystem-Rechte pruefen: `tailscaled.state` muss fuer `root` zugaenglich sein
|
||||
|
||||
## Reconnect-Test (auf Wegwerf-Host oder VM)
|
||||
|
||||
1. Tailscale mit dem gemounteten State-Pfad starten
|
||||
2. `tailscale status` zeigt `Connected` oder den erwarteten Hostnamen
|
||||
3. Tailscale-Admin-Konsole zeigt das Geraet als `Online`
|
||||
4. SSH ueber Tailscale-IP auf den Testhost moeglich
|
||||
5. Testinstanz stoppen; Wegwerf-Geraet in der Tailscale-Admin-Konsole entfernen
|
||||
|
||||
**Smoke-Test-Kriterium:** Instanz verbindet sich mit bestehendem Tailscale-Account (kein neues Re-Auth noetig), Tailscale-IP ist erreichbar.
|
||||
|
||||
**Hinweis:** Falls der State veraltet ist (Key expired), fordert Tailscale ein
|
||||
Re-Auth an. Das ist ein valides Testergebnis und belegt, wie lang der
|
||||
Reconnect-Pfad bei abgelaufenem Key ist.
|
||||
@@ -0,0 +1,45 @@
|
||||
# Unraid OS Flash - Restore-Runbook
|
||||
|
||||
Typ: Runbook · Stand: 2026-06-11 · Status: aktiv (Stick-Boot-Test offen)
|
||||
|
||||
Restore-Pfad fuer die Unraid-Flash-Konfiguration. Artefakt-Validierung ist
|
||||
automatisiert und belegt; offen bleibt nur der physische Ersatzstick-Boot-Test
|
||||
(siehe `docs/MASTER_TODO.md`).
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- Borg-Artefakt `unraid-flash-config.tar.gz` und `.sha256` unter `/mnt/user/backups/borg/dumps/latest` oder im Hetzner-Borg-Repo verfuegbar
|
||||
- Neuer leerer USB-Stick (Empfehlung: 16 GB, USB 2.0 kompatibel)
|
||||
- Unraid USB Flash Creator oder manueller Restore-Pfad
|
||||
- Offline-gesicherte Borg-Passphrase verfuegbar
|
||||
|
||||
## Artefakt-Validierung (ohne produktiven Stick)
|
||||
|
||||
Automatisiert via Repo-Skript `ops/maintenance/check-unraid-flash-backup.sh`
|
||||
(read-only, keine Extraktion). Manuelle Einzelschritte:
|
||||
|
||||
1. SHA256-Pruefung: `sha256sum -c unraid-flash-config.tar.gz.sha256`
|
||||
2. Artefakt-Inhalt pruefen: `tar -tzf unraid-flash-config.tar.gz | head -40` — erwartet `config/` als Prefix
|
||||
3. Kern-Configs vorhanden: `super.dat`, `disk.cfg`, `ident.cfg`, `share.cfg`, `network.cfg`, `docker.cfg`, `go`, `domain.cfg`
|
||||
4. Keine produktiven Konfigurationspfade (z. B. `config/ssh/`) ausserhalb des Test-Environments extrahieren
|
||||
5. Manifest-Datei auf Vollstaendigkeit pruefen
|
||||
|
||||
Letzte Validierung: 2026-06-05, Exit 0, sha256 OK, 390 Eintraege, 8/8
|
||||
Kern-Configs (siehe Reifegrad-Tabelle in `docs/RESTORE_MATRIX.md`).
|
||||
|
||||
## Vollstaendiger Restore-Test (auf Wegwerf-Stick)
|
||||
|
||||
1. Neuen USB-Stick mit Unraid USB Flash Creator formatieren und Basis-Unraid draufspielen
|
||||
2. `config/`-Verzeichnis aus `unraid-flash-config.tar.gz` in den `/boot/config`-Pfad des neuen Sticks extrahieren
|
||||
3. Im Testrahmen booten (kein Array starten, keine Shares mounten)
|
||||
4. Pruefen: Unraid-Grundkonfiguration (Shares, Hostname, Netzwerk) ist sichtbar
|
||||
5. Array-Zuordnung lesbar, ohne Drive-Assigns zu bestaetigen
|
||||
|
||||
**Smoke-Test-Kriterium:** Unraid bootet, Hostname ist `Kallilabcore`, Share-Konfiguration ist sichtbar, kein Array gestartet.
|
||||
|
||||
## Sonderregel
|
||||
|
||||
Das Artefakt enthaelt Host-Konfiguration und Secret-Material (SSH-Host-Keys,
|
||||
Tailscale-State, `passwd`/`shadow`/`smbpasswd`, Lizenz-Key) und ist wie
|
||||
Secret-Backup zu behandeln. Nicht auf oeffentlichen oder unverschluesselten
|
||||
Testzielen extrahieren.
|
||||
@@ -1,56 +0,0 @@
|
||||
# Vaultwarden Restore Test Plan
|
||||
|
||||
## Ziel
|
||||
|
||||
Nachweisen, dass ein Vaultwarden-Backup in einer isolierten Testumgebung wieder startbar und fachlich nutzbar ist.
|
||||
|
||||
## Quelle
|
||||
|
||||
- Backup-Quelle: Borg / Share-Backup
|
||||
- fachlich relevanter Datenpfad: `/mnt/user/appdata/vaultwarden`
|
||||
- Produktives Admin-Token wird fuer den Restore-Smoke bewusst nicht gemountet;
|
||||
die Testinstanz nutzt einen Wegwerf-Wert aus `vaultwarden-compose.test.yml`.
|
||||
|
||||
## Test-Ziel
|
||||
|
||||
- Restore-Lab: `/mnt/user/backups/restore-lab/vaultwarden`
|
||||
- Testdatenpfad: `/mnt/user/backups/restore-lab/vaultwarden/data`
|
||||
- Testcontainer: `restoretest-vaultwarden`
|
||||
- Testport: `127.0.0.1:18080:80`
|
||||
- Report-Ziel: `/mnt/user/backups/restore-reports/vaultwarden-YYYY-MM-DD.md`
|
||||
|
||||
## Schutzregeln
|
||||
|
||||
- produktiven Pfad `/mnt/user/appdata/vaultwarden` nie beschreiben
|
||||
- produktive Domain `vault.kaleschke.info` nicht fuer die Testinstanz uebernehmen
|
||||
- keine Traefik-Labels fuer die Testinstanz
|
||||
- Testcontainer nur gegen Restore-Lab-Daten starten
|
||||
|
||||
## Geplanter Ablauf
|
||||
|
||||
1. Restore-Ziel unter `/mnt/user/backups/restore-lab/vaultwarden` vorbereiten
|
||||
2. Vaultwarden-Daten aus Backup in `restore-lab/vaultwarden/data` wiederherstellen
|
||||
3. Testinstanz mit `ops/restore-tests/vaultwarden-compose.test.yml` starten
|
||||
4. lokalen Smoke-Test gegen `http://127.0.0.1:18080` ausfuehren
|
||||
5. Report unter `/mnt/user/backups/restore-reports/` schreiben
|
||||
6. Testcontainer stoppen und Testumgebung bereinigen oder bewusst stehen lassen
|
||||
|
||||
## Smoke-Test
|
||||
|
||||
Minimal erfolgreich:
|
||||
|
||||
- Container startet
|
||||
- Login-Seite antwortet
|
||||
- Vaultwarden-Daten sind vorhanden
|
||||
|
||||
Optional spaeter:
|
||||
|
||||
- Admin-Endpunkt nur mit separatem Wegwerf-Token pruefen
|
||||
- Websocket-Endpunkt pruefen
|
||||
- Anzahl/Vorhandensein zentraler Daten artefaktisch verifizieren
|
||||
|
||||
## Noch offen vor dem ersten echten Lauf
|
||||
|
||||
- exakter Borg-Restore-Befehl bzw. Restore-Quelle auf dem Host
|
||||
- Bereinigungsstrategie fuer alte Restore-Lab-Daten
|
||||
- ob Reports nur auf dem Host liegen oder zusaetzlich per ntfy referenziert werden
|
||||
Reference in New Issue
Block a user