Files
homelab-infra/docs/DR_DRILL_2026-06-03.md
T
Micha 9edd6c24e6 docs(dr): tabletop-folge - DR.md + EXTERNAL_DEPENDENCIES haerten
Reine Doku-Fixes nach DR-Tabletop 2026-06-03 und Operator-Antworten auf
vier offene Fragen.

DISASTER_RECOVERY.md:
- Abschnitt 3 Voraussetzungen: Operator-DR-Workstation als Pflichtposten
- Phase 0: privater GitHub-Mirror, Read-PAT/Deploy-Key, expliziter Repo-
  Bootstrap-Pfad Workstation -> Unraid
- Abschnitt 6.1: homelab_smtp_password.txt, n8n_encryption_key.txt,
  monitoring/influxdb/filebrowser Secrets nachgezogen
- Neuer Abschnitt 7.3: Borg-Extract ohne borg-ui (DR-Workstation oder
  docker run borgbackup/borg), Passphrase-Eingabe interaktiv
- Phase 4 neue Stufe 0 "Docker-Grundlage": docker network create
  frontend_net/backend_net/monitoring_net + dynamic/ Pre-Check
- Phase 4 Stufe 1: LE-Staging-Hinweis bei verlorenem acme.json
- Phase 4 Stufe 3 "Wichtige Stolperfallen": KOMODO_*-Quelle, Mongo-
  Datadir/Secret-Mismatch, extra_hosts-IP, Stack-ENV-Wiederherstellung
- Phase 5.3: App-DB-Verifikation per docker logs

EXTERNAL_DEPENDENCIES.md:
- GitHub-Mirror als privat klargestellt + Read-PAT/Deploy-Key Pflicht
- Operator-DR-Workstation als kritische Abhaengigkeit
- KOMODO_*-Notiz und GitHub-Read-PAT als noch nicht angelegt erfasst
- Hetzner-Maintenance-Key offline bestaetigt (Operator-Antwort 2026-06-03)
- Neuer Abschnitt "DR-Workstation Bare-Metal-Kit" mit konkretem Inhalt

AUDIT_2026-05-25_TODO.md:
- Vier neue P1-Operator-Aufgaben: KOMODO_*-Notiz, Read-PAT, DR-Workstation-
  Setup, Nextcloud-Restore-Test scharf laufen lassen

DR_DRILL_2026-06-03.md:
- Folge-Iteration-Tabelle: welcher Finding wo adressiert wurde

Operator-Aufgaben (nicht delegierbar) sind als P1 markiert. Nichts in
Runtime/Compose beruehrt, kein Container gestartet.
2026-06-03 16:00:00 +02:00

