diff --git a/docs/DR_DRILL_2026-06-03.md b/docs/DR_DRILL_2026-06-03.md new file mode 100644 index 0000000..5b91624 --- /dev/null +++ b/docs/DR_DRILL_2026-06-03.md @@ -0,0 +1,472 @@ +# 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. + +## 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. +```