From 1dc1c1ef17bafbf370722abf44bdd75fcb22ce5c Mon Sep 17 00:00:00 2001 From: Micha Date: Wed, 6 May 2026 20:13:30 +0200 Subject: [PATCH] Add restore test scaffolding for Vaultwarden --- ops/restore-tests/README.md | 45 +++++++++ ops/restore-tests/schedule.md | 74 ++++++++++++++ .../vaultwarden-compose.test.yml | 25 +++++ ops/restore-tests/vaultwarden-plan.md | 55 +++++++++++ .../vaultwarden-restore-test.ps1 | 34 +++++++ ops/restore-tests/vaultwarden-runbook.md | 97 +++++++++++++++++++ 6 files changed, 330 insertions(+) create mode 100644 ops/restore-tests/README.md create mode 100644 ops/restore-tests/schedule.md create mode 100644 ops/restore-tests/vaultwarden-compose.test.yml create mode 100644 ops/restore-tests/vaultwarden-plan.md create mode 100644 ops/restore-tests/vaultwarden-restore-test.ps1 create mode 100644 ops/restore-tests/vaultwarden-runbook.md diff --git a/ops/restore-tests/README.md b/ops/restore-tests/README.md new file mode 100644 index 0000000..c2cb774 --- /dev/null +++ b/ops/restore-tests/README.md @@ -0,0 +1,45 @@ +# Restore Tests + +Kontrollierte Restore-Tests fuer `homelab-infra`. + +Ziel: + +- Backups durch echte Test-Restores verifizieren +- produktive Pfade nicht beschreiben +- Testlaeufe spaeter weitgehend automatisieren + +## 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 + +## Geplante Struktur + +- `schedule.md`: Intervalle und Verantwortlichkeiten +- `vaultwarden-restore-test.ps1`: erster Mini-Restore-Ablauf +- `vaultwarden-plan.md`: konkreter Vaultwarden-Testplan +- `vaultwarden-compose.test.yml`: isolierte Testinstanz fuer Vaultwarden +- spaeter weitere Tests fuer `gitea` und `paperless` + +## Automatisierungsmodell + +- Ausfuehrung: Unraid User Script / Host-Job +- Logik: Repo-Skripte in diesem Verzeichnis +- Ergebnis: Markdown-Report +- Meldung: `ntfy` +- Hermes: optional nur fuer Zusammenfassung und Auswertung + +## Status + +Aktuell ist hier nur die erste Repo-Vorbereitung angelegt. + +- noch kein echter Restore-Lauf +- noch keine Host-Pfade beschrieben +- noch keine Container gestartet +- erster V1-Ablauf ohne `ntfy`, mit Bereinigung nach Erfolg + +Vor dem ersten echten Testlauf muessen Zielpfade, Quellpfade und Bereinigungsschritte bewusst freigegeben werden. diff --git a/ops/restore-tests/schedule.md b/ops/restore-tests/schedule.md new file mode 100644 index 0000000..01b7b98 --- /dev/null +++ b/ops/restore-tests/schedule.md @@ -0,0 +1,74 @@ +# Restore Test Schedule + +## Ziel + +Regelmaessige Restore-Tests mit wenig Handarbeit und klaren Nachweisen. + +## Intervalle + +Woechentlich: + +- Backup-/Dump-Frische pruefen +- keine echten Restore-Container starten +- pruefen: + - Dump-Dateien vorhanden + - Dump-Dateien nicht zu alt + - letzte Reports vorhanden + +Monatlich: + +- `vaultwarden` Mini-Restore +- `gitea` Mini-Restore, versetzt zum Vaultwarden-Lauf + +Alle 2 Monate: + +- `paperless` Mini-Restore + +Quartalsweise: + +- Restore-/DR-Sanity-Check +- pruefen: + - Restore-Lab-Struktur + - Reports + - Skripte und Pfade + - Doku noch passend + +Spaeter: + +- `immich` als eigener Sprint + +## Automatisierung + +Automatisch: + +- Testpfad vorbereiten +- Restore in `restore-lab` +- Testcontainer `restoretest-*` starten +- Smoke-Test ausfuehren +- Markdown-Report schreiben +- `ntfy` Erfolg/Fehler senden +- alte Testartefakte bereinigen + +Manuell: + +- neue Testfaelle einfuehren +- riskante oder produktionsnahe Sondertests +- Aenderungen an Restore-Logik +- Freigabe fuer den ersten echten Restore je Dienst + +## Ablage + +- Quelle: `/mnt/user/backups/borg` +- Restore-Lab: `/mnt/user/backups/restore-lab` +- Reports: `/mnt/user/backups/restore-reports` + +## Erfolgsregel + +Ein Test gilt erst dann als erfolgreich, wenn: + +- Restore abgeschlossen ist +- Testcontainer startet +- definierter Smoke-Test erfolgreich ist +- Report geschrieben wurde + +Nur "Container laeuft" reicht nicht. diff --git a/ops/restore-tests/vaultwarden-compose.test.yml b/ops/restore-tests/vaultwarden-compose.test.yml new file mode 100644 index 0000000..da9558e --- /dev/null +++ b/ops/restore-tests/vaultwarden-compose.test.yml @@ -0,0 +1,25 @@ +services: + restoretest-vaultwarden: + image: vaultwarden/server:latest@sha256:9a8eec71f4a52411cc43edc7a50f33e9b6f62b5baca0dd95f0c6e7fd60f1a341 + container_name: restoretest-vaultwarden + restart: "no" + + environment: + TZ: Europe/Berlin + DOMAIN: http://127.0.0.1:18080 + WEBSOCKET_ENABLED: "true" + SIGNUPS_ALLOWED: "false" + INVITATIONS_ALLOWED: "false" + ADMIN_TOKEN_FILE: /run/secrets/admin_token + ROCKET_PORT: 80 + ROCKET_ADDRESS: 0.0.0.0 + + ports: + - "127.0.0.1:18080:80" + + volumes: + - /mnt/user/backups/restore-lab/vaultwarden/data:/data + - /mnt/user/appdata/secrets/vaultwarden_admin_token.txt:/run/secrets/admin_token:ro + + security_opt: + - no-new-privileges:true diff --git a/ops/restore-tests/vaultwarden-plan.md b/ops/restore-tests/vaultwarden-plan.md new file mode 100644 index 0000000..d2103fd --- /dev/null +++ b/ops/restore-tests/vaultwarden-plan.md @@ -0,0 +1,55 @@ +# 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` +- Secret: `/mnt/user/appdata/secrets/vaultwarden_admin_token.txt` + +## 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 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 diff --git a/ops/restore-tests/vaultwarden-restore-test.ps1 b/ops/restore-tests/vaultwarden-restore-test.ps1 new file mode 100644 index 0000000..1748e22 --- /dev/null +++ b/ops/restore-tests/vaultwarden-restore-test.ps1 @@ -0,0 +1,34 @@ +param( + [string]$BackupSource = "/mnt/user/backups/borg", + [string]$RestoreRoot = "/mnt/user/backups/restore-lab/vaultwarden", + [string]$ReportRoot = "/mnt/user/backups/restore-reports", + [switch]$WhatIf +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +Write-Output "Vaultwarden restore test scaffold" +Write-Output "BackupSource: $BackupSource" +Write-Output "RestoreRoot: $RestoreRoot" +Write-Output "ReportRoot: $ReportRoot" +Write-Output "Expected Borg source path inside archive: local/appdata/vaultwarden" + +if ($WhatIf) { + Write-Output "Mode: WhatIf" +} else { + Write-Output "Mode: Scaffold only" +} + +Write-Output "" +Write-Output "Planned steps:" +Write-Output "1. Prepare restore-lab target under /mnt/user/backups/restore-lab/vaultwarden" +Write-Output "2. Restore Vaultwarden data into an isolated test path" +Write-Output ' Template: borg extract "$BORG_REPO" "::ARCHIVE_NAME" local/appdata/vaultwarden' +Write-Output "3. Start container restoretest-vaultwarden against test data only" +Write-Output "4. Run smoke checks against the test instance" +Write-Output "5. Write markdown report under /mnt/user/backups/restore-reports" +Write-Output "6. Send optional ntfy result" +Write-Output "" +Write-Output "This script is intentionally a scaffold only." +Write-Output "No restore, no container start, no file write is executed yet." diff --git a/ops/restore-tests/vaultwarden-runbook.md b/ops/restore-tests/vaultwarden-runbook.md new file mode 100644 index 0000000..e3e696f --- /dev/null +++ b/ops/restore-tests/vaultwarden-runbook.md @@ -0,0 +1,97 @@ +# Vaultwarden Restore Runbook + +## Vorbedingungen + +- Borg-Quelle ist verfuegbar +- Secret-Datei vorhanden: `/mnt/user/appdata/secrets/vaultwarden_admin_token.txt` +- Testpfade unter `/mnt/user/backups/restore-lab/` und `/mnt/user/backups/restore-reports/` sind freigegeben + +## Platzhalter + +- `ARCHIVE_NAME`: Borg-Archiv fuer den Restore-Test +- `REPORT_DATE`: z. B. `2026-05-06` +- `BORG_REPO`: Host-Borg-Repo, z. B. das produktive `critical_infra` +- `BORG_PASSPHRASE`: wie im bestehenden Host-Setup + +## Ablauf + +1. Testpfade vorbereiten + +```bash +mkdir -p /mnt/user/backups/restore-lab/vaultwarden/data +mkdir -p /mnt/user/backups/restore-reports +rm -rf /mnt/user/backups/restore-lab/vaultwarden/data/* +``` + +2. Vaultwarden-Daten aus Borg in das Restore-Lab extrahieren + +Archiv zuerst pruefen: + +```bash +export BORG_REPO='...' +export BORG_PASSPHRASE='...' +borg list "$BORG_REPO" +``` + +Restore in das Testziel: + +```bash +cd /mnt/user/backups/restore-lab/vaultwarden +borg extract "$BORG_REPO" "::ARCHIVE_NAME" local/appdata/vaultwarden +mv /mnt/user/backups/restore-lab/vaultwarden/local/appdata/vaultwarden /mnt/user/backups/restore-lab/vaultwarden/data +rmdir /mnt/user/backups/restore-lab/vaultwarden/local/appdata +rmdir /mnt/user/backups/restore-lab/vaultwarden/local +``` + +Wenn das Archiv den Pfad anders ablegt, zuerst mit `borg list "$BORG_REPO" "::ARCHIVE_NAME"` den exakten Eintrag pruefen. + +Zielpfad nach dem Restore: + +```text +/mnt/user/backups/restore-lab/vaultwarden/data +``` + +3. Testcontainer starten + +```bash +docker compose -f /mnt/user/services/homelab/ops/restore-tests/vaultwarden-compose.test.yml up -d +``` + +4. Smoke-Test + +```bash +curl -I http://127.0.0.1:18080 +docker logs restoretest-vaultwarden --tail 50 +``` + +Minimal erfolgreich: + +- HTTP-Antwort kommt +- Login-Seite ist erreichbar +- Vaultwarden-Daten liegen im Restore-Lab vor + +5. Testcontainer wieder stoppen + +```bash +docker compose -f /mnt/user/services/homelab/ops/restore-tests/vaultwarden-compose.test.yml down +``` + +6. Report schreiben + +Ziel: + +```text +/mnt/user/backups/restore-reports/vaultwarden-REPORT_DATE.md +``` + +7. Testdaten nach erfolgreichem Lauf bereinigen + +```bash +rm -rf /mnt/user/backups/restore-lab/vaultwarden/data +``` + +## Festgelegte Entscheidungen + +- Testdaten werden nach erfolgreichem Lauf geloescht. +- `ntfy` wird nicht im ersten echten Lauf eingebunden. +- `ntfy` folgt spaeter, wenn der manuelle Basisablauf stabil verifiziert ist.