25 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 in posture-check integriert (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.yml ist 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

  1. CRITICAL P1-1 zuerst - Operator-Laptop-Voraussetzung als DR-Pflichtposten dokumentieren. Eine Dokuzeile.
  2. 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.
  3. HIGH P2-1 - Operator-Bestaetigung "KOMODO_*-Notiz offline gesichert YYYY-MM-DD" in EXTERNAL_DEPENDENCIES.md ergaenzen (sobald real angelegt).
  4. HIGH P4-1 + P4-2 - Vorlauf "Stufe 0 - Docker-Grundlage" und LE-Staging-Hinweis in DR.md Phase 4 einfuegen. Etwa 10 Zeilen Doku.
  5. HIGH X-1 - nextcloud-restore-test.sh einmal scharf ausfuehren. Vermutlich ein Vormittag inklusive Report-Review.
  6. HIGH P2-2 + P4-8 - Reihenfolgen-Konsistenz Komodo/Vaultwarden in DR.md eindeutig aufloesen.
  7. 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.

Folge-Iteration 2026-06-03 (Doku-Fixes im selben Aenderungsblock)

Direkt nach dem Drill und nach Operator-Antworten auf vier offene Fragen wurden folgende Findings im Repo adressiert. Operator-Aufgaben, die ich nicht selbst tun kann, sind als P1 in docs/AUDIT_2026-05-25_TODO.md aufgenommen.

ID Massnahme
P0-1 DR.md Phase 0 ergaenzt um "Operativer Pfad fuer den Repo auf den frisch installierten Unraid-Host" (USB/SMB/rsync); DR.md Abschnitt 3 mit Zeile "Operator-DR-Workstation"; EXTERNAL_DEPENDENCIES.md neuer Abschnitt "DR-Workstation Bare-Metal-Kit"
P0-2 EXTERNAL_DEPENDENCIES.md GitHub-Mirror-Zeile praezisiert (privat, Read-PAT/Deploy-Key Pflicht); DR.md Phase 0 verweist explizit darauf; offene Operator-Aufgabe in Audit-Restliste
P1-1 Operator-DR-Workstation als Voraussetzung in DR.md Abschnitt 3 und in EXTERNAL_DEPENDENCIES.md; konkrete Pflichtbestandteile (WSL2, Borg, SSH-Key) gelistet
P1-2 Bleibt offen als P3-Test in Restore-Backlog (kein Doku-Fix moeglich)
P2-1 KOMODO_*-Notiz als kritische Secret-Zeile in EXTERNAL_DEPENDENCIES.md mit Status "noch nicht angelegt"; Operator-Aufgabe in Audit-Restliste
P2-2 DR.md Phase 4 Stufe 3 ergaenzt um expliziten Hinweis "KOMODO_* aus externer Notiz oder voraus gezogener Vaultwarden"
P2-3 DR.md Abschnitt 6.1 um homelab_smtp_password.txt erweitert
P2-4 DR.md Abschnitt 6.1 um n8n_encryption_key.txt erweitert
P2-5 DR.md Abschnitt 6.1 um Monitoring-Grafana/InfluxDB-/Filebrowser-Secrets erweitert
P3-1 DR.md neuer Abschnitt 7.3 "Borg-Extract ohne borg-ui-Container" mit DR-Workstation- und Docker-Variante
P3-2 DR.md Abschnitt 7.3 nennt Passphrase-Eingabe explizit als interaktiven Bootstrap-Schritt
P3-3 EXTERNAL_DEPENDENCIES.md Review-Zeile 2026-06-03: Hetzner-Maintenance-Key auch offline bestaetigt
P4-1 DR.md Phase 4 neue Stufe 0 "Docker-Grundlage" mit docker network create Befehlen
P4-2 DR.md Phase 4 Stufe 1 LE-Staging-Hinweis bei verlorenem acme.json
P4-3 DR.md Phase 4 Stufe 0 nennt traefik/dynamic/* als Pre-Check
P4-4 Wird mit fresh-Postgres-Initialisierungsskripten ohne Doku-Aenderung nicht sinnvoll abgedeckt; bleibt als Doku-Hinweis offen, ist im realen Restore-Pfad mit pg_dumpall --globals-only abgedeckt
P4-5 LOW, nicht angepasst (Reihenfolge nicht falsch, nur irrefuehrend)
P4-6 DR.md Phase 4 Stufe 3 "Wichtige Stolperfallen": Mongo-Datadir/Secret-Mismatch und Re-Init-Pfad
P4-7 DR.md Phase 4 Stufe 3 "Wichtige Stolperfallen": extra_hosts-Anpassung bei IP-Wechsel
P4-8 DR.md Phase 4 Stufe 3 "Wichtige Stolperfallen": Stack-ENV-Wiederherstellung per mongorestore oder manuell
P5-1 LOW, nicht angepasst
P5-2 DR.md Phase 5.3 um docker logs-Verifikation der App-zu-DB-Verbindung erweitert
X-1 Nextcloud-Restore-Test als P1 in Audit-Restliste

Nicht angefasst: P1-2 (kein Doku-Fix moeglich), P4-4 (im echten Restore-Pfad ohnehin abgedeckt), P4-5 und P5-1 (LOW). Die offenen Operator-Aufgaben (KOMODO_*-Notiz, Read-PAT, DR-Workstation, Nextcloud-Restore) stehen jetzt in docs/AUDIT_2026-05-25_TODO.md als P1.

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.