Kalter Lesetest gegen das Bare-Metal-Szenario aus DR.md Phase 0 bis 5, mit referenzierten Runbooks (SERVICES_RECOVERY, RESTORE_MATRIX, SECRETS_MAP, RESTORE_HANDBOOK, EXTERNAL_DEPENDENCIES) und Compose-Ankern (ops/komodo, traefik). 23 Findings mit Severity, Repo-Datei + Zeile, Fix-Vorschlag pro Punkt. 1x CRITICAL (Unraid-Flash-Restore ohne laufenden Host), 11x HIGH, 8x MED, 3x LOW. Schwerpunkte: - Bare-Metal-Operator-Workstation als DR-Voraussetzung nicht dokumentiert - Henne-Ei: KOMODO_* externe Notiz vs. Vaultwarden-Reihenfolge - Externe Docker-Netze fehlen in DR.md Phase 4 Stufe 1 - borg-ui-Container als impliziter Borg-Client im Bare-Metal-Bootstrap - Nextcloud-Restore-Skript ist da, ist aber noch nie real gelaufen (X-1) Keine produktiven Pfade beruehrt, kein Container gestartet, keine Skripte ausgefuehrt - reiner Doku-Drill.
22 KiB
DR Tabletop Drill - 2026-06-03
Trockenlauf gegen docs/DISASTER_RECOVERY.md Phase 0 bis 5 plus referenzierte
Runbooks (SERVICES_RECOVERY.md, RESTORE_MATRIX.md, SECRETS_MAP.md,
RESTORE_HANDBOOK.md, EXTERNAL_DEPENDENCIES.md).
Szenario: Bare-Metal-Ausfall. Unraid-Host und alle lokalen Festplatten sind weg. Operator hat: Laptop, Hetzner-Account, Vaultwarden-Export, Repo-Doku. Soft-Recovery (Host laeuft, Appdata futsch) ist eine Teilmenge dieser Findings.
Methode: kalter Lesetest. Kein Container gestartet, keine Skripte ausgefuehrt. Jeder Befund ist mit Repo-Datei und Zeile belegt. Spekulative "vielleicht unklar"-Befunde sind weggelassen.
Severity:
- CRITICAL - blockiert Wiederanlauf, ohne Workaround nicht loesbar
- HIGH - blockiert eine Phase, Workaround moeglich aber undokumentiert
- MED - kostet Zeit oder fuehrt zu vermeidbarem Fehler
- LOW - Konsistenz / Stil
Zusammenfassung
| ID | Phase | Severity | Thema |
|---|---|---|---|
| P0-1 | 0 | HIGH | Brueckenpfad Windows-Clone -> frischer Unraid-Host fehlt |
| P0-2 | 0 | HIGH | GitHub-Mirror-Zugang im DR ist nicht eigenstaendig dokumentiert |
| P1-1 | 1 | CRITICAL | Unraid-Flash-Restore: kein dokumentierter Extract-Pfad ohne laufenden Host |
| P1-2 | 1 | MED | Unraid-OS-Flash-Restore-Test laut Matrix nie real getestet |
| P2-1 | 2 | HIGH | KOMODO_* externe Operator-Notiz ist Pflichtquelle, Existenz nicht verifizierbar |
| P2-2 | 2 | HIGH | DR.md Phase 4 vs. SERVICES_RECOVERY.md Bootstrap-Reihenfolge widerspruechlich |
| P2-3 | 2 | MED | homelab_smtp_password.txt fehlt in DR.md Phase 2.6.1 |
| P2-4 | 2 | MED | n8n_encryption_key.txt fehlt in DR.md Phase 2.6.1 |
| P2-5 | 2 | LOW | Monitoring-/Filebrowser-Secrets fehlen in DR.md Phase 2.6.1 |
| P3-1 | 3 | HIGH | Borg-Client ohne borg-ui-Container ist nicht dokumentiert |
| P3-2 | 3 | HIGH | Borg-Passphrase-Bootstrap aus Offline-Sicherung nicht als expliziter Schritt |
| P3-3 | 3 | MED | Hetzner-Maintenance-Key aus Vaultwarden ist Henne-Ei im Bare-Metal |
| P4-1 | 4 | HIGH | Externe Docker-Netze in DR.md Phase 4 Stufe 1 nicht erwaehnt |
| P4-2 | 4 | HIGH | Cloudflare-LE-Rate-Limit-Risiko bei verlorenem letsencrypt-State |
| P4-3 | 4 | MED | traefik/dynamic/* als Phase-4-Pre-Check fehlt in der Reihenfolge |
| P4-4 | 4 | HIGH | Authelia "frische Postgres ohne Dump"-Pfad nicht beschrieben |
| P4-5 | 4 | LOW | Gitea in Stufe 2 hinter Postgres ist faktisch nicht noetig (SQLite) |
| P4-6 | 4 | HIGH | Komodo-Mongo Passwort-Lockout-Risiko bei restauriertem Datadir |
| P4-7 | 4 | MED | Komodo extra_hosts mit hardgecodeter LAN-IP bricht bei IP-Wechsel |
| P4-8 | 4 | HIGH | Stack-ENV-Wiederherstellung in Komodo praktisch nur manueller UI-Eintrag |
| P5-1 | 5 | LOW | Smoke-Tests in Phase 5 weniger streng als RESTORE_MATRIX |
| P5-2 | 5 | MED | Kein Verifikationspunkt fuer App-zu-DB-Verbindung nach Stack-ENV-Restore |
| X-1 | uebergreifend | HIGH | Nextcloud-Restore-Skript ist da, aber noch nie real ausgefuehrt |
Phase 0 - Repo-Zugang
P0-1 (HIGH) - Brueckenpfad Windows-Clone -> frischer Unraid fehlt
docs/DISASTER_RECOVERY.md:88-93 listet als Repo-Quellen: GitHub-Mirror,
lokaler Bare-Clone, lokaler Arbeits-Clone. SERVICES_RECOVERY.md:67-68
nennt den lokalen Operator-Clone unter G:\Gitea_Clone\homelab-infra\ als
Vorzug.
Luecke: der Pfad "wie kommt der Windows-Clone auf einen frisch installierten Unraid-Host" ist nicht beschrieben. Implizit: SMB-Share, USB-Stick, scp ueber LAN. Aber auf einem frisch aufgesetzten Unraid existiert noch keine funktionierende SMB-Konfiguration; SSH-Key vom Operator-PC ist nicht vorbereitet.
Vorschlag: Zwei Saetze in DISASTER_RECOVERY.md Phase 0 ergaenzen, wie der
Operator-Clone konkret zum Host kommt (USB-Stick + mkdir -p /mnt/user/services/homelab-infra && rsync -a aus Operator-Windows-PC, oder
direkt vom GitHub-Mirror per git clone https://github.com/... auf dem
Unraid-Host).
P0-2 (HIGH) - GitHub-Mirror-Zugang im DR
SECRETS_MAP.md:42 sagt, der GitHub-Push-Mirror-PAT liegt in den
Gitea-Mirror-Settings persistent unter /mnt/user/services/gitea/data.
EXTERNAL_DEPENDENCIES.md:18 nennt den Mirror als michaelkaleschke-spec/ homelab-infra und betont "privater" Push-Mirror.
Luecke: Wenn der Mirror privat ist, scheitert ein anonymer git clone
im DR-Bootstrap. Es gibt keine dokumentierte Notfall-Quelle fuer einen
Read-PAT/SSH-Key, der lokal beim Operator (nicht in Gitea, nicht im Repo)
verfuegbar ist.
Vorschlag in EXTERNAL_DEPENDENCIES.md: entweder explizit dokumentieren,
dass der Mirror lesend Public ist (DR-fit), oder einen Read-PAT in der
Vaultwarden-/Offline-Notiz neben der Borg-Passphrase als Bootstrap-Voraussetzung
benennen.
Phase 1 - Unraid und Shares
P1-1 (CRITICAL) - Unraid-Flash-Restore ohne laufenden Host
docs/DISASTER_RECOVERY.md:107 sagt: "Primaere lokale/off-site
Restore-Quelle fuer die bestehende Flash-Konfiguration ist das
Borg-Artefakt unraid-flash-config.tar.gz aus
/mnt/user/backups/borg/dumps/latest."
Henne-Ei: der Pfad ist auf den verlorenen Shares oder auf Hetzner. Hetzner-
Zugriff braucht einen funktionierenden Linux-Host mit Borg-Client und
Passphrase. Im Bare-Metal-Fall ist genau das nicht da. RESTORE_MATRIX.md
Tier 1 Zeile Unraid OS Flash (docs/RESTORE_MATRIX.md:29) sagt nur "Unraid
USB Flash Creator / neuer Boot-Stick" - das beschreibt die Stick-Erzeugung,
nicht den Extract des Borg-Artefakts.
Operativ: Operator braucht einen Laptop mit Borg-Client + Passphrase + SSH-Key fuer die Hetzner-Storage-Box. Das ist eine separat zu pflegende Operator-Workstation-Voraussetzung und ist in keinem Repo-Dokument als DR-Vorbedingung gelistet.
Vorschlag: In EXTERNAL_DEPENDENCIES.md oder DISASTER_RECOVERY.md
Abschnitt 3 als Pflichtposten aufnehmen: "Operator-Laptop mit installiertem
Borg-Client, SSH-Key fuer Hetzner und Zugriff auf die offline gesicherte
Passphrase". Inklusive Test, dass der Operator den Extract tatsaechlich
durchfuehren kann.
P1-2 (MED) - Unraid-OS-Flash-Restore-Test nie gelaufen
docs/RESTORE_MATRIX.md:140 Spalte "Letzter Restore-Test" fuer Unraid OS
Flash: - (kein Test). Das ist die Grundlage fuer Phase 1 und ist nie als
Smoke verifiziert. Empfehlung: einmaliger Test, der die Tar-Archiv-Struktur
gegen die erwarteten Flash-Pfade prueft (kein echter Boot-Test noetig).
Phase 2 - Secrets und Stack-ENV
P2-1 (HIGH) - KOMODO_* externe Operator-Notiz als Pflichtquelle
docs/SECRETS_MAP.md:132,138-143 macht den Komodo-Sonderfall klar: die
KOMODO_*-Secrets sind aus dem eigenen Mongo-Dump nicht rekonstruierbar,
solange Komodo nicht laeuft. Quellen: Vaultwarden ODER externe Notiz.
Im Bare-Metal-Fall ist Vaultwarden in DR.md Phase 4 Stufe 4, Komodo in Phase 4 Stufe 3. Damit ist die externe Operator-Notiz die einzige Pflichtquelle in der Reihenfolge.
Luecke: ob diese Notiz wirklich existiert und die 5 Werte (KOMODO_SECRET_KEY, KOMODO_WEBHOOK_SECRET, KOMODO_JWT_SECRET, KOMODO_MONGO_PASSWORD, KOMODO_PERIPHERY_PASSKEY) enthaelt, ist in keinem Repo-Dokument bestaetigt. Die Borg-Passphrase ist als "Operator-Bestaetigung 2026-05-26" dokumentiert; eine analoge Bestaetigung fuer die KOMODO_*-Notiz fehlt.
Vorschlag: gleiche Form wie Borg-Passphrase - eine Zeile in
EXTERNAL_DEPENDENCIES.md "Komodo-Stack-ENV-Notiz offline gesichert,
Operator-Bestaetigung YYYY-MM-DD".
P2-2 (HIGH) - Reihenfolgen-Inkonsistenz DR vs. SERVICES_RECOVERY
docs/SERVICES_RECOVERY.md:102 (Stufe C, Komodo-Bootstrap): "Vaultwarden
(sobald restauriert), externe Operator-Notiz, oder Komodo-Mongo-Dump (nur
wenn Mongo separat bereits gestartet ...)".
docs/DISASTER_RECOVERY.md:247-301 (Phase 4): Stufe 3 = Komodo, Stufe 4 =
Vaultwarden.
Wenn ein Leser sich an DR.md Phase 4 haelt, ist Vaultwarden nach Komodo fertig. Aber SERVICES_RECOVERY.md Stufe C setzt Vaultwarden als optionale Vorab-Quelle voraus. Ohne externe Notiz heisst das praktisch: Komodo kann nicht starten. Die Konsequenz steht nirgendwo explizit in DR.md.
Vorschlag: In DISASTER_RECOVERY.md Phase 4 Stufe 3 einen Hinweisblock
ergaenzen: "KOMODO_*-Werte muessen vor Stufe 3 aus externer Notiz oder
einer in Stufe 2 voraus gezogenen Vaultwarden-Instanz vorliegen. Default-
Pfad: externe Notiz."
P2-3 (MED) - homelab_smtp_password.txt fehlt in DR.md 6.1
docs/SECRETS_MAP.md:20 listet /mnt/user/appdata/secrets/ homelab_smtp_password.txt fuer Vaultwarden-SMTP. In DISASTER_RECOVERY.md
Abschnitt 6.1 (docs/DISASTER_RECOVERY.md:136-151) ist sie nicht
aufgefuehrt. Vaultwarden startet ohne, kann aber keine Einladungs-/
Benachrichtigungs-Mails versenden. Klein, aber unsichtbarer Folgefehler im
Familien-Onboarding-Pfad.
P2-4 (MED) - n8n_encryption_key.txt fehlt in DR.md 6.1
docs/SECRETS_MAP.md:58 listet /mnt/user/appdata/secrets/ n8n_encryption_key.txt. In DR.md 6.1 fehlt sie komplett.
SECRETS_MAP.md:135 macht die Folgen explizit: "Bei Verlust aller
Quellen: n8n startet, aber alle gespeicherten Credentials sind unbrauchbar".
Da n8n den GMX-Mail-Workflow fuer das Gitea-Micha/mails-Repo betreibt,
ist das ein direkter Workflow-Ausfall.
P2-5 (LOW) - Monitoring-/Filebrowser-Secrets fehlen in DR.md 6.1
docs/SECRETS_MAP.md:53-55: influxdb3_admin_token.json,
monitoring_grafana_admin_password.txt,
monitoring_grafana_influxdb_token.txt sowie
filebrowser_admin_password.txt sind nicht in DR.md 6.1. Tier-3-Apps,
Folge ist nur ein UI-Initialisierungs-Schritt nach Wiederanlauf. Keine
Critical-Konsequenz, aber Inkonsistenz.
Phase 3 - Borg-Extract
P3-1 (HIGH) - Borg-Client ohne borg-ui-Container
docs/RESTORE_HANDBOOK.md:30-33 sagt explizit: "Borg-Zugriff laeuft ueber
den vorhandenen borg-ui-Container".
Im Bare-Metal-Fall ist borg-ui selbst kalt (Tier 3, DR.md Phase 4 Stufe 5).
Es gibt keinen dokumentierten Pfad, wie der erste Borg-Extract ohne diesen
Container laeuft. Implizite Optionen: nativer Borg auf Unraid (Plugin),
docker run --rm borgbackup/borg, oder Operator-Laptop. Keine davon ist
benannt.
Vorschlag: In RESTORE_HANDBOOK.md Abschnitt 2 einen "Bare-Metal-Vorlauf"
ergaenzen, der den initialen Borg-Extract ohne borg-ui-Container
beschreibt - z. B. docker run --rm -v /mnt/user/backups/restore-lab:/restore borgbackup/borg ....
P3-2 (HIGH) - Borg-Passphrase-Bootstrap nicht als expliziter Schritt
docs/DISASTER_RECOVERY.md:68: "Host-Secret-Datei vorhanden und fuer
Borg-Zugriff verifiziert; externe Offline-Hinterlegung vom Operator am
2026-05-26 bestaetigt."
Praktisch heisst das: im Bare-Metal-Fall liest der Operator die Passphrase aus einem analogen Medium und tippt sie in den Borg-Client. Das ist ein Bootstrap-Schritt, der nicht als Schritt dokumentiert ist. Er steckt implizit in "extern bestaetigt".
Vorschlag: Ein nummerierter Bullet in DISASTER_RECOVERY.md Phase 3 ("Wenn
echte Daten aus Borg benoetigt werden"): "Schritt 1: Borg-Passphrase aus
Offline-Sicherung beschaffen. Wert wird nicht in Skripte oder Tickets
kopiert; nur in den interaktiven Borg-Aufruf eingegeben."
P3-3 (MED) - Hetzner-Maintenance-Key im Bare-Metal
docs/EXTERNAL_DEPENDENCIES.md:17: "Maintenance-Key liegt in Vaultwarden".
Im Bare-Metal-Bootstrap ist Vaultwarden Phase 4 Stufe 4. Damit ist der Key fuer die initiale Phase-3-Hetzner-Verbindung nicht zugaenglich. Implizit muss er ebenfalls offline gesichert sein (analog Borg-Passphrase).
Vorschlag: gleiche Form wie Borg-Passphrase - eine Operator-Bestaetigung
in EXTERNAL_DEPENDENCIES.md, dass der Hetzner-SSH-Key auch ausserhalb von
Vaultwarden offline verfuegbar ist. Sonst ist die "Vaultwarden"-Aussage
fuer Bare-Metal eine Falle.
Phase 4 - Bootstrap-Reihenfolge
P4-1 (HIGH) - Externe Docker-Netze in DR.md Phase 4 Stufe 1 nicht erwaehnt
docs/SERVICES_RECOVERY.md:82-84 Stufe A schreibt explizit: "Externe
Docker-Netze existieren oder werden erzeugt (frontend_net, backend_net).
Wenn nicht vorhanden: docker network create --driver bridge frontend_net
bzw. ... --internal backend_net."
docs/DISASTER_RECOVERY.md:252-260 Phase 4 Stufe 1 nennt nur Traefik,
AdGuard, Tailscale. Kein Hinweis auf externe Netze.
traefik/docker-compose.yml:70-76 deklariert frontend_net, backend_net,
monitoring_net als external: true. Ohne vorab erstellte Netze scheitert
der erste docker compose up mit "network frontend_net not found".
Vorschlag: In DISASTER_RECOVERY.md Phase 4 vor Stufe 1 einen Vorlauf
"Stufe 0 - Docker-Grundlage" einfuegen, der die Netzwerk-Erzeugung wie in
SERVICES_RECOVERY.md Stufe A explizit listet.
P4-2 (HIGH) - Cloudflare-LE-Rate-Limit-Risiko
docs/RESTORE_MATRIX.md:30 markiert letsencrypt korrekt als
Restore-relevant. docs/DISASTER_RECOVERY.md:240 listet
/mnt/user/appdata/traefik/letsencrypt ebenfalls als kritischen
Borg-Restore-Pfad.
Luecke: kein Hinweis auf den Praxisfall "LE-State verloren, frischer
Acme-Run". Let's Encrypt hat ein Rate-Limit von 50 Zertifikaten/Domain/
Woche und 5 Duplicate-Zertifikate/Woche. Bei einer Multi-Sub-Domain-
Konstellation wie *.kaleschke.info (15+ Hostnames) ist das beim
hektischen DR-Bootstrap erreichbar.
Vorschlag: In DISASTER_RECOVERY.md Phase 4 Stufe 1 einen Hinweis: "Bei
verlorenem oder unklarem acme.json zuerst gegen
acme-staging-v02.api.letsencrypt.org ausstellen lassen, erst nach
gruenem Smoke auf Production-CA umschalten." Ist eine Praesentations-
Aenderung in den Compose-Args, kein neuer Code.
P4-3 (MED) - traefik/dynamic/* als Pre-Check fehlt
docs/DISASTER_RECOVERY.md:357-365 Sektion 10 beschreibt die manuelle
Sonderregel fuer traefik/dynamic/*. Korrekt.
docs/DISASTER_RECOVERY.md:252-260 Phase 4 Stufe 1 verweist nicht auf
diese Sonderregel. Wer der Reihenfolge folgt und Sektion 10 nicht liest,
startet Traefik ohne Middlewares - alle 2FA-Routen brechen still.
Vorschlag: Cross-Reference in Phase 4 Stufe 1: "Vor docker compose up traefik pruefen, dass /mnt/user/appdata/traefik/dynamic/middlewares.yml,
tls.yml, dashboards.yml vorhanden sind (Sonderregel Sektion 10)."
P4-4 (HIGH) - Authelia "frische Postgres ohne Dump"-Pfad fehlt
docs/DISASTER_RECOVERY.md:267-275 Phase 4 Stufe 2 startet Postgres und
Authelia. Authelia erwartet eine Rolle authelia mit dem Passwort aus
authelia_postgres_password.txt. Im Restore-Pfad mit pg_dumpall --globals- only ist die Rolle abgedeckt.
Bei einem fresh-start (keine alten Daten, nur Container hochfahren) ist die Rolle nicht da. Postgres-Image legt sie nicht automatisch an. Authelia schlaegt mit "FATAL: role authelia does not exist" fehl.
Luecke: Der Initialisierungspfad fuer eine frische Postgres ohne pg_dumpall ist in der Doku nicht beschrieben. Im echten DR mit Borg ist das unwahrscheinlich, aber im Soft-Recovery oder Migrations-Drill schon.
Vorschlag: In DISASTER_RECOVERY.md Phase 4 Stufe 2 eine optionale
Anweisung: "Falls Postgres frisch ist (kein Dump-Restore), infra/ postgresql17/init/-Skripte oder manuelle CREATE ROLE/CREATE DATABASE-
Schritte ergaenzen."
P4-5 (LOW) - Gitea nach Postgres ist faktisch unnoetig
docs/DISASTER_RECOVERY.md:267-275 Phase 4 Stufe 2 ordnet Gitea hinter
Postgres ein. Gitea nutzt SQLite (gitea.sqlite.dump), nicht den shared
Postgres. Reihenfolge ist nicht falsch, aber irrefuehrend. Nicht kritisch.
P4-6 (HIGH) - Komodo-Mongo Passwort-Lockout-Risiko
ops/komodo/docker-compose.yml:18-20 zeigt: komodo-mongo initialisiert
sich bei leerem Datadir mit MONGO_INITDB_ROOT_PASSWORD_FILE aus
/mnt/user/appdata/secrets/komodo_mongo_password.txt.
Restore-Fall: Datadir aus Borg restauriert, Secret-Datei aus Borg restauriert - beide aus demselben Snapshot. OK.
Riskanter Fall: Datadir aus Borg, aber Secret-Datei aus einer anderen (neueren oder aelteren) Quelle. Mongo akzeptiert den Login nicht, Komodo laeuft nicht. Lockout. Doku erwaehnt diesen Pin-Punkt nicht.
Vorschlag: Hinweis in DISASTER_RECOVERY.md Phase 4 Stufe 3: "Mongo-
Datadir und komodo_mongo_password.txt muessen aus demselben Snapshot
kommen. Bei Mismatch: leeren Datadir und Re-Init, dann Daten aus
komodo-mongo.archive.gz per mongorestore."
P4-7 (MED) - Hardgecodete LAN-IP in extra_hosts
ops/komodo/docker-compose.yml:50 und :101 haben:
"git.kaleschke.info:192.168.178.58".
Bare-Metal-Recovery auf anderer Hardware oder veraenderter LAN-IP fuehrt zu stummem Fehler: Komodo-Core kann Gitea nicht ueber den Override erreichen, faellt auf AdGuard-DNS zurueck (wenn der schon laeuft) oder scheitert.
Vorschlag: kurzer Hinweis in DISASTER_RECOVERY.md Phase 4 Stufe 3: "Bei
geaenderter Host-LAN-IP extra_hosts-Werte in ops/komodo/docker-compose. yml vor compose up anpassen oder ueber .env parametrisieren."
P4-8 (HIGH) - Stack-ENV-Wiederherstellung praktisch manuell
docs/DISASTER_RECOVERY.md:188-195 sagt: "Wenn komodo-mongo.archive.gz
frisch ist, koennen die Werte beim Komodo-Restart aus dem Dump
zurueckgespielt werden, ohne dass jemand sie sieht."
docs/RESTORE_HANDBOOK.md:73-74 und docs/AUDIT_2026-05-25_TODO.md:20
machen den Daten-Mongo-Restore als "erledigt 2026-06-03" sichtbar - aber
NICHT als Teil des DR-Bootstraps. Komodo-Bootstrap im Trockenlauf benutzt
Wegwerf-Werte.
Praktisch heisst das: Im DR-Bootstrap (Phase 4 Stufe 3) startet Komodo
ohne den Mongo-Daten-Restore. Die KOMODO_* kommen aus externer
Notiz. Aber die Stack-ENVs fuer paperless/immich/mail-archiver/
speedtest (PAPERLESS_DBPASS etc.) muessen vor Stufe 4 wieder in
Komodo eingetragen sein. Wenn der Mongo-Daten-Restore nicht direkt nach
Komodo-Start passiert, gehen diese Werte manuell in die Komodo-UI.
Vorschlag: Klarstellung in DISASTER_RECOVERY.md Phase 4 zwischen Stufe
3 und Stufe 4: "Optionaler Mongo-Daten-Restore aus komodo-mongo.archive. gz per ops/restore-tests/komodo-mongo-restore-test.sh-Muster - dann
sind alle Stack-ENVs zurueck. Alternativ: Stack-ENVs manuell in Komodo-
UI eintragen, Quelle Vaultwarden (sobald Stufe 4 Vaultwarden laeuft -
Henne-Ei mit Paperless: Paperless-Start dann erst nach Vaultwarden, nicht
parallel)."
Phase 5 - Verifikation
P5-1 (LOW) - Smoke-Tests in DR.md weniger streng als Matrix
docs/DISASTER_RECOVERY.md:337-345 Phase 5.3 sagt z. B. "Vaultwarden
startet und ist erreichbar". docs/RESTORE_MATRIX.md:39 sagt: "Login-
Seite erreichbar, Tresor-Daten sichtbar". Das zweite ist faktisch der
echte Smoke-Test.
Geschmackssache, kein Bug. Empfehlung: DR.md auf die Matrix-Smokes verweisen statt eigene Kurzversion.
P5-2 (MED) - Kein Verifikationspunkt App-zu-DB-Verbindung
docs/DISASTER_RECOVERY.md:337-345 prueft App-Start, nicht DB-Auth-
Erfolg. Bei falschem PAPERLESS_DBPASS-Stack-ENV startet Paperless
moeglicherweise mit Error-Log und ist via Traefik nicht antwortend - aber
das fehlt als Pruefpunkt.
Vorschlag: Phase 5.3 ergaenzen: "Pro App: docker logs <app> zeigt keine
password authentication failed/FATAL: role does not exist-Eintraege."
Uebergreifende Findings
X-1 (HIGH) - Nextcloud-Restore-Skript existiert, ist aber ungetestet
ops/restore-tests/nextcloud-restore-test.sh und
ops/restore-tests/nextcloud-compose.test.yml existieren im Repo.
docs/RESTORE_MATRIX.md:147 Spalte "Letzter Restore-Test" fuer Nextcloud:
-, naechster Lauf **hoechste Prio**. docs/AUDIT_2026-05-25_TODO.md:18
fuehrt es als P1 "offen".
Damit ist der echte Tabletop-Gewinn: der Test ist nicht "noch zu bauen",
sondern "noch nie ausgefuehrt". Ein bash /mnt/user/services/homelab- infra/ops/restore-tests/nextcloud-restore-test.sh schliesst die letzte
Tier-2-Luecke.
Nicht-Findings
Was ich gepruft und als sauber verifiziert habe:
- Referenzierte Skripte existieren alle:
pre-backup-dumps.sh,gitea-bundle-mirror.sh,run-restore-checks.sh,komodo-bootstrap-test.sh,posture-check.sh, alle Restore-Test- Skripte fuer Tier-1 und Tier-2. - Pfadverweise zwischen DR.md, RESTORE_MATRIX.md, SECRETS_MAP.md,
SERVICES_RECOVERY.md sind konsistent (Borg-Dumps unter
/mnt/user/ backups/borg/dumps/latest, Secrets unter/mnt/user/appdata/secrets). - Drift-Erkennung Authelia (
services/authelia-diff.sh) ist inposture-checkintegriert (WORKFLOW.md:292). - GitHub-Mirror-Pfad und Gitea-Bundle-Mirror als Repo-Bootstrap-Quellen sind dreifach abgesichert (lokaler Clone, GitHub, Bundle).
- Tier-1-Postgres-Restore-Drill ist 2026-06-03 erfolgreich gelaufen
(
AUDIT_2026-05-25_TODO.md:19). ops/komodo/docker-compose.ymlist als Recovery-Anker getestet (SERVICES_RECOVERY.md:142-166).- Borg-Passphrase und Hetzner-Account-Hygiene sind Operator-bestaetigt
(
AUDIT_2026-05-25_TODO.md:46-47).
Vorschlag fuer Reihenfolge der Folge-Arbeit
- CRITICAL P1-1 zuerst - Operator-Laptop-Voraussetzung als DR-Pflichtposten dokumentieren. Eine Dokuzeile.
- HIGH P0-2 + P3-3 - klaeren, ob GitHub-Mirror lesend public ist und wo der Hetzner-Maintenance-Key offline liegt. Zwei Dokuzeilen oder eine echte Setup-Entscheidung.
- HIGH P2-1 - Operator-Bestaetigung "KOMODO_*-Notiz offline
gesichert YYYY-MM-DD" in
EXTERNAL_DEPENDENCIES.mdergaenzen (sobald real angelegt). - HIGH P4-1 + P4-2 - Vorlauf "Stufe 0 - Docker-Grundlage" und LE-Staging-Hinweis in DR.md Phase 4 einfuegen. Etwa 10 Zeilen Doku.
- HIGH X-1 -
nextcloud-restore-test.sheinmal scharf ausfuehren. Vermutlich ein Vormittag inklusive Report-Review. - HIGH P2-2 + P4-8 - Reihenfolgen-Konsistenz Komodo/Vaultwarden in DR.md eindeutig aufloesen.
- Rest in der Reihenfolge der Tabelle.
Punkte 1-4 sind reine Doku-Arbeit, keine Compose-/Runtime-Aenderung. Punkt 5 ist ein echter Restore-Lauf mit Report. Punkt 6 ist die substanziellste Doku-Aenderung in DR.md.
Reproduktion dieses Drills
Methode: kalter Lesetest gegen
- docs/DISASTER_RECOVERY.md
- docs/RESTORE_MATRIX.md
- docs/SECRETS_MAP.md
- docs/SERVICES_RECOVERY.md
- docs/RESTORE_HANDBOOK.md
- docs/EXTERNAL_DEPENDENCIES.md
- ops/komodo/docker-compose.yml
- traefik/docker-compose.yml
Verifizierte Skript-Existenz: ops/borg-ui/scripts/*, ops/restore-tests/*,
services/posture-check/*
Kein Container gestartet, kein Skript ausgefuehrt, keine produktiven
Pfade beruehrt.