# 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 ` 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 | **erledigt 2026-06-03**: Nextcloud-Restore-Test scharf gelaufen, drei Iterationen (zwei Skript-Bugs gefixt), Endresultat SUCCESS mit HTTP 200, occ status ok, 126 DB-Tabellen. Damit ist Tier-2 vollstaendig belegt. | 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 ```text 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. ```