cfa02ce627
Add explicit stages A-F to docs/SERVICES_RECOVERY.md: host/docker baseline, repo source, secrets order, Komodo start, web/GitOps validation, tier stack rollout. Recovery anchor is ops/komodo/ docker-compose.yml; the self-stack is explicitly not the anchor. Link DISASTER_RECOVERY Phase 4 stage 3 to the new bootstrap section and the stack-env-only secrets section in SECRETS_MAP. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
203 lines
9.6 KiB
Markdown
203 lines
9.6 KiB
Markdown
# 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:
|
|
|
|
1. `ops/borg-ui/scripts/gitea-bundle-mirror.sh` auf dem Host ausfuehren.
|
|
2. Ziel `/mnt/user/backups/git-bundles/gitea` in Borg/off-site Scope aufnehmen.
|
|
3. Job alle 6 Stunden oder mindestens vor Borg ausfuehren.
|
|
4. 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:
|
|
|
|
```bash
|
|
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, siehe `HOMELAB_ARCHITECTURE_MASTER_V2.md` Sektion 13, Drift-Recovery 2026-05-04).
|
|
- nicht ein Gitea-Webhook (`komodo`-Stack hat bewusst `webhook_enabled: false`).
|
|
|
|
**Quelle der Compose-Datei:**
|
|
|
|
1. Vorzug: lokaler Repo-Clone auf dem Operator-Windows-PC (`G:\Gitea_Clone\homelab-infra\`).
|
|
2. Fallback: GitHub-Mirror `michaelkaleschke-spec/homelab-infra` (siehe `docs/EXTERNAL_DEPENDENCIES.md`).
|
|
3. 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**
|
|
|
|
1. Unraid bootet; Array ist online; Shares `/mnt/user/appdata`, `/mnt/user/services`, `/mnt/user/backups` sichtbar.
|
|
2. Docker-Daemon laeuft (`docker info` antwortet).
|
|
3. 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`.
|
|
|
|
Erfolgskriterium: `docker network ls` zeigt `frontend_net` und `backend_net`.
|
|
|
|
**Stufe B - Repo-Quelle bereitstellen**
|
|
|
|
1. 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`).
|
|
2. Repo-Stand verifizieren: `git -C <pfad> log --oneline -1` zeigt 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`:
|
|
|
|
1. Host-Secrets unter `/mnt/user/appdata/secrets/` wiederherstellen (aus Borg oder analog gesicherter Quelle).
|
|
2. Datei `/mnt/user/appdata/secrets/komodo_mongo_password.txt` ist Pflicht (Mongo-Initialisierung).
|
|
3. Stack-ENV-Werte `KOMODO_SECRET_KEY`, `KOMODO_WEBHOOK_SECRET`, `KOMODO_JWT_SECRET`, `KOMODO_MONGO_PASSWORD`, `KOMODO_PERIPHERY_PASSKEY` muessen als Host-`.env` neben dem Compose vorliegen. Quelle in dieser Reihenfolge: Vaultwarden (sobald restauriert), externe Operator-Notiz, oder Komodo-Mongo-Dump (nur wenn Mongo separat bereits gestartet und die `stack`-Collection lesbar ist).
|
|
|
|
Erfolgskriterium: Compose-Validierung laeuft ohne fehlende Variablen.
|
|
|
|
```bash
|
|
docker compose -f ops/komodo/docker-compose.yml config >/dev/null
|
|
```
|
|
|
|
**Stufe D - Komodo starten**
|
|
|
|
1. Compose hochfahren:
|
|
|
|
```bash
|
|
docker compose -f ops/komodo/docker-compose.yml up -d
|
|
```
|
|
|
|
2. Reihenfolge intern: `komodo-mongo` zuerst healthy, dann `komodo-core`, dann `komodo-periphery`.
|
|
3. Status pruefen:
|
|
|
|
```bash
|
|
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**
|
|
|
|
1. `https://komodo.kaleschke.info` ist erreichbar (Authelia-Bypass dokumentiert, native Komodo-Auth aktiv).
|
|
2. Komodo zeigt im Web-UI die bekannten Stacks aus Gitea (sobald Gitea ebenfalls laeuft; siehe `docs/DISASTER_RECOVERY.md` Phase 4 Stufe 2 vor Stufe 3).
|
|
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-Idee (Doku-only, nicht ausgefuehrt)
|
|
|
|
Ein bewusster Trockenlauf des Komodo-Bootstraps gegen Wegwerf-Pfade ist die naechste sinnvolle Reife-Stufe. Vorschlag:
|
|
|
|
| Schritt | Inhalt |
|
|
|---|---|
|
|
| 1 | Test-Compose aus `ops/komodo/docker-compose.yml` in `/mnt/user/backups/restore-lab/komodo/` kopieren |
|
|
| 2 | Test-`.env` mit Wegwerf-Secrets erzeugen (nicht produktive Werte!) |
|
|
| 3 | `docker compose -f .../restore-lab/komodo/docker-compose.yml -p restoretest-komodo up -d` |
|
|
| 4 | Smoke: Mongo healthy, Core antwortet auf `http://127.0.0.1:<test-port>/api/health`, Periphery verbindet |
|
|
| 5 | `docker compose -p restoretest-komodo down -v` und Restore-Lab bereinigen |
|
|
|
|
Der Trockenlauf ist **noch nicht** als Repo-Skript abgelegt. Er bleibt als Folgeschritt analog zum Immich-Restore-Test geplant.
|
|
|
|
### Validierungs-Kommandos (Snapshot)
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
1. Borg-Passphrase analog/off-system beschaffen.
|
|
2. Borg-Repo-Zugang/SSH-Key wiederherstellen.
|
|
3. `/mnt/user/appdata/secrets/` aus Borg wiederherstellen.
|
|
4. Komodo Stack ENV / Recovery ENV wiederherstellen.
|
|
5. Gitea Secrets und SSH-Material wiederherstellen.
|
|
6. Traefik/Cloudflare Secret wiederherstellen.
|
|
7. 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 |
|
|
| offen | Komodo-Trockenlauf-Skript in `ops/restore-tests/` analog zu Immich vorbereiten |
|
|
| offen | Restore-Kommandos nach erstem Trockenlauf mit echten Pfaden ergaenzen |
|
|
| erledigt | Services-Recovery in `docs/DISASTER_RECOVERY.md` verlinken |
|