Six files had outdated status notes that the F-09 first run on 2026-05-30 made wrong: - ops/restore-tests/komodo-bootstrap-runbook.md: "Erster echter Lauf steht noch aus" -> first run confirmed - ops/restore-tests/komodo-bootstrap-plan.md: "Noch offen vor dem ersten echten Lauf" section -> "Bestaetigte Laeufe" table with the --what-if and --keep-data runs - ops/restore-tests/immich-runbook.md: status note still said "Erster echter Lauf steht noch aus" although the Immich first run was 2026-05-27; correcting in the same sweep - docs/AUDIT_2026-05-25_TODO.md: Sprint 2 entry on Komodo bootstrap path no longer carries the "Trockenlauf-Skript bleibt als offene Folgeaufgabe" tail - docs/SERVICES_RECOVERY.md: replaced the "Trockenlauf-Idee (Doku-only, nicht ausgefuehrt)" section with the confirmed repo-script flow and marked the two "Naechste Aufgaben" rows about the dry-run as done - docs/RESTORE_DRILL_ROUTINE.md: Q2 2026 DR-Sanity-Check entry now splits Komodo-Bootstrap-Pfad (done) from the two still-open items (Gitea bundles, secrets inventory) No behavior change, only documentation consistency. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
10 KiB
Services Recovery - KalliLab CORE
Status: Initiale Recovery-Baseline 2026-05-26, aus dem Audit 2026-05-25 abgeleitet.
Verwandte Docs: docs/DISASTER_RECOVERY.md, docs/RESTORE_MATRIX.md, docs/STORAGE_LAYOUT.md, docs/SECRETS_MAP.md
Zweck
Der Share /mnt/user/services/ ist recovery-kritisch, weil dort GitOps- und Host-Automation-Pfade liegen. Dieses Dokument beschreibt, welche Services-Pfade gesichert werden muessen und wie ein Kaltstart ohne laufendes Komodo gedacht ist.
Kritische Pfade
| Pfad | Zweck | Kritikalitaet | Backup-Anforderung |
|---|---|---|---|
/mnt/user/services/homelab-infra |
Host-Repo-Clone fuer Automation/Posture | hoch | Borg + GitHub/Gitea Mirror |
/mnt/user/services/stacks |
Komodo Stack Workspaces | hoch | Borg, vor strukturellen Aenderungen extra sichern |
/mnt/user/services/gitea/git/repositories |
Gitea Repository-Inhalte | kritisch | Borg + separater Mirror <= 6 h |
/mnt/user/services/posture-check |
Hostseitig ausgefuehrte Checks | hoch | Borg + Repo-Abgleich |
/mnt/user/appdata/secrets |
Runtime Secrets | kritisch | Borg + ausgewählte analoge/off-system Kopien |
Gitea Repository Mirror
Ziel: Verlustfenster fuer /mnt/user/services/gitea/git/repositories/ auf maximal 6 Stunden begrenzen.
Optionen:
| Option | Bewertung |
|---|---|
git bundle je Repository auf zweites Medium |
Sehr gut fuer Git-Recovery, transparent, gut pruefbar |
rsync auf externe Platte oder zweiten Host |
Einfach, aber Ziel muss regelmaessig erreichbar und geprueft sein |
| Separates Borg-Repo mit kurzem Schedule | Konsistent zum bestehenden Backup, aber wieder Borg-/Passphrase-abhaengig |
Empfohlener Start:
ops/borg-ui/scripts/gitea-bundle-mirror.shauf dem Host ausfuehren.- Ziel
/mnt/user/backups/git-bundles/giteain Borg/off-site Scope aufnehmen. - Job alle 6 Stunden oder mindestens vor Borg ausfuehren.
- Stichprobe: ein Bundle in Wegwerfpfad klonen.
Erstlauf 2026-05-26: 4 Gitea-Bundles erzeugt, Checksums OK, homelab-infra.bundle in Restore-Lab geklont und git fsck sauber. Offen bleibt die dauerhafte Host-Zeitplanung.
Erfolgskriterium:
git clone /path/to/repo.bundle /tmp/repo-restore-test
git -C /tmp/repo-restore-test fsck
Komodo Bootstrap
Problemstellung
Komodo verwaltet alle Stacks per GitOps, ist aber selbst Teil des Recovery-Pfads. Ein kalter Host darf nicht voraussetzen, dass Komodo schon laeuft. Das ist das klassische Henne-Ei-Problem: Komodo darf sich nicht selbst aus dem Repo holen muessen, bevor es laufen kann.
Recovery-Anker (verbindlich)
Anker: ops/komodo/docker-compose.yml aus dem Repo.
Dieses Compose-File ist die einzige Quelle, aus der Komodo nach einem Kaltstart hochgefahren wird. Es wird nicht ueber Komodos eigenen Auto-Deploy-Pfad konsumiert.
Was der Anker bewusst NICHT ist:
- nicht der Komodo-Self-Stack (Komodo darf sich nicht selbst deployen).
- nicht der laufende Komodo-Workspace unter
/mnt/user/services/stacks/komodo/compose.yaml(kann driften, sieheHOMELAB_ARCHITECTURE_MASTER_V2.mdSektion 13, Drift-Recovery 2026-05-04). - nicht ein Gitea-Webhook (
komodo-Stack hat bewusstwebhook_enabled: false).
Quelle der Compose-Datei:
- Vorzug: lokaler Repo-Clone auf dem Operator-Windows-PC (
G:\Gitea_Clone\homelab-infra\). - Fallback: GitHub-Mirror
michaelkaleschke-spec/homelab-infra(siehedocs/EXTERNAL_DEPENDENCIES.md). - Letzter Fallback: Gitea-Bundles unter
/mnt/user/backups/git-bundles/gitea/homelab-infra.bundle(siehe Mirror-Abschnitt oben).
Wenn alle drei Quellen down sind, ist Recovery blockiert und das Problem ist nicht Komodo, sondern Repo-Verlust.
Kaltstart-Schritte
Der Wiederanlauf-Pfad ist linear; jeder Schritt hat ein eindeutiges Erfolgskriterium, bevor der naechste laeuft.
Stufe A - Host und Docker-Grundlage
- Unraid bootet; Array ist online; Shares
/mnt/user/appdata,/mnt/user/services,/mnt/user/backupssichtbar. - Docker-Daemon laeuft (
docker infoantwortet). - Externe Docker-Netze existieren oder werden erzeugt (
frontend_net,backend_net). Wenn nicht vorhanden:docker network create --driver bridge frontend_netbzw.... --internal backend_net.
Erfolgskriterium: docker network ls zeigt frontend_net und backend_net.
Stufe B - Repo-Quelle bereitstellen
- Repo-Clone aus dem bevorzugten Pfad bereithalten:
- lokaler Operator-Clone, oder
- frischer Clone aus GitHub-Mirror, oder
- Bundle-Restore aus
/mnt/user/backups/git-bundles/gitea/homelab-infra.bundle(git clone homelab-infra.bundle homelab-infra).
- Repo-Stand verifizieren:
git -C <pfad> log --oneline -1zeigt einen plausibel aktuellen Commit.
Erfolgskriterium: ops/komodo/docker-compose.yml ist auf dem Host lesbar.
Stufe C - Komodo-Secrets bereitstellen
Komodo braucht beim Start mehrere Secrets, die nicht aus dem Repo kommen. Restore-Reihenfolge gemaess docs/SECRETS_MAP.md:
- Host-Secrets unter
/mnt/user/appdata/secrets/wiederherstellen (aus Borg oder analog gesicherter Quelle). - Datei
/mnt/user/appdata/secrets/komodo_mongo_password.txtist Pflicht (Mongo-Initialisierung). - Stack-ENV-Werte
KOMODO_SECRET_KEY,KOMODO_WEBHOOK_SECRET,KOMODO_JWT_SECRET,KOMODO_MONGO_PASSWORD,KOMODO_PERIPHERY_PASSKEYmuessen als Host-.envneben dem Compose vorliegen. Quelle in dieser Reihenfolge: Vaultwarden (sobald restauriert), externe Operator-Notiz, oder Komodo-Mongo-Dump (nur wenn Mongo separat bereits gestartet und diestack-Collection lesbar ist).
Erfolgskriterium: Compose-Validierung laeuft ohne fehlende Variablen.
docker compose -f ops/komodo/docker-compose.yml config >/dev/null
Stufe D - Komodo starten
- Compose hochfahren:
docker compose -f ops/komodo/docker-compose.yml up -d
- Reihenfolge intern:
komodo-mongozuerst healthy, dannkomodo-core, dannkomodo-periphery. - Status pruefen:
docker ps --filter "name=komodo"
docker logs --tail 50 komodo-core
docker logs --tail 50 komodo-periphery
Erfolgskriterium: alle drei Container laufen; Komodo-Core meldet Bind auf Port 9120; Periphery meldet erfolgreiche Verbindung zu Core.
Stufe E - Web-UI und GitOps validieren
https://komodo.kaleschke.infoist erreichbar (Authelia-Bypass dokumentiert, native Komodo-Auth aktiv).- Komodo zeigt im Web-UI die bekannten Stacks aus Gitea (sobald Gitea ebenfalls laeuft; siehe
docs/DISASTER_RECOVERY.mdPhase 4 Stufe 2 vor Stufe 3). - Gitea-Webhooks gegen Komodo werden separat in der Phase-4-Reihenfolge geprueft, nicht als Teil des Komodo-Bootstraps.
Erfolgskriterium: Komodo-UI laedt, Periphery Online, mindestens ein Stack aus Gitea sichtbar.
Stufe F - Stacks in Tier-Reihenfolge aufnehmen
Erst nach erfolgreichem Komodo-Bootstrap werden produktive Stacks ueber den dokumentierten Stufenpfad in docs/DISASTER_RECOVERY.md Phase 4 hochgefahren (Traefik, AdGuard, Tailscale, dann PostgreSQL, Authelia, Redis, Gitea, dann Apps).
Trockenlauf (als Repo-Skript, bestaetigt)
Trockenlauf gegen Wegwerf-Pfade ist seit 2026-05-29 als Repo-Skript abgelegt: ops/restore-tests/komodo-bootstrap-{compose.test.yml,test.sh,plan.md,runbook.md}. Aufruf:
bash /mnt/user/services/homelab-infra/ops/restore-tests/komodo-bootstrap-test.sh --what-if # nur Plan
bash /mnt/user/services/homelab-infra/ops/restore-tests/komodo-bootstrap-test.sh --keep-data # echter Lauf
Erstlauf 2026-05-30 erfolgreich: SUCCESS, alle 5 Checks gruen (compose config valid, Mongo healthy, Mongo authenticated ping ok, Komodo Core HTTP 200, Test-Periphery running). Report unter /mnt/user/backups/restore-reports/komodo-bootstrap-2026-05-30.md. Produktive Komodo-Container, Mongo-Datadir und Secrets wurden nicht beruehrt.
Test-Isolation:
| Bereich | Wegwerf-Wert |
|---|---|
| Compose-Project | restoretest-komodo (isoliert von Produktions-Project komodo) |
| Test-Mongo-Datadir | /mnt/user/backups/restore-lab/komodo/mongo |
| Test-Port | 127.0.0.1:19120 (kein LAN, kein Traefik) |
| Test-Periphery | ohne docker.sock-Mount, ohne /mnt/user/services-Mount |
KOMODO_*-Secrets |
Wegwerf-Werte im Test-Compose, niemals produktive Werte |
Damit ist ops/komodo/docker-compose.yml als Recovery-Anker fuer Stufen A-F belegt tauglich, nicht nur angenommen tauglich.
Validierungs-Kommandos (Snapshot)
# Compose syntaktisch ok?
docker compose -f ops/komodo/docker-compose.yml config >/dev/null
# Komodo-Container vorhanden und laufend?
docker ps --filter "name=komodo" --format "table {{.Names}}\t{{.Status}}"
# Mongo Health?
docker exec komodo-mongo mongosh --quiet --eval 'db.adminCommand({ping:1}).ok'
# Core API up?
docker exec komodo-core sh -lc 'wget -q -O- http://127.0.0.1:9120/api/health || true'
# Periphery sichtbar?
docker logs --tail 50 komodo-periphery 2>&1 | grep -i "connected\|periphery"
Secrets Recovery Reihenfolge
Authoritativ ist docs/SECRETS_MAP.md. Fuer den Kaltstart ist diese Reihenfolge praktisch:
- Borg-Passphrase analog/off-system beschaffen.
- Borg-Repo-Zugang/SSH-Key wiederherstellen.
/mnt/user/appdata/secrets/aus Borg wiederherstellen.- Komodo Stack ENV / Recovery ENV wiederherstellen.
- Gitea Secrets und SSH-Material wiederherstellen.
- Traefik/Cloudflare Secret wiederherstellen.
- App-spezifische Secrets nach Tier-Reihenfolge wiederherstellen.
Break-glass Regeln
- Keine Secret-Werte in Git oder Tickets kopieren.
- Restore-Tests laufen in Wegwerfpfaden, nie direkt gegen produktive Pfade.
- Wenn Gitea und Komodo beide down sind, gewinnt der externe GitHub-Mirror als Repo-Quelle.
- Wenn Borg ohne Passphrase nicht entschluesselbar ist, ist Recovery blockiert. Die Offline-Sicherung wurde am 2026-05-26 vom Operator bestaetigt; bei Reviews nur pruefen, dass sie weiterhin auffindbar und lesbar ist.
Naechste Aufgaben
| Status | Aufgabe |
|---|---|
| erledigt (Skript + Host-Test) | Gitea-Bundle- oder Mirror-Mechanik final entscheiden |
| erledigt | Komodo-Bootstrap-Quelle finalisieren |
| erledigt (Doku) | Komodo-Kaltstart in linearen Stufen A-F dokumentieren |
| erledigt 2026-05-29 | Komodo-Trockenlauf-Skript in ops/restore-tests/ analog zu Immich vorbereiten |
| erledigt 2026-05-30 | Restore-Kommandos nach erstem Trockenlauf mit echten Pfaden ergaenzen |
| erledigt | Services-Recovery in docs/DISASTER_RECOVERY.md verlinken |