8 Commits

Author SHA1 Message Date
renovate d8bcd65504 chore(deps): update docker.n8n.io/n8nio/n8n docker tag to v2.26.3 2026-06-11 16:20:20 +00:00
Micha a4f4696b0d docs: anchor documentation rules, rebuild index, archive proposal
- REPO_MAP.md: replace Arbeitsregel with 8 binding documentation rules
  (one fact one home, done leaves the working copy, file types, header
  convention, quarterly gardening)
- WORKFLOW.md Dokumentationspflicht and CLAUDE.md aligned to the rules
- docs/README.md index rebuilt for the consolidated state
- H drive docs merged into ops/h-drive-nearline/README.md (scheduled
  task + no-MIR rule added); docs/H_DRIVE_NEARLINE_PULL.md removed
- implemented proposal archived to docs/archive/2026/

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:14:11 +02:00
Micha 1fcdb68221 docs: consolidate restore documentation into ops/restore-tests
- merge RESTORE_HANDBOOK.md into ops/restore-tests/README.md (single
  operations doc; restore status lives only in RESTORE_MATRIX maturity
  table)
- RESTORE_MATRIX.md: extract embedded runbook drafts (261 -> 141 lines);
  unraid-flash and tailscale stubs become ops/restore-tests runbooks,
  adguard/redis checklists superseded by validated scripts
- delete six historical pre-first-run *-plan.md files (runbook + script
  are the source of truth since the validated first runs)
- SERVICES_RECOVERY: drop completed task table; DISASTER_RECOVERY:
  point related docs and section 11 to MASTER_TODO/schedule

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:11:16 +02:00
Micha 489a429316 docs: single status list - dissolve audit restliste, slim AI context
- MASTER_TODO.md is now the only status list: parked decisions point to
  DECISIONS.md, done log capped at 5 condensed entries
- delete AUDIT_2026-05-25_TODO.md (open items and parked decisions fully
  covered by MASTER_TODO/DECISIONS)
- AI_CONTEXT.md: drop duplicated status block, keep rules and pointers
- EXTERNAL_DEPENDENCIES.md: condense review log to recent entries
- fix references in DR_WORKSTATION_SETUP, EXTERNAL_OPERATOR_RUNBOOK,
  STORAGE_LAYOUT, REPO_MAP, docs/README

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:08:43 +02:00
Micha 513f41b852 docs: introduce DECISIONS.md decision register, slim architecture master
- new docs/DECISIONS.md (ADR-light): decisions migrated from master
  section 13, MASTER_TODO parked items, hardware inventory and audit
  restliste into one chronological register
- HOMELAB_ARCHITECTURE_MASTER_V2.md: section 13 replaced by pointer,
  section 9 condensed (502 -> 372 lines, target picture only)
- ROLLBACK.md: drop rollback recipes for already removed services
  (uptime-kuma, grafana/influx legacy, stirling/glance bootstrap notes)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:06:18 +02:00
Micha c80b51f585 docs: introduce docs/archive, remove finished sprint boards and generated report
- docs/archive/2026/ with index README: DR tabletop drill, workstation
  audits, HA/Ecowitt draft, pre-Borg backup audit, finished windows
  reinstall project docs
- delete weekend sprint boards (content preserved in MASTER_TODO done log
  and git history)
- untrack generated ops/policy-checks/last-report.md and gitignore it
- fix references (CLAUDE.md, docs/README.md, ops/windows-reinstall/README.md)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:02:57 +02:00
Micha 42ed59a4d7 docs: commit pending status updates from 2026-06-06 sprint wrap-up
Preserves uncommitted working-copy updates (Veeam recovery test done,
BitLocker decision, ACL rollout, freshness negative test) before the
documentation consolidation restructures these files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:00:25 +02:00
Micha 58c3324557 docs: add homelab documentation optimization proposal
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 06:36:53 +02:00
53 changed files with 952 additions and 1828 deletions
+3
View File
@@ -22,6 +22,9 @@
**/*.tgz **/*.tgz
**/*.zip **/*.zip
# Generated reports
ops/policy-checks/last-report.md
# Local/editor noise # Local/editor noise
.DS_Store .DS_Store
Thumbs.db Thumbs.db
+3 -2
View File
@@ -1,6 +1,6 @@
# Claude Code Context - Homelab Infra # Claude Code Context - Homelab Infra
Stand: 2026-05-04 Stand: 2026-06-11
Dieses Repository ist die GitOps-Quelle fuer das KalliLab CORE Homelab auf einem Unraid-Host. Es verwaltet Docker-Compose-Stacks fuer Core-Dienste, Security, Infrastruktur, Apps, Operations-Tools, Host-nahe Dienste und Traefik. Gitea Online ist die operative Quelle der Wahrheit; Komodo konsumiert den Git-Stand und deployed daraus. Dieses Repository ist die GitOps-Quelle fuer das KalliLab CORE Homelab auf einem Unraid-Host. Es verwaltet Docker-Compose-Stacks fuer Core-Dienste, Security, Infrastruktur, Apps, Operations-Tools, Host-nahe Dienste und Traefik. Gitea Online ist die operative Quelle der Wahrheit; Komodo konsumiert den Git-Stand und deployed daraus.
@@ -22,7 +22,7 @@ Zusaetzlich je nach Thema:
- Secrets: `docs/SECRETS_MAP.md` - Secrets: `docs/SECRETS_MAP.md`
- GitOps-/Komodo-/Runtime-Drift: `docs/GITOPS_DRIFT_RUNBOOK.md` - GitOps-/Komodo-/Runtime-Drift: `docs/GITOPS_DRIFT_RUNBOOK.md`
- Gesamtbild fuer KI-Agenten: `docs/AI_CONTEXT.md` - Gesamtbild fuer KI-Agenten: `docs/AI_CONTEXT.md`
- Home Assistant / Ecowitt / InfluxDB: `docs/HOME_ASSISTANT_INFLUXDB_ECOWITT.md` - Architektur-/Betriebsentscheidungen mit Begruendung: `docs/DECISIONS.md`
## Projektbeschreibung ## Projektbeschreibung
@@ -123,6 +123,7 @@ Standard-Rollback ist ein Ruecknahme-Commit oder gezielte Rueckaenderung mit Pus
## Arbeitsweise fuer Claude ## Arbeitsweise fuer Claude
- Erst lesen, dann handeln. - Erst lesen, dann handeln.
- Doku-Regeln aus `docs/REPO_MAP.md` einhalten: ein Fakt, ein Zuhause. Status nur in `docs/MASTER_TODO.md`, Entscheidungen nur in `docs/DECISIONS.md`, Erledigtes verlaesst die Arbeitskopie.
- Bei Unsicherheit Zustand messen, nicht erraten. - Bei Unsicherheit Zustand messen, nicht erraten.
- Aenderungen klein halten und nur den betroffenen Bereich anfassen. - Aenderungen klein halten und nur den betroffenen Bereich anfassen.
- Bestehende Doku und Repo-Konventionen bevorzugen. - Bestehende Doku und Repo-Konventionen bevorzugen.
+9 -186
View File
@@ -3,7 +3,7 @@
> **Single Source of Truth** für Docker-Netzwerkarchitektur, Sicherheitsregeln, Zielbild und Migration des Kallilabcore-Homelabs. > **Single Source of Truth** für Docker-Netzwerkarchitektur, Sicherheitsregeln, Zielbild und Migration des Kallilabcore-Homelabs.
> **Arbeitsregel für KI-Assistenten:** Dieses Dokument immer zuerst lesen, bevor Fragen zu Containern, Netzwerken, Traefik, Tailscale, Migration oder Security beantwortet werden. > **Arbeitsregel für KI-Assistenten:** Dieses Dokument immer zuerst lesen, bevor Fragen zu Containern, Netzwerken, Traefik, Tailscale, Migration oder Security beantwortet werden.
**Stand:** 2026-06-02 | **Aktueller Schwerpunkt:** GitOps / Doku-Synchronisierung / Reproduzierbare Deployments **Stand:** 2026-06-11 | **Aktueller Schwerpunkt:** GitOps / Doku-Synchronisierung / Reproduzierbare Deployments
--- ---
@@ -20,7 +20,7 @@
10. [Bekannte Ausnahmen und Begründungen](#10-bekannte-ausnahmen-und-begründungen) 10. [Bekannte Ausnahmen und Begründungen](#10-bekannte-ausnahmen-und-begründungen)
11. [Projektorganisation und Arbeitsmodus](#11-projektorganisation-und-arbeitsmodus) 11. [Projektorganisation und Arbeitsmodus](#11-projektorganisation-und-arbeitsmodus)
12. [Nutzung mit KI / Kontext-Regel](#12-nutzung-mit-ki--kontext-regel) 12. [Nutzung mit KI / Kontext-Regel](#12-nutzung-mit-ki--kontext-regel)
13. [Betriebserfahrungen und Entscheidungs-Log](#13-betriebserfahrungen-und-entscheidungs-log) 13. [Betriebserfahrungen und Entscheidungs-Log (ausgelagert)](#13-betriebserfahrungen-und-entscheidungs-log-ausgelagert)
--- ---
@@ -371,23 +371,7 @@ labels:
## 9. Historische Migration (abgeschlossen) ## 9. Historische Migration (abgeschlossen)
Die frühere Blockmigration aus der Portainer-/Dockerman-Phase ist fachlich abgeschlossen. Die Blockmigration aus der Portainer-/Dockerman-Phase ist abgeschlossen: Traefik laeuft labelbasiert ohne File-Provider-Service-Routen, Komodo ist alleiniger Stack-Manager, Portainer CE ist entfernt, Borg/Dumps/Restore-Tests sind produktiv. Entscheidungen und Hintergruende stehen in `docs/DECISIONS.md`; die Sprint-Historie liegt in Git.
Dieser Abschnitt dient nur noch als **historischer Vermerk**:
- Traefik läuft labelbasiert ohne Service-Routen im File-Provider.
- Komodo ist der einzige aktive Stack-Manager.
- Portainer CE ist entfernt.
- Borg/Borg UI, Dump-Automatisierung und Restore-Test sind produktiv eingeführt.
- Frühere Sprint-/Block-Checklisten werden hier **nicht mehr operativ gepflegt**.
Für den laufenden Betrieb gilt stattdessen:
- Zielbild und Architektur in diesem Dokument
- Git-/Komodo-Ablauf in `docs/WORKFLOW.md`
- fachliche Änderungen in der jeweils betroffenen Stack-Doku
- Entscheidungen und besondere Umstellungen im Entscheidungs-Log unten
## 10. Bekannte Ausnahmen und Begründungen ## 10. Bekannte Ausnahmen und Begründungen
| Container | Ausnahme | Begründung | | Container | Ausnahme | Begründung |
@@ -464,176 +448,15 @@ Damit ist sofort klar:
--- ---
## 13. Betriebserfahrungen und Entscheidungs-Log ## 13. Betriebserfahrungen und Entscheidungs-Log (ausgelagert)
### Fix Common Problems Plugin entfernt (2026-06-03) Architektur- und Betriebsentscheidungen werden seit 2026-06-11 zentral in
`docs/DECISIONS.md` gefuehrt (ADR-light: Entscheidung, Kontext, Review-Trigger).
Befund: Drei `grep -R ... /usr/local/emhttp`-Prozesse liefen seit ~7 Tagen durchgehend mit je 100 % CPU (TIME+ 177-179 h). Status `R`, von PID 1 adoptierte Zombies einer laengst beendeten Fix-Common-Problems-(FCP)-Scan-Session. Folge: konstante Load 14.6 auf 12 Cores, IOWAIT-Peaks bis 55 %, USB-Flash unter Dauer-IO. Dieses Dokument haelt nur noch das Zielbild. Neue Entscheidungen werden dort
eingetragen; hier aendert sich nur etwas, wenn das Zielbild selbst betroffen
Ursache: Unraids `/usr/local/emhttp` enthaelt Symlinks `mnt -> /mnt` (mehrere TB Array) und `boot -> /boot` (USB-Flash). GNU `grep -R` dereferenziert Symlinks rekursiv. Ein FCP-Scan-Schritt (`/etc/cron.daily/fix.common.problems.sh -> scripts/scan.php`) hat dadurch effektiv die gesamte Array-Struktur gegrept und ist beim ersten Treffer-Loop haengen geblieben. Der Lock `/tmp/fix.common.problems/scanRunning` war vom 2026-06-03 04:40 - jeder weitere Daily-Cron-Run wuerde dasselbe Verhalten reproduzieren. ist (Netze, Zugangsmodell, Ausnahmen in Sektion 10).
Massnahme: FCP-Plugin per `plugin remove fix.common.problems.plg` deinstalliert. Cron-Eintrag, Plugin-Verzeichnis und `/tmp`-Reste sauber. Load fiel innerhalb Minuten auf 1.08 (1-min).
Entscheidung: FCP wird bewusst **nicht** wieder installiert. Begruendung:
- Restliche Risiken werden bereits ueber andere Wege abgedeckt: Scrutiny (Laufwerks-SMART), Monitoring-Stack (Container-Health, Prometheus-Alerts, Blackbox), Posture-Check (Filesystem-/Drift-/Authelia-Audit), Critical-Events-Watcher (`services/posture-check/docker-critical-events.sh`).
- FCP ist ein externes Community-Plugin und nicht Teil der Repo-managed GitOps-Welt; Verhalten haengt von einer Online-Templates-Datei ab.
- Ein einmaliges Hang-up reicht, um die Flash-Drive 7 Tage lang zu thrashen - das Verhaeltnis Nutzen/Risiko ist negativ.
Folgen fuer Doku: Eintrag in `docs/AUDIT_2026-05-25_TODO.md` unter "Zuletzt geschlossen"; FCP taucht nicht mehr als Voraussetzung in DR/Monitoring-Pfaden auf, da es nie produktiv referenziert war.
### Plex Server Reclaim und LAN-only-Profil (2026-05-28)
Befund: Die `Preferences.xml` des Plex-Servers war seit dem 18.05.2026 13:18 jungfraeulich (391 Bytes, ohne `PlexOnlineMail`/`PlexOnlineUsername`/`PlexOnlineToken`). Der Server war damit nicht mit einem Plex.tv-Account geclaimt, obwohl die Smart-TVs ueber LAN-Discovery (mDNS/Plex-GDM) weiter funktionierten. Beim Login als `Xeridos` ueber `app.plex.tv` meldete der Server "Keine Berechtigung", weil kein Owner registriert war. Zusaetzlich war die `library_sections`-Konfiguration leer (Backups vom 19./22./28.05. ebenfalls ~370 KB statt MBs/GBs); die Bibliotheks-Konfiguration war seit dem 18.05. weg, die Filmdateien unter `/mnt/user/media/*` blieben aber intakt (~833 Verzeichnisse, davon `movies/` 1.4 TB und `Heimatfilme/` 300 GB).
Reclaim:
- Operator-Claim-Token via `https://www.plex.tv/claim` als `Xeridos` erzeugt.
- Plex-Container per `PLEX_CLAIM=claim-... docker compose up -d --force-recreate plex` am Host-Pfad `/mnt/user/services/stacks/plex/host-services/plex` neu erstellt. Token wurde **nur** als Shell-Inline-ENV mitgegeben, **nicht** in eine `.env`-Datei, **nicht** in die Compose, **nicht** in die Komodo-Stack-ENV geschrieben.
- Nach Erfolg: zweiter `docker compose up -d --force-recreate plex` ohne `PLEX_CLAIM`, damit der verbrauchte Token nicht im `docker inspect`-ENV-Snapshot persistiert.
- Bash-History defensiv geleert.
Endstand:
- `PlexOnlineUsername="Xeridos"`, `PlexOnlineMail="michideheld@gmx.de"`, `PlexOnlineHome="1"`.
- Bibliotheken neu angelegt via Plex-Web → Verwalte Mediatheken → `/data/movies`, `/data/Heimatfilme` etc.
- `PublishServerOnPlexOnlineKey="0"` (Remote Access deaktiviert), Plex-Relay aus.
- 2026-06-06: Externer Komfortzugriff ueber `https://plex.kaleschke.info` via Traefik ergaenzt. Das ist **kein** Plex-Remote-Access und keine direkte FRITZ!Box-Freigabe auf `32400`; Plex bleibt hinter Traefik/443 und nutzt native Plex-Auth.
Konsequenzen fuer Doku/Betrieb:
- Plex-Home-Familien-Profil ("Familie") muss bei Bedarf neu eingeladen werden; war ohnehin nicht aktiv genutzt.
- Watch-State aus der Zeit vor dem 18.05. ist nicht recoverbar; Filme/Serien laufen bei Wiederaufruf bei 00:00 los.
- `host-services/plex/docker-compose.yml` enthaelt weiter `PLEX_CLAIM: ${PLEX_CLAIM:-}`, damit ein zukuenftiger Reclaim ohne Repo-Aenderung moeglich ist.
### Traefik — Wechsel zu reinen Docker-Labels (2026-03-28)
Die statischen File-Provider-Konfigurationen in `/mnt/user/appdata/traefik/dynamic/` wurden vollständig bereinigt:
- **Gelöscht:** `immich.yml`, `gitea.yml`, `mealie.yml`, `scrutiny.yml`, `vaultwarden.yml.bak`
- **Verbleibend (notwendig):** `middlewares.yml`, `tls.yml`, `dashboards.yml`
**Hintergrund:** Die alten File-Provider-Configs haben `@file`-Routen mit `@docker`-Routen konkurrieren lassen. In Traefik v3 gewinnt der File-Provider und hat z.B. Immich auf die falsche IP geroutet (Bad Gateway). Nach Löschung läuft Traefik ausschließlich auf Docker-Labels.
**Regel:** Neue Dienste ausschließlich via Docker Compose Labels konfigurieren. Keine neuen `.yml`-Dateien im `dynamic/`-Verzeichnis für Service-Routen anlegen.
### Komodo — Ablösung von Portainer als Stack-Manager (2026-03-28)
Komodo ist nun der primäre GitOps-Stack-Manager:
- **Komodo Core** läuft als Docker-Stack (`ops/komodo/docker-compose.yml`)
- **Komodo Periphery** läuft auf dem Unraid-Host für direktes Server-Management
- Stacks werden via Gitea synchronisiert und über Komodo deployed
- Portainer CE ist abgeschaltet; Komodo ist der alleinige aktive Stack-Manager
**Betriebsregel:** Alle Stack-Änderungen laufen über Git; Komodo konsumiert nur den Stand aus Gitea.
**Zugangsregel:** Komodo bleibt bewusst bei nativer Authentifizierung ohne pauschal vorgeschaltete ForwardAuth-Middleware vor dem gesamten Router. Hintergrund sind die gemischten UI-, API-, Webhook- und Periphery-Endpunkte unter derselben Domain.
### Komodo Self-Stack Drift-Recovery (2026-05-04)
- Befund: `komodo-core` und `komodo-periphery` liefen aus temporaeren `/tmp/*repair.yml`-Dateien, waehrend `komodo-mongo` auf den fehlenden persistenten Pfad `/mnt/user/services/stacks/komodo/compose.yaml` verwies.
- Recovery: Repair-YAMLs und Runtime-ENV wurden unter `/mnt/user/appdata/komodo/_drift_backup_2026-05-04/` gesichert; eine zusaetzliche Recovery-ENV liegt unter `/mnt/user/appdata/secrets/_komodo_stack_env_recovery_2026-05-04.env` und ist als temporaeres Tier-1-Secret-Material zu behandeln.
- Der persistente Self-Stack wurde unter `/mnt/user/services/stacks/komodo/compose.yaml` aus `ops/komodo/docker-compose.yml` wiederhergestellt. Die hostseitige `.env` bleibt ausserhalb von Git.
- Reconcile-Regel: Bei Self-Stack-Drift keinen pauschalen `docker compose up -d` ausfuehren, wenn der Dry-run `komodo-mongo` recreaten wuerde. Core und Periphery koennen gezielt mit `--no-deps` neu erstellt werden, Mongo bleibt dabei unangetastet.
- Ergebnis: Alle drei Komodo-Container zeigen wieder auf `/mnt/user/services/stacks/komodo/compose.yaml`; Mongo blieb waehrend der Rueckfuehrung healthy.
### AdGuard Home — Ablösung von Pi-hole (2026-03-28)
`binhex-official-pihole` wurde entfernt und durch `AdGuard Home` + `unbound` ersetzt:
- AdGuard läuft als Git-Stack (`host-services/Adguard/docker-compose.yml`)
- Netzwerke: `dns_net` (feste IP 172.23.0.3) + `frontend_net`
- Port 53 (DNS) direkt gebunden — dokumentierte Ausnahme
- Admin-UI direkt gebunden via Tailscale-IP `100.80.98.33:8082` auf Container-Port 80 — 2026-05-26 bewusst als einfache Operator-Entscheidung ohne Traefik-/2FA-Umstellung
- `unbound` läuft weiterhin als Upstream-Resolver in `dns_net`
### diun — Entfernung (2026-03-28)
`diun` (Docker Image Update Notifier) wurde deinstalliert:
- Stack gelöscht
- Orphan-Netzwerk `diun_diun_default` bereinigt
- Repo-Eintrag `infra/diun/` aus Git entfernt
Update-Monitoring kann über Komodo's eingebaute Update-Notifications abgedeckt werden.
### ntfy — Push-Notifications (Git-Stack)
`ntfy` läuft als Git-Stack (`apps/ntfy/docker-compose.yml`):
- `ntfy.kaleschke.info` via Traefik
- `NTFY_UPSTREAM_BASE_URL: https://ntfy.sh` für mobile Push-Notifications
- `NTFY_BEHIND_PROXY: true` korrekt gesetzt
### immich_default — internal: true gesetzt (2026-03-29)
`immich_default` wurde von `external: true` auf ein Compose-verwaltetes internes Netz umgestellt:
- **Vorher:** `external: true` (manuell erstellt, falsche Labels `com.docker.compose.network=default`)
- **Nachher:** Compose-managed, `internal: true`, `driver: bridge`, korrekte Labels
- Durchgeführt via: manuelles `docker stop` der Containers → `docker network rm immich_default` → Komodo Redeploy
- Ergebnis: alle Immich-Container (`immich_postgres`, `immich_redis`, `immich_machine_learning`) sind jetzt vom Internet isoliert; nur `immich_server` hat zusätzlich `frontend_net` für Traefik
### Secrets in Komodo Stacks
Host-Pfade in `env_file` (z.B. `/mnt/...`) sind in Git-Stacks nicht verfügbar. Standardlösung: Stack Environment Variables + `${VARIABLE_NAME}` in der Compose.
**Regel:** Wenn `_FILE` nicht unterstützt wird → Stack Environment Variable. Kein Secret im Git.
**Bewusste Ausnahme:** `paperless-ngx` bleibt fuer `PAPERLESS_DBPASS` und `PAPERLESS_REDIS` vorerst bei Stack Environment Variables. Eine Umstellung auf `_FILE` ist fachlich denkbar, wird aber nicht gegen den aktuell stabilen Produktionsstand erzwungen.
### Borg UI / BorgBase (2026-04-12)
- `borg-ui` läuft als Admin-Dienst in `ops/borg-ui/docker-compose.yml`
- nur `frontend_net`, weil Web-UI + externer SSH-Zugang zu BorgBase benötigt werden
- keine direkten Host-Ports; Zugriff ausschließlich via Traefik + Middleware über `borg.kaleschke.info`
- breite Restore-/Backup-Mounts bewusst gesetzt; inklusive `/local/secrets` fuer Disaster Recovery, separates Restore-Ziel unter `/mnt/user/appdata/borg-ui/restore`
- kein separater Borg-CLI-Container nötig, da Borg UI die Borg-CLI bereits im Container mitbringt
| Container | `_FILE` Support |
|---|---|
| Vaultwarden | ✅ ja |
| PostgreSQL | ✅ ja |
| code-server | ✅ ja (`PASSWORD_FILE`) |
| Immich Postgres | ✅ ja (`POSTGRES_PASSWORD_FILE`) |
| Mealie | ✅ ja (`POSTGRES_PASSWORD_FILE`) |
| paperless-ngx | ❌ nein für DB-Pass → Stack ENV |
### Reproduzierbare Deployments (2026-04-17)
Mutable Tags wie `latest`, `stable`, `release` oder reine Major-Tags wurden auf die **aktuell laufenden Digests** eingefroren. Das ist bewusst **kein Upgrade-Mechanismus**, sondern dient dazu, den heute funktionierenden Laufzeitstand exakt im Repo festzuhalten. Echte Versions-Upgrades bleiben ein eigener, geplanter Schritt.
### Stateful Digest-Pinning (2026-05-05, ergaenzt 2026-05-16)
- Tier-1/stateful Basisdienste werden bevorzugt mit sprechendem Minor-/Patch-Tag plus Digest gepinnt, z. B. `postgres:17.9@sha256:...` oder `mongo:7.0.32@sha256:...`.
- Redis-Caches sind seit dem Hardening-Sprint 2026-05-16 auf `redis:7.4-alpine@sha256:...` vereinheitlicht. Updates erfolgen bewusst stackweise mit Smoke-Test.
- Bereits versionierte Apps koennen optional spaeter ebenfalls Digests erhalten; dieser Schritt ist getrennt vom Datenhalter-Pinning.
### Nextcloud und Stirling-PDF (2026-04-19)
- `nextcloud` wird bewusst **nicht** als AIO-Stack gebaut, sondern als klassischer Docker-Microservice-Stack mit eigenem PostgreSQL und eigenem Redis. Das passt besser zum bestehenden GitOps-/Compose-Modell des Repos.
- `nextcloud` bleibt bei nativer App-Authentifizierung ohne zentrale ForwardAuth-Middleware vor dem Router, damit Browser-Login, Desktop-/Mobile-Clients sowie WebDAV/CardDAV sauber funktionieren.
- `stirling-pdf` wird als geschuetzter Tool-Stack hinter `authelia@file,secure-headers@file` betrieben; die interne Stirling-Login-Funktion bleibt deaktiviert, um Doppel-Login zu vermeiden.
### BentoPDF und Monitoring-Zielstack (2026-04-30, aktualisiert 2026-05-17)
- `bentopdf` ersetzt repo-seitig `stirling-pdf` auf der bestehenden Domain `pdf.kaleschke.info`, bleibt aber bis zum bewussten Komodo-Deploy nur vorbereitet.
- BentoPDF benoetigt fuer Office-Konvertierung die Cross-Origin-Isolation-Header `Cross-Origin-Opener-Policy: same-origin` und `Cross-Origin-Embedder-Policy: require-corp`; diese werden per Traefik-Docker-Middleware gesetzt.
- `monitoring/` ist der zentrale Zielstack fuer Prometheus, Loki, Promtail, Grafana, node-exporter, cAdvisor und InfluxDB 3 Core.
- `monitoring-grafana` wird als geschuetztes Monitoring-UI unter `monitoring.kaleschke.info` betrieben.
- `monitoring-influxdb3-core` bleibt ohne Traefik-/Public-Route; fuer interne Writer wie Home Assistant kann Port `8181` per `INFLUXDB_BIND_IP` auf eine LAN-Adresse gebunden werden.
- Fuer dieses Port-Publishing nutzt `monitoring-influxdb3-core` zusaetzlich `monitoring_influx_lan`. Das ist keine Public-App-Freigabe und ersetzt nicht die Token-Authentifizierung.
- InfluxDB 3 Core nutzt einen festen Versionstag statt `latest`, weil der InfluxDB-`latest`-Tag versionsstrategisch im Umbruch ist.
- Die alten Pfade `ops/grafana-influxdb` und `ops/loki` wurden am 2026-05-26 aus dem aktiven Repo entfernt; `monitoring/` ist der einzige Observability-Zielstack.
- Uptime Kuma wurde nach erfolgreichem Blackbox-/Grafana-Smoke-Test entfernt; `monitoring/` ist die Quelle fuer HTTP-Erreichbarkeit und Alerts.
### Monitoring-Logging-Baseline (2026-05-17)
- `monitoring-loki` laeuft intern auf `monitoring_net`, ohne Traefik-Route und ohne Host-Port.
- `monitoring-promtail` sammelt Docker-Logs ueber `/var/run/docker.sock:ro` und `/var/lib/docker/containers:ro` und schreibt sie an Loki.
- `monitoring-grafana` bekommt provisionierte Datasources fuer Prometheus, Loki und InfluxDB 3 Core.
- Loki-Logdaten sind Diagnosematerial mit begrenzter Retention, keine primaere Restore-Quelle.
### Authelia ohne Redis-Session-Backend (2026-05-04)
- Authelia nutzt PostgreSQL fuer persistente Storage-Daten, aber bewusst kein Redis-Session-Backend.
- Das haelt den Tier-1-Auth-Pfad einfacher; nach einem Authelia-Restart muessen aktive Sessions neu aufgebaut werden.
- `infra/redis` ist historisch als "shared Cache" angelegt, wird aber faktisch nur von Paperless als App-Cache genutzt. Immich, Nextcloud und Mealie betreiben jeweils eigene Redis-Instanzen in ihren App-internen Netzen; Authelia laeuft bewusst ohne Redis. Eine spaetere Konsolidierung in `apps/paperless/` (analog zu Mealie/Immich/Nextcloud) bleibt fachlich denkbar, ist aber kein priorisierter Schritt.
### ddns-updater — Netz-Ausnahme
Bleibt bewusst in `frontend_net` statt `backend_net`, weil `backend_net` `internal: true` ist und ddns-updater die Cloudflare-API erreichen muss.
### mail-archiver — Hybrid-Dienst
Benötigt `backend_net` (PostgreSQL) + `frontend_net` (IMAP-Abruf von GMX/Gmail). Kein reiner Backend-Dienst. Die Web-UI ist via Traefik unter `mail.kaleschke.info` erreichbar und wird durch `authelia@file,secure-headers@file` plus App-eigene Auth geschuetzt.
### Netzwerk-Standard für Apps mit Datenbanken
- App → `frontend_net` + internes Netzwerk
- Datenbank → nur internes Netzwerk (`internal: true`)
Beispiel (Mealie): `mealie``frontend_net` + `mealie_internal`, `mealie-postgres` → nur `mealie_internal`.
--- ---
## Schlussformel ## Schlussformel
Dieses Dokument ist keine lose Notiz, sondern das **operative Masterdokument** für die Docker- und Zugriffsarchitektur des Homelabs. Dieses Dokument ist keine lose Notiz, sondern das **operative Masterdokument** für die Docker- und Zugriffsarchitektur des Homelabs.
+1
View File
@@ -66,6 +66,7 @@ Bei Hardware-, Netzwerk-, Provider- oder Kapazitaetsfragen zusaetzlich:
## Status ## Status
- Offene Punkte stehen ausschliesslich in `docs/MASTER_TODO.md`; Entscheidungen mit Begruendung in `docs/DECISIONS.md`.
- Komodo ist der primaere und einzige produktive Stack-Manager. - Komodo ist der primaere und einzige produktive Stack-Manager.
- Komodo bleibt bewusst bei nativer Authentifizierung; zentrale Traefik-Auth wird dort nicht pauschal vorgeschaltet. - Komodo bleibt bewusst bei nativer Authentifizierung; zentrale Traefik-Auth wird dort nicht pauschal vorgeschaltet.
- Portainer CE ist abgeschaltet und kein Teil des aktiven Betriebs mehr. - Portainer CE ist abgeschaltet und kein Teil des aktiven Betriebs mehr.
+1 -1
View File
@@ -1,6 +1,6 @@
services: services:
n8n: n8n:
image: docker.n8n.io/n8nio/n8n:2.26.2@sha256:61ba01bc5e39304bbc928c9dbecd938c3a5cc1331b68affba6a34d0f654c43d9 image: docker.n8n.io/n8nio/n8n:2.26.3@sha256:51ac1d08178e635a593368f0947532990e55c14342ac781c8d77538daae859c8
container_name: n8n container_name: n8n
restart: unless-stopped restart: unless-stopped
+13 -40
View File
@@ -1,8 +1,10 @@
# AI Context # AI Context
Stand: 2026-06-05 Typ: Einstieg/Index · Stand: 2026-06-11 · Status: aktiv
Kurzer Kontext fuer KI-Agenten. Nicht als Ersatz fuer die echten Runbooks lesen. Kurzer Kontext fuer KI-Agenten. Nicht als Ersatz fuer die echten Runbooks lesen.
Diese Datei enthaelt bewusst **keinen** Arbeitsstand mehr — Status nur in
`docs/MASTER_TODO.md`, Entscheidungen nur in `docs/DECISIONS.md`.
## Systembild ## Systembild
@@ -20,6 +22,7 @@ Kurzer Kontext fuer KI-Agenten. Nicht als Ersatz fuer die echten Runbooks lesen.
3. betroffene Compose-Datei 3. betroffene Compose-Datei
4. bei Service-Fragen `docs/SERVICE_CATALOG.md` 4. bei Service-Fragen `docs/SERVICE_CATALOG.md`
5. bei Restore/DR `docs/DISASTER_RECOVERY.md` und `docs/RESTORE_MATRIX.md` 5. bei Restore/DR `docs/DISASTER_RECOVERY.md` und `docs/RESTORE_MATRIX.md`
6. bei "warum ist das so?"-Fragen `docs/DECISIONS.md`
## Harte Regeln ## Harte Regeln
@@ -30,51 +33,21 @@ Kurzer Kontext fuer KI-Agenten. Nicht als Ersatz fuer die echten Runbooks lesen.
- Traefik dynamic config und Authelia Host-Config sind manuelle Sync-Ausnahmen. - Traefik dynamic config und Authelia Host-Config sind manuelle Sync-Ausnahmen.
- Bei Drift zuerst Git, Gitea, Komodo Workspace, Docker Runtime und Host getrennt pruefen. - Bei Drift zuerst Git, Gitea, Komodo Workspace, Docker Runtime und Host getrennt pruefen.
- Nach zwei fehlgeschlagenen Reparaturversuchen stoppen und `docs/GITOPS_DRIFT_RUNBOOK.md` nutzen. - Nach zwei fehlgeschlagenen Reparaturversuchen stoppen und `docs/GITOPS_DRIFT_RUNBOOK.md` nutzen.
- Doku-Regel: ein Fakt hat genau ein Zuhause; verlinken statt kopieren (`docs/REPO_MAP.md`).
## Bekannte Ausnahmen ## Bekannte Ausnahmen
Autoritativ: `HOMELAB_ARCHITECTURE_MASTER_V2.md` §10. Kurzliste:
- Traefik: Host-Ports 80/443, WAN-Freigabe nur 443 - Traefik: Host-Ports 80/443, WAN-Freigabe nur 443
- Gitea: SSH auf Host-Port 222, keine WAN-Freigabe - Gitea: SSH auf Host-Port 222, keine WAN-Freigabe
- AdGuard: DNS 53 direkt; Admin nur auf Tailscale-IP `100.80.98.33:8082` - AdGuard: DNS 53 direkt; Admin nur auf Tailscale-IP `100.80.98.33:8082`
- Tailscale und Plex: Host-Netz - Tailscale: natives Unraid-Plugin (nicht repo-verwaltet); Plex: Host-Netz
- Scrutiny: privileged - Scrutiny: privileged; Komodo/Periphery: Docker-Socket
- Komodo/Periphery: Docker-Socket-Zugriff
- InfluxDB 3 Core: `127.0.0.1:8181`, Root-User-Ausnahme dokumentiert - InfluxDB 3 Core: `127.0.0.1:8181`, Root-User-Ausnahme dokumentiert
## Aktuelle Restpunkte ## Arbeitsstand
Authoritativ: `docs/MASTER_TODO.md`. - Offene Punkte: `docs/MASTER_TODO.md` (einzige Statusliste)
- Entscheidungen und Begruendungen: `docs/DECISIONS.md`
Kurzfassung: - Belege/Reports: `/mnt/user/backups/restore-reports/` auf dem Host
- Auth-/OIDC-/CrowdSec-/Hermes-Themen bewusst geparkt
- Wochenend-Sprint 2026-06-05: `docs/WEEKEND_EXECUTION_PLAN_2026-06-05.md`
und `docs/WEEKEND_STATUS_2026-06-05.md`
Letzte Bestaetigung:
- Windows-Image `baerchen`: Veeam Agent Free Job `baerchen-c-image` auf
`\\kallilabcore\backups\windows-images\baerchen`, erster Full-Backup-Lauf
2026-06-05 erfolgreich, GUI-Wert 53,8 GB, Dauer 0:11:31. Recovery-USB ist
erstellt; Boot-/SMB-/Restore-Point-Test ohne Restore ist noch offen.
- Veeam Storage Encryption ist beim ersten Full-Lauf nicht aktiv
(`StorageEncryptionEnabled=False`); nachtraegliche Aktivierung ist eine
Operator-Entscheidung, weil sie Passwort- und Restore-Prozess aendert.
- BitLocker fuer `baerchen` ist bewusst nicht aktiviert und bleibt
Operator-Entscheidung.
- Tailscale-Inventar 2026-06-05 real gemessen: `Kallilabcore`
`100.80.98.33`, IPv6 `fd7a:115c:a1e0::2c01:62b2`, kein Exit Node, aber
aktiver Subnet Router fuer `192.168.178.0/24`. Dadurch ist die Tailnet-ACL
sicherheitsrelevant; Entscheidung Default-Allow vs tag-basierte ACL offen.
- Unraid-Flash-Backup-Artefaktpruefung: `ops/maintenance/check-unraid-flash-backup.sh`
prueft Artefakt, SHA256, Alter und Kern-Configs. Test 2026-06-05 gegen Host
erfolgreich laut `docs/MASTER_TODO.md`.
- Borg-Nachlauf 2026-06-01 erfolgreich: Archiv `Taegliche-Sicherung-2026-06-01T04:30:26.913`, Freshness Critical 0 / Warnings 0.
- H:/ Nearline-Pull 2026-06-01 repariert: Borg-Dumps werden kuratiert kopiert, Gitea-Bundles aktuell.
- Family-Status-Dashboard liegt als `monitoring/grafana/dashboards/family-status.json` im Repo.
- Alt-Volumes nach PG18/VectorChord-Burn-in sind seit 2026-06-02 reversibel archiviert unter `/mnt/user/appdata/_archive/pg18-immich-rollback-volumes-20260602`; die alten Originalpfade sind nicht mehr aktiv gemountet.
- Family-Onboarding ist auf drei Nutzungsziele fokussiert: Vaultwarden, Immich und Mealie; praktischer Ablauf in `docs/FAMILY_ONBOARDING.md`.
- Externer Betreibercheck: `ops/maintenance/check-external-operator.sh`; FRITZ!Box 7590 meldet FRITZ!OS `154.08.25`, DNS fuer Public Apps hat keine AAAA-Records, Host hat keine globale Provider-IPv6.
- FRITZ!Box-UI 2026-06-01: Remote-HTTPS auf FRITZ!Box-UI aus, FTP/FTPS auf Speichermedien aus, WAN-Freigabe nur `443/tcp`, keine aktive IPv6-Freigabe sichtbar, UPnP-Selbstfreigaben aus.
- FRITZ!Box-Konfig-Backup 2026-06-01 extern/off-system in Vaultwarden abgelegt; Datei und Kennwort bleiben ausserhalb des Repos.
- Hetzner-Account-Hygiene 2026-06-01 erledigt: 2FA aktiv, Recovery Key offline gedruckt, Zahlung ok; Storage Box SSH-only, Maintenance-Key in Vaultwarden. Append-only forced-command brach Key-Auth und wurde per Passwort-Recovery zurueckgesetzt; Operator-Entscheidung: fuer dieses Homelab bewusst nicht umsetzen.
-68
View File
@@ -1,68 +0,0 @@
# Audit-Restliste 2026-05-25
Status: **kompakte Restliste**. Die erledigten Sprint-Tabellen und langen
Audit-Snapshots wurden aus der Arbeitskopie entfernt; Detailhistorie liegt in Git.
Letzter Sync mit `docs/MASTER_TODO.md`: 2026-06-05. Offene Punkte sind deckungsgleich;
neue Restore-Runbook-Stubs (Unraid Flash / AdGuard / Tailscale / Redis 8) wurden
in `docs/RESTORE_MATRIX.md` ergaenzt.
## Aktuell offene Punkte
| Prioritaet | Punkt | Naechster Schritt |
|---|---|---|
| P2 | Family-Onboarding praktisch starten | Fokus: Vaultwarden als Passwortbasis, Immich-Mobile-Backup auf jedem Handy, Mealie mit erstem Rezept/Einkaufsliste; Ablauf steht in `docs/FAMILY_ONBOARDING.md` |
## Restore-Audit Backlog (Stand 2026-06-03)
Ergebnis des Restore-Skills-Audits (Session 2026-06-02/03). Die kritischen Bugfixes (Cron-OR-Semantik, ntfy-Race, Cleanup-Trap, Pfad-Inkonsistenz, Vaultwarden-Token, Paperless-Retry, Header-Validierung, Authelia-Test) sind erledigt und committed. Die folgenden Punkte sind bewusst offener Backlog:
| Prioritaet | Punkt | Status | Naechster Schritt |
|---|---|---|---|
| P1 | Nextcloud-Restore-Test | **erledigt 2026-06-03** | Borg-Extract + pg_restore (126 Tabellen) + HTTP 200 + `occ status maintenance:false`. Quelle: `hetzner_borg_appdata_critical`, Archiv `Taegliche-Sicherung-2026-06-03T04:30:41.432`. Zwei Skript-Bugs im Zuge des Laufs gefixt (`check_data_directory_permissions: false` patchen, `.ncdata`-Marker anlegen). Report `/mnt/user/backups/restore-reports/nextcloud-2026-06-03.md`. |
| P1 | Shared PostgreSQL 18 Cluster Restore Drill | **erledigt 2026-06-03** | Globals + 5 DBs (paperless 72t, mailarchiver 1t, authelia 25t, nextcloud 126t, mealie 66t), `data_checksums=on`, Report `/mnt/user/backups/restore-reports/shared-pg-cluster-2026-06-03.md` |
| P1 | Komodo-Mongo-Daten-Restore | **erledigt 2026-06-03** | 86904 Dokumente erfolgreich restored, Report `/mnt/user/backups/restore-reports/komodo-mongo-restore-2026-06-03.md`. Nebenbefund: Dump von Mongo 8.0.23, Test auf 7.0.32 — Cross-Version-Warning, fuer Lesetest harmlos |
| P2 | Mailarchiver-Restore-Test | **erledigt 2026-06-03** | Data-Protection-Keys + 645M pg_restore + HTTP 200. Report `/mnt/user/backups/restore-reports/mailarchiver-2026-06-03.md` |
| P2 | Mealie-Restore-Test | **erledigt 2026-06-03** | Borg-Data + pg_restore + HTTP 200, 3 Rezepte. Report `/mnt/user/backups/restore-reports/mealie-2026-06-03.md` |
| P2 | Traefik-Restore-Test | **erledigt 2026-06-03** | dynamic/ + letsencrypt/ aus Borg, File-Provider + Ping 200. CF-Token bewusst nicht im Smoke. Report `/mnt/user/backups/restore-reports/traefik-2026-06-03.md` |
| P3 | Negativ-Test fuer Frische-Check | offen | Einmal pro Quartal bewusst kaputten Dump einfuettern und pruefen ob `homelab-alerts` feuert |
| P3 | End-to-end-DR-Drill | offen | Komplett-Bootstrap Phase 1-5 auf einem Wegwerf-Host; realistisch nur mit zweiter Hardware |
## Bewusst geparkt
| Punkt | Entscheidung |
|---|---|
| Authelia 2FA fuer Operator-UIs (Rest) | Tier-1-Operator-UIs sind 2026-06-03 auf `two_factor` gehoben (`files`, `scrutiny`, `borg`, `code`). Restliche Admin-UIs (`monitoring`, `glances`, `glance`, `speedtest`, `paperless-gpt`, `pdf`, `mail`, `hermes`, `sp`) bleiben bewusst auf `one_factor`, bis die finale Auth-Policy steht. |
| Authelia OIDC fuer Apps | Geparkt bis klare Familien-/SSO-Entscheidung |
| CrowdSec vor Traefik | Bewusst nicht umgesetzt: einzige WAN-Tuer ist `443/tcp`, Operator-Pfad ist Tailscale, Authelia-`regulation:` deckt Auth-Brute-Force ab. Neu bewerten bei breiterer Attack Surface. |
| Nextcloud 2FA/Brute-Force-Haertung | UI-Schritt fuer Operator-Account (`twofactor_totp` aktivieren) bleibt offen. App-weite Familien-Policy gemeinsam mit OIDC entscheiden. |
| Hermes-Agent | NAS-Stack bleibt deaktiviert; Review-Deadline 2026-07-25 |
| USV | Anschaffung verschoben; Power-Loss-Risiko bewusst akzeptiert |
| Zweites Off-site-Ziel | Bewusst nicht umgesetzt; neu bewerten bei Hetzner-Problemen, stark wachsendem Datenwert oder geaenderter Betreiber-Praeferenz |
| Borg `append-only` auf Hetzner | Operator-Entscheidung 2026-06-01: nicht umgesetzt. Der forced-command-Test auf der Storage Box brach Key-Auth und wurde per Passwort-Recovery zurueckgesetzt; Nutzen steht fuer dieses Homelab nicht im Verhaeltnis zum Betriebsrisiko. |
## Zuletzt geschlossen
- DR-Workstation Bare-Metal-Kit abgeschlossen (2026-06-06): WSL2 Ubuntu 24.04, SSH/Git, Borg 1.2.8, DR-Key-Arbeitskopien `~/.ssh/dr-readonly` und `~/.ssh/dr-hetzner`, `~/dr-smoke.sh`. Finaler Operator-Smoke erfolgreich: GitHub HEAD `3a263a4...`, Hetzner Storage Box Repos sichtbar (`backup`, `backup2`, `hetzner_borg_appdata`, `hetzner_borg_appdata_critical`), Borg-Repo `hetzner_borg_appdata_critical` gelesen, Repository ID `5dd9b949...`, encrypted `Yes (repokey)`, `DR-Smoke OK (2026-06-06 10:05:30)`. Borg-Passphrase wurde nur interaktiv eingegeben und nicht gespeichert.
- Nextcloud-Restore-Test 2026-06-03 erfolgreich (Tier-2 damit komplett belegt). Drei Laeufe noetig: Lauf 1 schlug an `chmod()` der data-Dir auf shfs fehl (`OC_Util.php:486`), Lauf 2 an fehlender `.ncdata`-Marker-Datei, Lauf 3 sauber durch. Beide Bug-Fixes ins Skript `ops/restore-tests/nextcloud-restore-test.sh` integriert. Endresultat: HTTP 200 auf `/status.php`, `occ status` ok, 126 Tabellen in der DB. Source: `hetzner_borg_appdata_critical`, Archiv `Taegliche-Sicherung-2026-06-03T04:30:41.432`. Report unter `/mnt/user/backups/restore-reports/nextcloud-2026-06-03.md`.
- Hetzner Storage Box DR-SSH-Key `dr-hetzner-2026-06-03` (ed25519, Passphrase-frei) angelegt: Pubkey via `install-ssh-key` auf der Storage Box autorisiert, passwortloser Login erfolgreich (Borg-Repos `backup`, `backup2`, `hetzner_borg_appdata`, `hetzner_borg_appdata_critical` sichtbar), Private-Key offline neben KOMODO_*-Notiz und GitHub-Deploy-Key abgelegt, Arbeitsplatz-Kopie geloescht. Damit ist Bare-Metal-Borg-Zugang von der DR-Workstation moeglich, sobald WSL2+Borg installiert sind.
- Fix Common Problems Plugin (FCP) 2026-06-03 deinstalliert. Befund: drei `grep -R ... /usr/local/emhttp`-Prozesse aus einem FCP-Daily-Scan hingen seit ~7 Tagen in einem Symlink-Loop (`/usr/local/emhttp/mnt -> /mnt`, gesamte Array). 3 Cores dauerhaft 100 %, IOWAIT bis 55 %, USB-Flash unter Dauer-IO. Plugin via `plugin remove` entfernt, Cron + /tmp-Reste sauber, Load von 14.6 auf 1.08 gefallen. FCP wird bewusst nicht wieder installiert (Begruendung siehe `HOMELAB_ARCHITECTURE_MASTER_V2.md` Sektion 13). Bekannte Risiken decken Scrutiny, Monitoring, Posture-Check und Critical-Events-Watcher bereits ab.
- GitHub-Mirror Read-Only Deploy-Key `DR Read-Only 2026-06-03` (ed25519, Passphrase-frei) angelegt: GitHub Repo Settings -> Deploy Keys ohne Write-Access, Smoke `git ls-remote` erfolgreich (HEAD `d947c7f` = master), Private-Key offline neben der KOMODO_*-Notiz abgelegt, Arbeitsplatz-Kopie nach USB-Transfer geloescht. Damit ist der DR-Read-Pfad zum privaten Mirror ohne Operator-Browser-Login moeglich.
- KOMODO_*-Notiz offline gesichert (Operator-Bestaetigung 2026-06-03). Quelle bleibt host-seitige `.env` unter `/mnt/user/services/stacks/komodo/.env` bzw. die Drift-Recovery-Kopie unter `/mnt/user/appdata/secrets/_komodo_stack_env_recovery_2026-05-04.env`. Damit ist der Bare-Metal-Komodo-Bootstrap ohne Vaultwarden moeglich. Eintrag in `docs/EXTERNAL_DEPENDENCIES.md` Reviews und Pflichtbestandteil im DR-Workstation-Kit nachgezogen.
- DR-Tabletop 2026-06-03 durchgelaufen, Findings in `docs/DR_DRILL_2026-06-03.md` (23 Befunde: 1 CRITICAL, 11 HIGH, 8 MED, 3 LOW). Reine Doku-Fixes in DR.md (Phase 0 Mirror-Klarstellung, neue Phase 4 Stufe 0 Docker-Netze, LE-Staging-Hinweis, Komodo-Stolperfallen, App-DB-Verify in Phase 5) und in `EXTERNAL_DEPENDENCIES.md` (DR-Workstation-Kit, KOMODO_*-Notiz und GitHub-Read-PAT als offene Bootstrap-Bloecke) sind im selben Aenderungsblock erledigt. Operator-Aufgaben (Notiz/PAT/WSL-Setup) wandern als P1 in die offenen Punkte.
- Authelia ACL: `borg.kaleschke.info` und `code.kaleschke.info` 2026-06-03 in den `two_factor`-Block der Repo-Baseline aufgenommen. Beide UIs haben effektiv Host-/Backup-Zugriff (Borg-Restore-Scope inkl. `/local/secrets`, code-server mit Workspaces). Wirkung erst nach manuellem Merge in `/mnt/user/appdata/authelia/config/configuration.yml`, `docker restart authelia` und Smoke-Test auf einer der vier 2FA-Domains; `services/authelia-diff.sh` muss `exit 0` liefern. TOTP-Enrollment des Operator-Accounts ist Voraussetzung, sonst Login-Sperre.
- Alt-Volumes nach Burn-in freigegeben und reversibel archiviert: Shared PG17, Mealie PG17, Nextcloud PG17 und Immich pgvecto.rs liegen seit 2026-06-02 unter `/mnt/user/appdata/_archive/pg18-immich-rollback-volumes-20260602`; Manifest auf dem Host: `/mnt/user/appdata/_archive/pg18-immich-rollback-volumes-20260602/MANIFEST.txt`. Keine harte Loeschung, keine aktiven Container-Mounts auf die alten Pfade.
- Externer Betreibercheck vorbereitet: `docs/EXTERNAL_OPERATOR_RUNBOOK.md` und `ops/maintenance/check-external-operator.sh`; Live-Baseline am 2026-06-01: FRITZ!OS `154.08.25`, keine Public-AAAA-Records fuer `*.kaleschke.info`, Host ohne globale Provider-IPv6, WAN `443/tcp` offen und `80/tcp`/`222/tcp` geschlossen.
- FRITZ!Box-Servicefenster UI-seitig abgeschlossen: FRITZ!Box-Dienste aus dem Internet sind aus (HTTPS auf FRITZ!Box-UI, FTP/FTPS auf Speichermedien), aktive WAN-Freigabe bleibt nur `443/tcp -> 192.168.178.58`, keine aktive IPv6-Freigabe sichtbar, UPnP-Selbstfreigaben aus.
- FRITZ!Box-Konfig-Backup exportiert und extern/off-system in Vaultwarden abgelegt: `Einstellungen_FRITZ.Box_7590_154.08.25_01.06.26_1318.export`; Kennwort und Datei bleiben ausserhalb des Repos.
- Hetzner-Account-Hygiene erledigt: externe Kontakt-/Rechnungs-Mail bestaetigt, Zahlung ok, 2FA mit Google Authenticator aktiv, Recovery Key offline ausgedruckt.
- Hetzner Storage Box geprueft: `storage-box-1`, `u565255.your-storagebox.de`, SSH-Port `23`, SSH aktiv, SMB/WebDAV aus, 64,94 GB / 1 TB belegt; Borg-UI-Key und separater Maintenance-Key funktionieren wieder nach Passwort-Recovery. Borg `append-only` ist bewusst nicht umgesetzt.
- Family-View Dashboard ist repo-seitig gebaut: `monitoring/grafana/dashboards/family-status.json` zeigt Family-App-Uptime, Backup-Alter, TLS-Restlaufzeit, Critical-Container und Image-Drift.
- Borg-Nachlauf nach dem 2026-05-31-Sprint ist belegt: Archiv `Taegliche-Sicherung-2026-06-01T04:30:26.913`, 101669 Dateien, `rc=0`; Freshness-Check am 2026-06-01: Critical 0, Warnings 0.
- H:/ Nearline-Pull am 2026-06-01 repariert und manuell validiert: kuratierte Borg-Dumps Exit 0, Gitea-Bundles Exit 1 (Robocopy-Erfolg mit Kopien), Report `nearline-pull-2026-06-01-082553.md`.
- Immich-, Paperless-, Gitea- und Vaultwarden-Restore-Pfade sind belegt.
- H:/ Nearline-Pull laeuft seit 2026-05-28 als Windows Scheduled Task.
- FRITZ!Box-Portfreigaben sind bereinigt: WAN-seitig bleibt `443/tcp`.
- InfluxDB 3 Core ist effektiv nur auf `127.0.0.1:8181` gebunden.
- Renovate ist produktiv, Major-Updates werden bewusst manuell entschieden.
- Policy-Check bleibt ohne Criticals; bekannte Root-Ausnahmen sind dokumentiert.
+1 -1
View File
@@ -59,7 +59,7 @@ du -sh /mnt/user/documents /mnt/user/photos /mnt/user/media /mnt/user/backups 2>
| Pull der Gitea-Bundles aus `/mnt/user/backups/git-bundles/gitea` | identisch | Bundles sind klein und schnell synchronisiert | | Pull der Gitea-Bundles aus `/mnt/user/backups/git-bundles/gitea` | identisch | Bundles sind klein und schnell synchronisiert |
| Pull des Unraid-Flash-Artefakts `unraid-flash-config.tar.gz` | bewusst nicht im H:/ Scope | Restore-Quelle bleibt Hetzner-Borg; Flash-Config wie Secret behandeln | | Pull des Unraid-Flash-Artefakts `unraid-flash-config.tar.gz` | bewusst nicht im H:/ Scope | Restore-Quelle bleibt Hetzner-Borg; Flash-Config wie Secret behandeln |
Der konkrete Pull-Pfad ist in `docs/H_DRIVE_NEARLINE_PULL.md` und `ops/h-drive-nearline/pull-critical-backups.ps1` produktiv. Der Windows Scheduled Task `KalliLab H Drive Nearline Pull` laeuft seit 2026-05-28 taeglich 05:30. Der konkrete Pull-Pfad ist in `ops/h-drive-nearline/README.md` und `ops/h-drive-nearline/pull-critical-backups.ps1` produktiv. Der Windows Scheduled Task `KalliLab H Drive Nearline Pull` laeuft seit 2026-05-28 taeglich 05:30.
| Abgrenzung | Bewertung | Begruendung | | Abgrenzung | Bewertung | Begruendung |
|---|---|---| |---|---|---|
+118
View File
@@ -0,0 +1,118 @@
# Entscheidungs-Register (ADR-light)
Typ: Entscheidung · Stand: 2026-06-11 · Status: aktiv
Zentrales Register fuer Architektur- und Betriebsentscheidungen. Neueste oben.
Jeder Eintrag: Entscheidung, Kontext, ggf. Alternativen und Review-Trigger.
Lange Incident-Erzaehlungen gehoeren nicht hierher, sondern in den Commit bzw.
Host-Report; hier steht das Destillat. Vorher lebten diese Eintraege verstreut
in `HOMELAB_ARCHITECTURE_MASTER_V2.md` §13, `docs/MASTER_TODO.md` (Geparkt),
`docs/HARDWARE_INVENTORY.md` und der Audit-Restliste.
---
## 2026-06-11 — Doku-Konsolidierung: ein Fakt, ein Zuhause
**Entscheidung:** Die Dokumentation wird nach `docs/archive/2026/homelab-doku-optimierung-2026-06-11.md` konsolidiert: `MASTER_TODO.md` ist die einzige Statusliste, dieses Register die einzige Entscheidungssammlung, `docs/archive/` nimmt abgeschlossene Snapshots auf, Erledigtes verlaesst die Arbeitskopie. Keine Ordner-Restruktur des Bestands.
**Kontext:** 74 Markdown-Dateien / ~9.400 Zeilen; einzelne Sachverhalte waren an 69 Stellen dokumentiert; vier parallele Statuslisten.
**Review-Trigger:** Quartals-Gaertnern (siehe `docs/REPO_MAP.md` Doku-Regeln).
## 2026-06-06 — baerchen: BitLocker und Veeam Storage Encryption bewusst aus
**Entscheidung:** BitLocker bleibt auf allen Laufwerken deaktiviert; Veeam Storage Encryption bleibt aus (`StorageEncryptionEnabled=False`).
**Kontext:** Recovery laeuft ueber das Veeam-Image auf dem lokalen SMB-Share; kein Key-Management-Aufwand, Restrisiko physischer Diebstahl akzeptiert.
**Review-Trigger:** Off-host-Auslagerung des Windows-Images oder geaendertes Risikoprofil. Runbook: `ops/windows-reinstall/docs/windows-image-backup-baseline.md`.
## 2026-06-06 — Tailscale: natives Unraid-Plugin kanonisch, restriktive ACL
**Entscheidung:** Tailscale laeuft ausschliesslich als natives Unraid-Plugin (`tailscale.plg`, Subnet-Router, State im Flash-Backup); der redundante userspace-Docker-Stack `host-services/tailscale/` wurde entfernt. Tailnet-ACL ist tag-basiert restriktiv (`tag:server`/`tag:operator`, `tag:family` schlafend), Default-Allow entfernt.
**Kontext:** Zwei parallele `tailscaled`-Instanzen; nur die Plugin-Instanz routet. Details: `docs/NETWORK_INVENTORY.md`.
**Review-Trigger:** Erstes reales Familiengeraet (Familien-Dienste in ACL konkretisieren).
## 2026-06-06 — Authelia: 2FA-Catch-all aktiv, OIDC-Rollout gestaffelt
**Entscheidung:** Catch-all `*.kaleschke.info` -> `two_factor` in Repo- und Host-Config. OIDC-SSO wird app-weise ausgerollt (live: Grafana, Mealie; deployed: Paperless). Immich- und Nextcloud-OIDC sowie Nextcloud-Operator-TOTP sind geparkt, bis Familien-Accounts existieren.
**Kontext:** Nur der Operator hat aktuell einen Authelia-Account; Familien-SSO-Nutzen entsteht erst mit dem Onboarding. Runbook: `docs/AUTHELIA_OIDC_PLAN.md`.
**Review-Trigger:** Family-Onboarding erreicht die App-Login-Ebene.
## 2026-06-05 — USV geparkt, Cold-Backup Hetzner-only, kein Strom-Monitoring
**Entscheidung:** Keine USV-Anschaffung dieses Quartal (Power-Loss bewusst akzeptiert). Off-site bleibt allein Hetzner-Borg, keine zweite rotierende Cold-Kopie. Stromverbrauch wird nicht gemessen (kein Messgeraet, kein Beschaffungs-Todo).
**Review-Trigger:** USV: Q3-Review ab 2026-07-01, Hardware-Upgrade oder realer Stromausfall mit Datenfolge. Cold-Backup: Hetzner-Probleme oder stark wachsender Datenwert. Strom: nur bei Anschaffung eines Messgeraets.
## 2026-06-03 — Fix Common Problems Plugin entfernt, keine Neuinstallation
**Entscheidung:** FCP wurde deinstalliert und wird bewusst nicht wieder installiert.
**Kontext:** Ein FCP-Scan hing 7 Tage in einem `grep -R`-Symlink-Loop ueber das gesamte Array (3 Cores 100 %, IOWAIT bis 55 %, Load 14.6 -> 1.08 nach Entfernung). Die abgedeckten Risiken uebernehmen Scrutiny, Monitoring-Stack, Posture-Check und Critical-Events-Watcher.
**Review-Trigger:** keiner; Entscheidung ist final.
## 2026-06-01 — Borg append-only auf Hetzner nicht umgesetzt
**Entscheidung:** Kein append-only/forced-command auf der Storage Box.
**Kontext:** Der forced-command-Test brach die Key-Auth und musste per Passwort-Recovery zurueckgesetzt werden; Nutzen/Betriebsrisiko-Verhaeltnis unguenstig. Kompensation (Storage-Box-Snapshots) siehe `docs/homelab-optimierung.md` Empfehlung 2.
**Review-Trigger:** Hetzner bietet robusteren Mechanismus, oder Ransomware-Risikoprofil aendert sich.
## 2026-05-28 — Plex: Reclaim, Traefik-Route ohne ForwardAuth, kein Remote Access
**Entscheidung:** Plex-Server ist als Operator-Konto geclaimt; externer Zugriff laeuft ausschliesslich ueber Traefik/443 (`plex.kaleschke.info`, File-Provider-Ausnahme wegen Host-Netz), Plex Remote Access und WAN-Port 32400 bleiben aus, keine Authelia-ForwardAuth (native Plex-Auth).
**Kontext:** Preferences waren nach dem Mai-Crash jungfraeulich; Claim-Token wurde nur als Shell-Inline-ENV genutzt, nie persistiert. Details: `docs/SERVICE_CATALOG.md`, `HOMELAB_ARCHITECTURE_MASTER_V2.md` §10.
## 2026-05-28 — Gitea-SSH (222) bleibt ohne WAN-Freigabe
**Entscheidung:** Port 222 wird nicht in der FRITZ!Box freigegeben.
**Kontext:** Tailscale ist der Operator-Pfad, der GitHub-Mirror deckt DR-Bootstrap ab, SSH-Brute-Force-Vektor extern vermeiden.
## 2026-05-28 — paperless-gpt und BentoPDF bleiben aktiv
**Entscheidung:** Beide Container bleiben trotz geringer Nutzung. paperless-gpt-Abloese wird erst mit Paperless-NGX 3.0 (eigene KI-Features) neu bewertet; BentoPDF ist situatives Tool mit vernachlaessigbarem Footprint und ersetzt Stirling-PDF.
**Review-Trigger:** Paperless-NGX-3.0-Release.
## 2026-05-26 — AdGuard-Admin nur auf Tailscale-IP, ohne Traefik/2FA
**Entscheidung:** Admin-UI bleibt auf `100.80.98.33:8082` (Tailscale-only) gebunden; bewusst keine Traefik-/2FA-Umstellung. DNS-Port 53 bleibt direkte Host-Port-Ausnahme.
**Review-Trigger:** Aenderung des Tailnet-Zugangsmodells.
## 2026-05-25 — Ein Dienst pro Funktion: Jellyfin, Homepage, Uptime-Kuma entfernt
**Entscheidung:** Plex ist der einzige Medienserver, Glance das einzige Dashboard, Blackbox-Exporter + Prometheus-Alerts + Grafana ersetzen Uptime-Kuma.
**Kontext:** Doppelte Dienste = doppelte Pflege/Attack-Surface. Removal-Checkliste: `docs/WORKFLOW.md`.
## 2026-05-17 — Monitoring-/Logging-Baseline
**Entscheidung:** `monitoring/` ist der einzige Observability-Stack (Prometheus, Loki, Promtail, Grafana, Exporter, InfluxDB 3 Core). Loki intern ohne Route, Promtail mit read-only Docker-Socket, Loki-Daten sind Diagnosematerial mit Retention, keine Restore-Quelle. Alte Pfade `ops/loki`/`ops/grafana-influxdb` sind entfernt (Rollback nur via Git-Historie).
## 2026-05-05 — Stateful Digest-Pinning und Versionspolitik
**Entscheidung:** Tier-1-/stateful Dienste laufen mit sprechendem Versions-Tag plus Digest (z. B. `postgres:17.x@sha256:...`); mutable Tags wurden 2026-04-17 auf laufende Digests eingefroren. Digest-Pinning ist Reproduzierbarkeit, kein Upgrade-Mechanismus; echte Upgrades sind eigene Aenderungsbloecke. Renovate (live seit 2026-05-29) liefert PRs, kein Auto-Merge.
**Review-Trigger:** Mutable-Tag-Restbestand siehe `docs/homelab-optimierung.md` Empfehlung 1.
## 2026-05-04 — Authelia ohne Redis-Session-Backend
**Entscheidung:** Authelia nutzt PostgreSQL fuer Storage, aber kein Redis-Session-Backend; nach Restart werden Sessions neu aufgebaut.
**Kontext:** Haelt den Tier-1-Auth-Pfad einfach. `infra/redis` ist faktisch nur Paperless-Cache; Konsolidierung nach `apps/paperless/` bleibt denkbar, unpriorisiert.
## 2026-05-04 — Komodo-Self-Stack: Reconcile-Regel nach Drift
**Entscheidung:** Der Komodo-Self-Stack laeuft aus `/mnt/user/services/stacks/komodo/compose.yaml` (Quelle: `ops/komodo/docker-compose.yml`). Bei Self-Stack-Drift kein pauschales `docker compose up -d`, wenn der Dry-run `komodo-mongo` recreaten wuerde; Core/Periphery gezielt mit `--no-deps` neu erstellen, Mongo unangetastet lassen.
**Kontext:** Drift-Recovery 2026-05-04 (Repair-YAMLs aus `/tmp`); Sicherungen unter `/mnt/user/appdata/komodo/_drift_backup_2026-05-04/`.
## 2026-04-19 — Nextcloud als klassischer Stack, nicht AIO; native Auth
**Entscheidung:** Nextcloud laeuft als App + eigene PostgreSQL + eigene Redis (kein AIO), ohne zentrale ForwardAuth (Browser-/Client-/WebDAV-Flows brauchen native Auth).
## 2026-04-12 — Borg-Scope enthaelt bewusst /local/secrets
**Entscheidung:** Borg sichert ausgewaehltes Secret-Material (`/local/secrets`) als Teil der DR-Strategie; `borg-ui` hat dafuer breite, bewusste Mounts. Dumps statt Raw-DB-Pfade sind der primaere Restore-Weg.
**Kontext:** `ops/borg-ui/BACKUP_SCOPE.md`.
## 2026-03-28/29 — GitOps-Fundament
**Entscheidung:** Komodo ersetzt Portainer als alleiniger Stack-Manager (Docker-Socket-Ausnahme, native Auth ohne pauschale ForwardAuth wegen Webhooks/`/ws/periphery`). Traefik routet ausschliesslich ueber Docker-Labels; File-Provider nur fuer `middlewares.yml`, `tls.yml`, `dashboards.yml` (+ dokumentierte `plex.yml`-Ausnahme). AdGuard Home + Unbound ersetzen Pi-hole.
**Kontext:** Konkurrierende `@file`-/`@docker`-Router hatten Fehlrouting verursacht; Regel: keine neuen Service-Routen im File-Provider.
## Aelteres / Sonderfaelle
- **Paperless Stack-ENV-Ausnahme:** `PAPERLESS_DBPASS`/`PAPERLESS_REDIS` bleiben Komodo-Stack-ENV (kein `_FILE`-Support im Image); Konsequenzen fuer DR siehe `docs/DISASTER_RECOVERY.md` Phase 2.
- **ddns-updater in `frontend_net`:** braucht Cloudflare-API; `backend_net` ist internal.
- **mail-archiver Hybrid:** `frontend_net` (IMAP) + `backend_net` (DB), App-Auth zusaetzlich zu Authelia.
- Vollstaendige technische Ausnahmen-Liste mit Begruendung: `HOMELAB_ARCHITECTURE_MASTER_V2.md` §10 (bleibt dort autoritativ).
+7 -8
View File
@@ -8,7 +8,7 @@ Verwandte Dokumente:
- `docs/ROLLBACK.md` - Rueckweg bei Fehlern im laufenden GitOps-Betrieb - `docs/ROLLBACK.md` - Rueckweg bei Fehlern im laufenden GitOps-Betrieb
- `docs/RESTORE_MATRIX.md` - Restore-Quellen und Verifikationsregeln pro Dienst - `docs/RESTORE_MATRIX.md` - Restore-Quellen und Verifikationsregeln pro Dienst
- `docs/RESTORE_HANDBOOK.md` - praktische Restore-Betriebsanleitung - `ops/restore-tests/README.md` - Restore-Test-Betrieb und Werkzeuge
- `docs/SERVICES_RECOVERY.md` - Recovery-kritische `/mnt/user/services`-Pfade, Gitea-Mirror und Komodo-Bootstrap - `docs/SERVICES_RECOVERY.md` - Recovery-kritische `/mnt/user/services`-Pfade, Gitea-Mirror und Komodo-Bootstrap
- `docs/EXTERNAL_DEPENDENCIES.md` - externe Provider/Konten und Ausfall-Szenarien - `docs/EXTERNAL_DEPENDENCIES.md` - externe Provider/Konten und Ausfall-Szenarien
- `ops/borg-ui/BACKUP_SCOPE.md` - Zielbild des Borg-Scopes - `ops/borg-ui/BACKUP_SCOPE.md` - Zielbild des Borg-Scopes
@@ -565,15 +565,14 @@ und physisch ausserhalb des Rechners abgelegt sein.
--- ---
## 11. Offene Vorbereitungs-To-dos ## 11. Laufende Vorbereitung
- Unraid-USB-/Flash-Backup regelmaessig ueber `unraid-flash-config.tar.gz` und optional Unraid Connect pruefen Offene Punkte werden in `docs/MASTER_TODO.md` gefuehrt. Daueraufgaben:
- Borg-Passphrase ist laut Operator-Bestaetigung vom 2026-05-26 extern/offline hinterlegt; bei Reviews nur Existenz/Lesbarkeit der Offline-Kopie pruefen, nie den Wert dokumentieren
- Komodo Stack-ENV-Werte zentral ausserhalb von Komodo dokumentieren - Unraid-Flash-Artefakt regelmaessig pruefen (`ops/maintenance/check-unraid-flash-backup.sh`)
- regelmaessige automatisierte Restore-Smoke-Tests fuer Vaultwarden, Gitea und Paperless etablieren - Offline-Kopien (Borg-Passphrase, KOMODO_*-Notiz, DR-Keys) bei Reviews nur auf Auffindbarkeit pruefen, nie Werte dokumentieren
- `komodo-mongo`-Dump nach Major-Upgrades gezielt kontrollieren - `komodo-mongo`-Dump nach Major-Upgrades gezielt kontrollieren
- `baerchen` Recovery-USB-Boot-/SMB-Test nach erfolgreichem erstem Full-Lauf - Restore-Drills nach Kadenz aus `ops/restore-tests/schedule.md` rotieren
verifizieren
--- ---
+1 -3
View File
@@ -167,9 +167,7 @@ Nach erfolgreicher Einrichtung im Repo dokumentieren. In `docs/EXTERNAL_DEPENDEN
| 2026-06-XX | DR-Workstation produktiv: WSL2 Ubuntu auf Gaming-PC, borgbackup installiert, Hetzner-DR-Key und GitHub-Deploy-Key in ~/.ssh, Quartals-Smoke-Skript ~/dr-smoke.sh. Bare-Metal-DR-Pillars sind damit alle vier produktionsreif. | Quartalsweise Smoke laufen lassen | | 2026-06-XX | DR-Workstation produktiv: WSL2 Ubuntu auf Gaming-PC, borgbackup installiert, Hetzner-DR-Key und GitHub-Deploy-Key in ~/.ssh, Quartals-Smoke-Skript ~/dr-smoke.sh. Bare-Metal-DR-Pillars sind damit alle vier produktionsreif. | Quartalsweise Smoke laufen lassen |
``` ```
Audit-Restliste analog: in `docs/AUDIT_2026-05-25_TODO.md` den P1 "DR-Workstation Bare-Metal-Kit: WSL2 + Borg-Client installieren" auf erledigt setzen und unter "Zuletzt geschlossen" einen Eintrag mit Smoke-Ergebnis machen. Falls der Punkt noch als offen in `docs/MASTER_TODO.md` steht, dort in den Kurzlog uebernehmen.
Wenn ich (Claude) am Tag der Einrichtung mit SSH-Zugang dabei bin, ziehe ich das nach. Sonst per `git add docs/EXTERNAL_DEPENDENCIES.md docs/AUDIT_2026-05-25_TODO.md && git commit && git push`.
--- ---
+1 -10
View File
@@ -96,15 +96,6 @@ Operative Regel: Die DR-Workstation wird nicht als Test-/Spiel-PC betrachtet. WS
| Datum | Ergebnis | Naechste Aktion | | Datum | Ergebnis | Naechste Aktion |
|---|---|---| |---|---|---|
| 2026-05-26 | Bekannte externe Abhaengigkeiten aus Repo-/Betriebsdoku dokumentiert; keine Secret-Werte aufgenommen. Borg-Passphrase ist laut Operator offline gesichert. | Account-Besitz, 2FA-Recovery-Codes und Zahlungswege extern bestaetigen | | 2026-05-26 bis 2026-06-03 | Baseline und Haertung abgeschlossen: externe Abhaengigkeiten dokumentiert; FRITZ!Box-WAN auf 443/tcp bereinigt, Remote-Dienste aus, Konfig-Backup in Vaultwarden; Hetzner-Account-Hygiene (2FA, Recovery Key offline); KOMODO_*-Notiz und GitHub-Read-Deploy-Key offline gesichert. Detailhistorie in Git. | Keine Folgeaktion |
| 2026-05-26 | Telekom-DSL und FRITZ!Box 7590 (damals FRITZ!OS 8.21) als WAN-/Router-Abhaengigkeit aufgenommen; Ausfallschutz nicht eingerichtet | FRITZ!OS-Update am 2026-06-01 als `154.08.25` beobachtet |
| 2026-05-28 | FRITZ!Box-Portfreigaben bereinigt: aktiv bleibt nur `443/tcp`; `80/tcp` entfernt, `222/tcp` bewusst nicht angelegt; UPnP-Recht fuer VONETS-Bridge deaktiviert | IPv6-/Dienste-Review am 2026-06-01 nachgezogen |
| 2026-06-01 | Externer Betreibercheck vorbereitet: `docs/EXTERNAL_OPERATOR_RUNBOOK.md` und `ops/maintenance/check-external-operator.sh`; FRITZ!Box meldet per TR-064 FRITZ!OS `154.08.25`, Public DNS hat keine AAAA-Records, Host hat keine globale Provider-IPv6 | Account-Hygiene am 2026-06-01 nachgezogen |
| 2026-06-01 | FRITZ!Box-UI gegengeprueft und Konfig-Backup extern/off-system in Vaultwarden abgelegt; Remote-HTTPS auf FRITZ!Box-UI aus, FTP/FTPS auf Speichermedien aus, nur `443/tcp -> 192.168.178.58`, keine aktive IPv6-Freigabe sichtbar, UPnP-Selbstfreigaben aus | Bei naechstem Router-Update erneut exportieren |
| 2026-06-01 | Hetzner-Account-Hygiene erledigt: externe Mail ok, Zahlung ok, 2FA aktiv, Recovery Key offline gedruckt. Storage Box: SSH aktiv, SMB/WebDAV aus, Maintenance-Key in Vaultwarden, Borg-Repo-Zugriff nach Recovery geprueft. Borg `append-only` wird bewusst nicht umgesetzt. | Keine Folgeaktion |
| 2026-06-03 | Hetzner Storage Box Maintenance-Key zusaetzlich offline gesichert bestaetigt (Operator-Antwort im DR-Tabletop 2026-06-03). Damit ist der Hetzner-Zugang im Bare-Metal-Fall ohne Vaultwarden moeglich. | Keine Folgeaktion |
| 2026-06-03 | DR-Tabletop ergibt drei offene Bootstrap-Bloecke: KOMODO_*-Notiz nicht offline, GitHub-Mirror-Read-PAT/Deploy-Key nicht angelegt, DR-Workstation nicht als DR-Kit konfiguriert. Details in `docs/DR_DRILL_2026-06-03.md` und Folge-Tasks in `docs/AUDIT_2026-05-25_TODO.md`. | KOMODO_*-Notiz erzeugen, Read-PAT erzeugen, WSL2+Borg auf Gaming-PC einrichten |
| 2026-06-03 | KOMODO_*-Notiz offline gesichert (Operator-Bestaetigung im DR-Tabletop-Followup). Quelle bleibt host-seitige `.env` (`/mnt/user/services/stacks/komodo/.env`) bzw. Drift-Recovery-Kopie vom 2026-05-04. Bare-Metal-Komodo-Bootstrap ist damit ohne Vaultwarden moeglich. | Restliche P1-Operator-Aufgaben: GitHub-Read-PAT, DR-Workstation-Setup, Nextcloud-Restore-Test |
| 2026-06-03 | GitHub-Mirror Read-Only Deploy-Key `DR Read-Only 2026-06-03` (ed25519, Passphrase-frei) erzeugt, in GitHub Repo Settings ohne Write-Access hinterlegt, Smoke `git ls-remote` erfolgreich (`d947c7f` matched master HEAD), Private-Key offline neben KOMODO_*-Notiz abgelegt, Arbeitsplatz-Kopie geloescht. | Restliche P1-Operator-Aufgaben: DR-Workstation-Setup, Nextcloud-Restore-Test |
| 2026-06-03 | Hetzner Storage Box DR-SSH-Key `dr-hetzner-2026-06-03` (ed25519, Passphrase-frei) erzeugt, via `install-ssh-key` auf Storage Box `u565255.your-storagebox.de:23` autorisiert, passwortloser Login erfolgreich (Borg-Repos sichtbar), Private-Key offline neben KOMODO_*-Notiz und GitHub-Deploy-Key abgelegt, Arbeitsplatz-Kopie geloescht. Bare-Metal-Borg-Restore von der DR-Workstation ist damit moeglich, sobald WSL2 + Borg-Client installiert sind. | Restliche P1-Operator-Aufgaben: WSL2 + Borg-Client auf DR-Workstation installieren, Nextcloud-Restore-Test | | 2026-06-03 | Hetzner Storage Box DR-SSH-Key `dr-hetzner-2026-06-03` (ed25519, Passphrase-frei) erzeugt, via `install-ssh-key` auf Storage Box `u565255.your-storagebox.de:23` autorisiert, passwortloser Login erfolgreich (Borg-Repos sichtbar), Private-Key offline neben KOMODO_*-Notiz und GitHub-Deploy-Key abgelegt, Arbeitsplatz-Kopie geloescht. Bare-Metal-Borg-Restore von der DR-Workstation ist damit moeglich, sobald WSL2 + Borg-Client installiert sind. | Restliche P1-Operator-Aufgaben: WSL2 + Borg-Client auf DR-Workstation installieren, Nextcloud-Restore-Test |
| 2026-06-06 | DR-Workstation produktiv: WSL2 Ubuntu 24.04 vorhanden, SSH/Git und Borg 1.2.8 in WSL vorhanden, DR-Key-Arbeitskopien unter `~/.ssh/dr-readonly` und `~/.ssh/dr-hetzner`, GitHub-Read-Smoke und Hetzner-SSH-Smoke erfolgreich, `ops/maintenance/dr-workstation-smoke.sh` nach `~/dr-smoke.sh` kopiert. Finaler Operator-Smoke erfolgreich: GitHub HEAD `3a263a4...`, Hetzner Storage Box Repos sichtbar, Borg-Repo `hetzner_borg_appdata_critical` gelesen, Repository ID `5dd9b949...`, encrypted `Yes (repokey)`, `DR-Smoke OK (2026-06-06 10:05:30)`. | Quartalsweise `bash ~/dr-smoke.sh`; Borg-Passphrase weiterhin nur interaktiv eingeben und nicht speichern | | 2026-06-06 | DR-Workstation produktiv: WSL2 Ubuntu 24.04 vorhanden, SSH/Git und Borg 1.2.8 in WSL vorhanden, DR-Key-Arbeitskopien unter `~/.ssh/dr-readonly` und `~/.ssh/dr-hetzner`, GitHub-Read-Smoke und Hetzner-SSH-Smoke erfolgreich, `ops/maintenance/dr-workstation-smoke.sh` nach `~/dr-smoke.sh` kopiert. Finaler Operator-Smoke erfolgreich: GitHub HEAD `3a263a4...`, Hetzner Storage Box Repos sichtbar, Borg-Repo `hetzner_borg_appdata_critical` gelesen, Repository ID `5dd9b949...`, encrypted `Yes (repokey)`, `DR-Smoke OK (2026-06-06 10:05:30)`. | Quartalsweise `bash ~/dr-smoke.sh`; Borg-Passphrase weiterhin nur interaktiv eingeben und nicht speichern |
+1 -1
View File
@@ -91,7 +91,7 @@ Nach Aenderung:
1. Einen regulaeren Borg-Lauf abwarten oder manuell starten. 1. Einen regulaeren Borg-Lauf abwarten oder manuell starten.
2. `check-external-operator.sh` ausfuehren. 2. `check-external-operator.sh` ausfuehren.
3. In `docs/AUDIT_2026-05-25_TODO.md` nur das Ergebnis dokumentieren. 3. Nur das Ergebnis dokumentieren: Datum/Befund im Review-Log von `docs/EXTERNAL_DEPENDENCIES.md`.
## 4. FRITZ!Box-Servicefenster ## 4. FRITZ!Box-Servicefenster
-131
View File
@@ -1,131 +0,0 @@
# H:/ Nearline Pull
Status: **produktiv** (2026-05-28). Erster echter Lauf 2026-05-27 20:45 erfolgreich. Windows Scheduled Task `KalliLab H Drive Nearline Pull` taeglich 05:30 ist seit 2026-05-28 aktiv.
## Erstlauf-Befund 2026-05-27
- Erster `-WhatIf`-loser Lauf: 18 Borg-Dump-Files erfolgreich gepullt, 4 unraid-flash-config-Files und 10 Gitea-Bundle-Files blockiert (`Zugriff verweigert`).
- Ursache: Bundles wurden mit `chmod 600` geschrieben, Flash-Config bewusst `0600 root:root`, Filebrowser-Dump erbte 0640. Der SMB-Read-Share auf dem Operator-PC liest mit unprivilegierten Rechten, kein root.
- Fixes im selben Sprint:
- `ops/borg-ui/scripts/gitea-bundle-mirror.sh` schreibt Bundles und Sidecars jetzt 0644 (Bundle-Inhalt = Git-Historie, ohne Secrets durch `.gitignore`).
- `ops/borg-ui/scripts/pre-backup-dumps.sh` setzt alle Dumps via `atomic_write` per Default auf 0644; `unraid-flash-config.*` bleibt explizit 0600.
- `ops/h-drive-nearline/pull-critical-backups.ps1` excluded die `unraid-flash-config.*`-Familie ueber `/XF`, damit Flash-Config bewusst nicht in den Nearline-Scope kommt.
- Zweiter Lauf (nach Fixes): beide Robocopy-Jobs Exit-Code 1, **19 Borg-Dumps + 10 Gitea-Bundle-Files** auf H:/.
## Befund 2026-06-01
- Der Scheduled Task um 05:30 kopierte die aktuellen Dumps, brach aber mit Robocopy Exit-Code 8 ab, weil im Dump-Root alte `*-pre-*` Dateien und Migration-/Cutover-Verzeichnisse mit restriktiven Rechten lagen.
- Fix: `ops/h-drive-nearline/pull-critical-backups.ps1` kopiert fuer `borg-dumps-latest` nur noch die kuratierte Pflichtdatei-Liste und schliesst Migration-/Cutover-Verzeichnisse aus.
- Manueller Kontrolllauf 2026-06-01 08:25 erfolgreich: `borg-dumps-latest` Exit-Code 0, `gitea-bundles` Exit-Code 1 (Robocopy-Erfolg mit Kopien), Report `H:\kallilab-nearline-backups\_reports\nearline-pull-2026-06-01-082553.md`.
## Zweck
`H:/` ist eine zweite lokale Nearline-Kopie fuer die wichtigsten Restore-Artefakte. Es ersetzt weder Hetzner/Borg noch ein echtes Off-site-/Airgap-Ziel, reduziert aber das Risiko, dass ein lokaler Restore nur vom Unraid-Array abhaengt.
## Quelle und Ziel
| Zweck | Quelle | Ziel |
|---|---|---|
| Aktuelle kuratierte Dumps ohne Flash-Backup | `\\192.168.178.58\backups\borg\dumps\latest` | `H:\kallilab-nearline-backups\borg-dumps\latest` |
| Gitea-Bundles | `\\192.168.178.58\backups\git-bundles\gitea` | `H:\kallilab-nearline-backups\git-bundles\gitea` |
Das Skript kopiert bewusst **nicht** mit `/MIR` und loescht keine Dateien auf `H:/`. Alte Artefakte duerfen dort erst nach manueller Sichtpruefung geloescht werden.
Der Borg-Dumps-Job ist eine Whitelist der aktuellen Nearline-Pflichtartefakte. Einmalige Migrations-Sicherungen, Pre-Major-Snapshots und Redis-Cutover-Verzeichnisse bleiben ueber Borg/Hetzner abgedeckt, sind aber kein H:/-Nearline-Pflichtbestand.
## Skript
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File G:\Gitea_Clone\homelab-infra\ops\h-drive-nearline\pull-critical-backups.ps1 -WhatIf
```
Echter Lauf:
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File G:\Gitea_Clone\homelab-infra\ops\h-drive-nearline\pull-critical-backups.ps1
```
Reports landen unter:
```text
H:\kallilab-nearline-backups\_reports
```
Robocopy-Logs landen unter:
```text
H:\kallilab-nearline-backups\_logs
```
## Geplanter Schedule
Empfohlen: taeglich 05:30 Uhr, nach dem Borg-Dump-Fenster um ca. 04:00 Uhr.
Aktiv seit 2026-05-28. Tatsaechlicher Register-Befehl (RunLevel-Enum-Wert ist `Limited`, nicht `LeastPrivilege`):
```powershell
$Action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -File `"G:\Gitea_Clone\homelab-infra\ops\h-drive-nearline\pull-critical-backups.ps1`""
$Trigger = New-ScheduledTaskTrigger -Daily -At 05:30
$Settings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries `
-StartWhenAvailable `
-ExecutionTimeLimit (New-TimeSpan -Hours 2)
Register-ScheduledTask `
-TaskName "KalliLab H Drive Nearline Pull" `
-Action $Action `
-Trigger $Trigger `
-Settings $Settings `
-Description "Copies critical KalliLab restore artifacts from Unraid SMB backup share to H:/ nearline disk." `
-RunLevel Limited
```
Status pruefen:
```powershell
Get-ScheduledTask -TaskName "KalliLab H Drive Nearline Pull" | Format-List TaskName, State
Get-ScheduledTaskInfo -TaskName "KalliLab H Drive Nearline Pull" | Format-List LastRunTime, LastTaskResult, NextRunTime, NumberOfMissedRuns
```
Manueller Trigger zum Testen:
```powershell
Start-ScheduledTask -TaskName "KalliLab H Drive Nearline Pull"
```
Verhalten:
- Laeuft als angemeldeter User (`RunLevel Limited`); wenn der PC abgemeldet ist, wartet der Task bis zur naechsten Anmeldung (`StartWhenAvailable`).
- Akku-Modus blockiert nicht (`AllowStartIfOnBatteries`).
- Maximale Laufzeit 2 h, danach wird der Task abgebrochen.
## Erfolgscheck
Nach einem echten Lauf muessen mindestens diese Artefakte unter `H:\kallilab-nearline-backups` liegen:
- `borg-dumps\latest\immich.dump`
- `borg-dumps\latest\komodo-mongo.archive.gz`
- `borg-dumps\latest\postgresql17-paperless.dump`
- `borg-dumps\latest\postgresql17-mailarchiver.dump`
- `borg-dumps\latest\nextcloud.dump`
- `borg-dumps\latest\mealie.dump`
- `borg-dumps\latest\gitea.sqlite.dump`
- `borg-dumps\latest\vaultwarden.sqlite.dump`
- `git-bundles\gitea\latest-report.md`
- `git-bundles\gitea\micha\*.bundle`
Bewusst **nicht** im Nearline-Scope:
- `unraid-flash-config.tar.gz` (hostseitig 0600 root:root; Restore-Quelle bleibt das Hetzner-Borg-Repo, siehe `docs/RESTORE_MATRIX.md` Tier 1 Unraid OS Flash).
## Schutzregeln
- Kein CIFS-/SMB-Hard-Mount von `H:/` auf Unraid.
- Kein Borg-Repo direkt auf `H:/` ueber SMB.
- Kein `/MIR` und kein automatisches Loeschen auf `H:/`.
- Flash-Backup wie Secret behandeln; `H:/` bleibt lokaler Operator-Datentraeger.
+39 -70
View File
@@ -1,112 +1,81 @@
# Master To-do - KalliLab CORE # Master To-do - KalliLab CORE
Stand: 2026-06-06 (Wochenend-Sprint, nach Status-Kategorien sortiert) Typ: Status/To-do · Stand: 2026-06-11 · Status: aktiv
Diese Liste ist die zentrale Arbeitsliste fuer offene operative Punkte im Diese Liste ist die **einzige** Arbeitsliste fuer offene operative Punkte im
Homelab. Detailentscheidungen bleiben in den verlinkten Runbooks; diese Datei Homelab. Detailablaeufe stehen in den verlinkten Runbooks; Entscheidungen mit
haelt Status, naechsten konkreten Schritt und Quelle zusammen. Begruendung stehen in `docs/DECISIONS.md`; Belege fuer Erledigtes liegen in
Host-Reports (`/mnt/user/backups/restore-reports/`) und in der Git-Historie.
## Status-Kategorien ## Status-Kategorien
- **Aktiv dieses Wochenende** - soll jetzt vorankommen (Claude, Codex oder Operator); konkreter naechster Schritt steht. - **Aktiv** - soll vorankommen; konkreter naechster Schritt steht.
- **Operator-Entscheidung** - wartet auf eine bewusste Entscheidung des Betreibers (ja/nein/welche Option). - **Operator-Entscheidung** - wartet auf eine bewusste Entscheidung (ja/nein/Option).
- **Geparkt** - bewusst nicht jetzt, mit klarem Review-Trigger. - **Geparkt** - bewusst nicht jetzt, mit klarem Review-Trigger.
- **Extern blockiert** - wartet auf ein externes Ereignis oder eine Abhaengigkeit (Nachtlauf, zweite Hardware, Geraetebeschaffung). - **Extern blockiert** - wartet auf ein externes Ereignis oder eine Abhaengigkeit.
Owner-Aufteilung fuer das Wochenende: `baerchen`/Veeam/Backup-Verifikation liegt
bei **Codex**; Doku-/Inventar-/Onboarding-Arbeit liegt bei **Claude**;
Host-/Entscheidungsaufgaben beim **Operator**.
--- ---
## Aktiv dieses Wochenende ## Aktiv
| Thema | Owner | Naechster konkreter Schritt | Quelle | | Thema | Owner | Naechster konkreter Schritt | Quelle |
|---|---|---|---| |---|---|---|---|
| Family-Onboarding erster Termin | Operator | Checkliste ist fertig (`docs/FAMILY_ONBOARDING.md` Abschnitt "Erster Onboarding-Termin"). Operator legt fest, welche Personen/Geraete real verfuegbar sind, und arbeitet die Reihenfolge Vaultwarden -> Immich -> Mealie pro Person ab | `docs/FAMILY_ONBOARDING.md`, `docs/AUDIT_2026-05-25_TODO.md` | | Family-Onboarding erster Termin | Operator | Checkliste ist fertig (`docs/FAMILY_ONBOARDING.md` Abschnitt "Erster Onboarding-Termin"). Personen/Geraete festlegen, Reihenfolge Vaultwarden -> Immich -> Mealie pro Person abarbeiten | `docs/FAMILY_ONBOARDING.md` |
| Restore-Test Unraid OS Flash (Stick-Boot) | Operator | Artefakt-Validierung am 2026-06-05 erledigt (`ops/maintenance/check-unraid-flash-backup.sh`, sha256 OK, 8 Kern-Configs). **Verbleibt:** physischer Ersatzstick-Boot-Test, wenn ein Wegwerf-Stick bereitliegt | `docs/RESTORE_MATRIX.md` Abschnitt "Unraid OS Flash" | | Restore-Test Unraid OS Flash (Stick-Boot) | Operator | Artefakt-Validierung 2026-06-05 erledigt (`ops/maintenance/check-unraid-flash-backup.sh`). **Verbleibt:** physischer Ersatzstick-Boot-Test, wenn ein Wegwerf-Stick bereitliegt | `ops/restore-tests/unraid-flash-runbook.md` |
| Restore-Test Tailscale | Operator | Runbook-Stub abarbeiten: State-Validierung + Reconnect nur auf Wegwerf-Host/VM, danach Geraet in Tailscale-Admin entfernen | `docs/RESTORE_MATRIX.md` Abschnitt "Tailscale" | | Restore-Test Tailscale | Operator | State-Validierung + Reconnect nur auf Wegwerf-Host/VM, danach Geraet in Tailscale-Admin entfernen | `ops/restore-tests/tailscale-runbook.md` |
| Authelia OIDC fuer Apps | Operator/Claude | **Aktive Phase abgeschlossen 2026-06-06.** Live: Grafana (admin, Login verifiziert) + Mealie (family, verifiziert) + Paperless (family, deployed; Login-Test offen). Muster + Gotchas in `docs/AUTHELIA_OIDC_PLAN.md`. **Immich + Nextcloud bewusst GEPARKT bis Onboarding** (Entscheidung 2026-06-06): nur `micha` hat Authelia-Account, Familien-SSO-Nutzen + UI/occ-Aufwand lohnen erst mit Familien-Accounts. Runbook bereit | `docs/AUTHELIA_OIDC_PLAN.md`, `security/authelia/configuration.yml` | | Authelia OIDC fuer Apps | Operator/Claude | Live: Grafana + Mealie (verifiziert), Paperless deployed (Login-Test offen). Immich + Nextcloud bewusst geparkt bis Family-Onboarding (siehe `docs/DECISIONS.md` 2026-06-06) | `docs/AUTHELIA_OIDC_PLAN.md` |
--- ---
## Operator-Entscheidung ## Operator-Entscheidung
**Stand 2026-06-06: keine offenen Operator-Entscheidungen.** Alle am 2026-06-06 **Stand 2026-06-11: keine offenen Operator-Entscheidungen.**
entschieden — Ergebnisse in "Aktiv", "Geparkt" bzw. "Entschieden 2026-06-06". Getroffene Entscheidungen mit Begruendung und Review-Trigger: `docs/DECISIONS.md`.
--- ---
## Geparkt ## Geparkt
Bewusst nicht jetzt - mit Review-Trigger. Bewusst nicht jetzt - Begruendungen in `docs/DECISIONS.md`, hier nur Thema und Trigger.
| Thema | Entscheidung / Trigger | Quelle | | Thema | Review-Trigger | Quelle |
|---|---|---| |---|---|---|
| USV-Anschaffung | **Auf Q3/2026 geparkt** (2026-06-05). Power-Loss bleibt akzeptiertes Risiko. Trigger: Hardware-Upgrade, realer Stromausfall mit Datenfolge, oder Q3-Review ab 2026-07-01 | `docs/HARDWARE_INVENTORY.md` | | USV-Anschaffung | Q3-Review ab 2026-07-01, Hardware-Upgrade oder realer Stromausfall mit Datenfolge | `docs/DECISIONS.md` |
| Cold-Backup-Rotation | **Bewusst Hetzner-only** (2026-06-05). Keine zweite rotierende Cold-Kopie. Trigger: stark wachsender Datenwert, wiederholte Hetzner-Probleme, geaenderte Praeferenz | `docs/HARDWARE_INVENTORY.md` | | Cold-Backup-Rotation (zweites Off-site-Ziel) | Hetzner-Probleme, stark wachsender Datenwert oder geaenderte Praeferenz | `docs/DECISIONS.md` |
| WAN-Ausfallschutz | **Spaeter evaluieren** (2026-06-05). Mobilfunk-Failover inaktiv; lokale Apps laufen bei WAN-Ausfall weiter. Trigger: haeufigere/laengere DSL-Ausfaelle oder kritischer Remote-Zugang | `docs/NETWORK_INVENTORY.md` | | WAN-Ausfallschutz | haeufigere/laengere DSL-Ausfaelle oder kritischer Remote-Zugang | `docs/NETWORK_INVENTORY.md` |
| Docker Critical Events Watcher | **Aktiviert 2026-06-05:** Unraid User Script `docker-critical-events-at-start` nutzt den Supervisor und steht in `schedule.json` auf `frequency: start`; Watcher manuell gestartet, Status `running`. Optionaler ntfy-Smoke wurde nachts bewusst nicht gesendet und kann spaeter mit `docker-critical-events-supervisor.sh smoke` nachgeholt werden | `docs/SERVICE_CATALOG.md`, `services/posture-check/docker-critical-events.sh`, `services/posture-check/unraid-user-scripts.md` | | Borg `append-only` auf Hetzner | robusterer Hetzner-Mechanismus oder geaendertes Ransomware-Risikoprofil | `docs/DECISIONS.md` |
| Negativ-Test Backup-Frische | **Validiert 2026-06-06:** `ops/restore-tests/negative-freshness-alert-test.sh` simuliert fehlende Dumps nur in einem synthetischen Restore-Lab-Pfad und sendet einen Test-Alert nach `homelab-alerts`; Host-Lauf schrieb Report `/mnt/user/backups/restore-reports/freshness-negative-2026-06-06-130320.md` (10 Criticals, produktive Dumps unangetastet). Quartalsweise wiederholen: `ops/restore-tests/run-restore-checks.sh freshness-negative` | `ops/restore-tests/README.md`, `docs/AUDIT_2026-05-25_TODO.md` | | CrowdSec vor Traefik | breitere Attack Surface als nur `443/tcp` | `docs/DECISIONS.md` |
| End-to-end-DR-Drill | Komplett-Bootstrap Phase 1-5 auf Wegwerf-Host; realistisch erst mit zweiter Hardware (siehe auch Extern blockiert) | `docs/AUDIT_2026-05-25_TODO.md`, `docs/DISASTER_RECOVERY.md` | | Nextcloud 2FA (Operator-TOTP) | OIDC-/SSO-Block erreicht die App-Login-Ebene | `docs/DECISIONS.md` |
| Wiederkehrende Restore-Drills | Vaultwarden, Gitea, Authelia, Komodo, Paperless, Immich, Traefik, PostgreSQL, Mongo, Nextcloud, Mealie, Mail-Archiver nach Matrix-Intervallen rotieren | `docs/RESTORE_MATRIX.md`, `docs/RESTORE_HANDBOOK.md` | | Hermes-Agent | Review-Deadline 2026-07-25; NAS-Stack bleibt deaktiviert | `docs/SERVICE_CATALOG.md` |
| Dedizierter SMB-User `veeam-baerchen` | Optional spaeter, nur wenn Unraid-User-/Share-Rechte bewusst angefasst werden | `ops/windows-reinstall/docs/windows-image-backup-baseline.md` | | Tailnet-Konsole aufraeumen (Rest) | trivial, bei Gelegenheit: tote Node-Eintraege (`kallilab-core`, alter `baerchen`) in der Tailscale-Admin-Konsole entfernen; optional State-Pfad `/mnt/user/appdata/tailscale` nach `_archive/` | `docs/NETWORK_INVENTORY.md` |
| Nextcloud 2FA (Operator-TOTP) | **Geparkt (Entscheidung 2026-06-06):** Operator-TOTP fuer Nextcloud erst zusammen mit der app-weiten Familien-/OIDC-Policy entscheiden. Trigger: OIDC-/SSO-Block (jetzt aktiv) erreicht die App-Login-Ebene | `docs/AUDIT_2026-05-25_TODO.md` | | Dedizierter SMB-User `veeam-baerchen` | nur wenn Unraid-User-/Share-Rechte bewusst angefasst werden | `ops/windows-reinstall/docs/windows-image-backup-baseline.md` |
| Tailnet-Konsole aufraeumen (Rest) | Nach Docker-Stack-Abbau (2026-06-06) nur noch tote Node-Eintraege: `kallilab-core` (down) und alter Offline-`baerchen` in der Tailscale-Admin-Konsole entfernen. Optional State-Pfad `/mnt/user/appdata/tailscale` nach `_archive/`. Trivial, kein Risiko | `docs/NETWORK_INVENTORY.md` | | Filebrowser-Mount-Scope | naechster Hardening-Sprint | `docs/SERVICE_CATALOG.md` |
| CrowdSec vor Traefik | Bewusst nicht umgesetzt; einzige WAN-Tuer ist `443/tcp`, Authelia `regulation:` deckt Brute-Force ab. Neu bewerten bei breiterer Attack Surface | `docs/AUDIT_2026-05-25_TODO.md` | | Scrutiny Privileged-Ausnahme | nur mit klarer Begruendung aendern | `docs/SERVICE_CATALOG.md` |
| Hermes-Agent | NAS-Stack bleibt deaktiviert; Review-Deadline 2026-07-25 | `docs/AUDIT_2026-05-25_TODO.md`, `docs/SERVICE_CATALOG.md` | | Immich Redis named volume | passende Wartung am Immich-Stack | `docs/SERVICE_CATALOG.md` |
| Filebrowser-Mounts | Bei zukuenftigem Hardening-Sprint Mount-Scope reduzieren | `docs/SERVICE_CATALOG.md` | | Storage-Wachstum (zweite NVMe, zweite Array-Disk, ZFS/BTRFS) | Trigger aus Capacity-Doku | `docs/STORAGE_LAYOUT.md`, `docs/CAPACITY_AND_LIFECYCLE.md` |
| Scrutiny Privileged-Ausnahme | Nur mit klarer Begruendung aendern; sonst dokumentierte Ausnahme beibehalten | `docs/SERVICE_CATALOG.md` | | Wiederkehrende Restore-Drills | laufend nach Kadenz, inkl. quartalsweisem Frische-Negativtest (`run-restore-checks.sh freshness-negative`) | `docs/RESTORE_MATRIX.md`, `ops/restore-tests/schedule.md` |
| Immich Redis named volume | Anonymes Volume bei passender Wartung auf named volume umstellen oder Ausnahme dokumentieren | `docs/SERVICE_CATALOG.md` |
| Storage-Wachstum | Zweite NVMe, ZFS/BTRFS-Optionen, zweite Array-Disk nur bei Triggern aus Capacity-Doku | `docs/STORAGE_LAYOUT.md`, `docs/CAPACITY_AND_LIFECYCLE.md` |
| Zweites Off-site-Ziel | Bewusst nicht umgesetzt; neu bewerten bei Hetzner-Problemen oder wachsendem Datenwert | `docs/AUDIT_2026-05-25_TODO.md` |
| Borg `append-only` auf Hetzner | Operator-Entscheidung 2026-06-01: nicht umgesetzt (forced-command brach Key-Auth, Nutzen/Risiko unguenstig) | `docs/AUDIT_2026-05-25_TODO.md` |
--- ---
## Extern blockiert ## Extern blockiert
Wartet auf ein externes Ereignis oder eine Abhaengigkeit.
| Thema | Blockiert durch | Naechster Schritt sobald entblockt | Quelle | | Thema | Blockiert durch | Naechster Schritt sobald entblockt | Quelle |
|---|---|---|---| |---|---|---|---|
| End-to-end-DR-Drill (Hardware-Teil) | Keine zweite Wegwerf-Hardware verfuegbar | Sobald zweite Hardware da ist: Komplett-Bootstrap Phase 1-5 fahren | `docs/DISASTER_RECOVERY.md` | | End-to-end-DR-Drill | Keine zweite Wegwerf-Hardware verfuegbar | Komplett-Bootstrap Phase 1-5 fahren | `docs/DISASTER_RECOVERY.md` |
--- ---
## Erledigt im Wochenend-Sprint (2026-06-05) ## Zuletzt erledigt (Kurzlog, max. 5 Eintraege)
- Restore-Matrix "Naechste Restore-Test-Kandidaten" bereinigt: 5 am 2026-06-03 abgeschlossene Kandidaten entfernt, durch die 4 real offenen Pfade ersetzt; Stand-Datum aktualisiert. - **2026-06-11** Doku-Konsolidierung umgesetzt: `docs/archive/`, `docs/DECISIONS.md`, Statuslisten auf diese Datei reduziert, Restore-Doku zusammengefuehrt. Details: `docs/DECISIONS.md` Eintrag 2026-06-11.
- Restore-Test-Runbook-Stubs fuer Unraid Flash / AdGuard / Tailscale / Redis 8 in `docs/RESTORE_MATRIX.md` ergaenzt. - **2026-06-06** Wochenend-Sprint abgeschlossen: Veeam-Recovery-Test, DR-Workstation-Kit final (DR-Smoke OK), Tailscale-ACL restriktiv + redundanter Docker-Stack entfernt, Gast-/IoT-Netz validiert, AdGuard-/Redis-Restore-Smokes, Authelia-2FA-Catch-all, Frische-Negativtest. Belege: Host-Reports, `docs/DECISIONS.md`.
- Alte Windows-Doku bereinigt: WinRE-/Admin-Check-To-dos in `boot-cleanup-plan-2026-06-04.md` und `laufwerks-neustruktur-2026-06-04.md` als erledigt markiert. - **2026-06-03** Restore-Backlog geschlossen: Nextcloud, Shared-PG18-Cluster, Komodo-Mongo, Mailarchiver, Mealie, Traefik. Reports unter `/mnt/user/backups/restore-reports/`.
- `docs/HARDWARE_INVENTORY.md`: USV (Q3-Park), Cold-Backup (Hetzner-only) und Stromverbrauch von diffusen TBDs auf bewusste Entscheidungen mit Review-Triggern gehoben.
- `docs/NETWORK_INVENTORY.md`: Tailscale-Inventar am 2026-06-05 **real per read-only SSH gemessen** und eingetragen: IPv6 `fd7a:115c:a1e0::2c01:62b2`, Exit Node `nein`, **Subnet-Router fuer `192.168.178.0/24` aktiv** (widerlegt fruehere Vermutung), Tailnet `taild9fcf2.ts.net`, Geraete-Snapshot + Dubletten-Hinweis. WAN-Failover und Gast-/IoT geschaerft. `zu messen`-Platzhalter entfernt. **`Tailscale-Inventar messen` damit geschlossen.**
- `ops/maintenance/check-unraid-flash-backup.sh` neu: read-only Validierung des Flash-Artefakts (sha256, Frische, Kern-Configs, keine Extraktion). Am 2026-06-05 gegen den Host getestet: Exit 0, sha256 OK, 390 Eintraege, 8/8 Kern-Configs. `docs/RESTORE_MATRIX.md` mit Testdatum/Ergebnis aktualisiert. **Artefakt-Validierung des Unraid-Flash-Backups damit erledigt; nur Stick-Boot-Test offen.**
- `docs/FAMILY_ONBOARDING.md`: Michi-Checkliste in eine echte Erste-Termin-Checkliste (Vorbereitung, Reihenfolge, Erfolgskriterium, bewusst spaeter) umgebaut.
- `docs/MASTER_TODO.md` in vier Status-Kategorien (Aktiv / Operator-Entscheidung / Geparkt / Extern blockiert) umstrukturiert.
- `baerchen` Veeam-Erstbackup: erster Full-Lauf 2026-06-05 erfolgreich geschrieben (Veeam-GUI 53,8 GB, Dauer 0:11:31, MetaCheck 0 Fehler/0 Warnungen, VSS `job: success`). Beleg in `ops/windows-reinstall/docs/windows-image-backup-baseline.md`; Veeam Storage Encryption war im ersten Lauf nicht aktiv und ist als Operator-Entscheidung nachgezogen.
- Docker Critical Events Watcher auf Unraid aktiviert: Host-Clone auf Commit `2f3d184` aktualisiert, User Script `/boot/config/plugins/user.scripts/scripts/docker-critical-events-at-start/script` auf den Supervisor umgestellt, altes Script als `script.bak-20260605-232621` gesichert, `schedule.json` zeigt `frequency: start`, Watcher laeuft mit PID `1681168`. ntfy-Smoke am 2026-06-06 erfolgreich beim Operator angekommen.
- Restore-Test AdGuard Home: automatisierter Test `ops/restore-tests/adguard-restore-test.sh` erstellt und am 2026-06-06 auf Unraid erfolgreich ausgefuehrt. Ergebnis: Borg-Config-Restore aus Archiv `Taegliche-Sicherung-2026-06-06T04:30:05.910`, isolierter Container `restoretest-adguard`, HTTP `/control/status` = `401`, DNS-Smoke `git.kaleschke.info -> 192.168.178.58`, 7 Filterlisten-Eintraege, Report `/mnt/user/backups/restore-reports/adguard-2026-06-06.md`.
- Restore-Test Redis 8: automatisierter Test `ops/restore-tests/redis-restore-test.sh` erstellt und am 2026-06-06 auf Unraid erfolgreich ausgefuehrt. Ergebnis: Restore aus `/mnt/user/backups/borg/dumps/latest/shared-redis-pre-redis8-20260531-185011`, isolierter Container `restoretest-redis`, `PING` = `PONG`, Redis `8.8.0`, AOF `1`, `DBSIZE` = `1`, Report `/mnt/user/backups/restore-reports/redis-2026-06-06.md`.
- **Tailscale ACL-Policy restriktiv ausgerollt (2026-06-06):** Von Default-Allow auf Tag-basierte `grants`-Policy umgestellt, gemeinsam mit dem Operator in lockout-sicherer Reihenfolge (additiv -> taggen -> Allow-all entfernen), jeder Schritt read-only per SSH verifiziert. Live: `kallilabcore`=`tag:server`, `baerchen-1`+`iphone-14`=`tag:operator`, `tag:family` vorbereitet/schlafend. Subnet-Route `192.168.178.0/24` bleibt via `autoApprovers` approved. Smoke-Tests gruen (Operator-SSH, AdGuard-Admin `HTTP 302` ueber Tailnet, Ping 0%); untagged Nodes (`kallilab-core` Docker-Sidecar, alter `baerchen`) isoliert. Beleg: `docs/NETWORK_INVENTORY.md` Abschnitt "ACL-Policy — ANGEWENDET 2026-06-06". Familien-Dienste konkretisieren bei erstem realem Familiengeraet.
- **Redundanten Docker-Tailscale-Stack entfernt (2026-06-06):** Befund: Host hatte zwei `tailscaled` — die funktionale native Plugin-Instanz `kallilabcore` (echtes TUN `tailscale1`, Subnet-Router, State im Flash-Backup) und den redundanten userspace-only Docker-Stack `kallilab-core` (`host-services/tailscale/`, routet nichts, nichts haengt dran). Sauber per GitOps abgebaut: Operator hat Komodo-Stack `tailscale` gestoppt+destroyed; danach `git rm host-services/tailscale/`, Glance-Widget entfernt, Architektur-/Service-Catalog-/DR-Bootstrap-/CLAUDE-/Restore-Matrix-/Netzwerk-Doku auf "natives Plugin" nachgezogen. Read-only verifiziert: Container weg, nur noch der native `tailscaled`, Subnet-Route + Operator-Zugriff intakt. Rest: tote Node-Eintraege in der Admin-Konsole entfernen (eigener Todo).
- DR-Workstation Bare-Metal-Kit abgeschlossen: WSL2 Ubuntu 24.04 auf `baerchen`, Borg 1.2.8, GitHub-Read-DR-Key und Hetzner-DR-Key in WSL, `~/dr-smoke.sh` vorhanden. Finaler Smoke 2026-06-06 erfolgreich: GitHub HEAD `3a263a4...`, Hetzner Storage Box Repos sichtbar, Borg-Repo `hetzner_borg_appdata_critical` gelesen, Repository ID `5dd9b949...`, encrypted `Yes (repokey)`, `DR-Smoke OK (2026-06-06 10:05:30)`. Passphrase wurde nur interaktiv eingegeben und nicht gespeichert.
- Restore-Frische-Negativtest validiert: `ops/restore-tests/negative-freshness-alert-test.sh` erstellt und am 2026-06-06 auf Unraid erfolgreich ausgefuehrt. Ergebnis: synthetischer leerer Dump-Pfad erzeugte erwartungsgemaess 10 Criticals, Test-Alert nach `homelab-alerts` gesendet, Report `/mnt/user/backups/restore-reports/freshness-negative-2026-06-06-130320.md`, produktive Dumps unangetastet.
- Gast-/IoT-Netz aktiviert und validiert: FRITZ!Box-Gastzugang `Fritzi Gastzugang` aktiv, Heimnetz-Zugriff aus dem Gastnetz blockiert. LAN- und Host-Preflight gruen; iPhone-Smoke aus dem Gast-WLAN bestaetigt, dass `192.168.178.58:8082`, `:8181`, `:222`, `https://192.168.178.58` und `192.168.178.1` nicht erreichbar sind. Runbook: `docs/GUEST_IOT_NETWORK.md`.
- `baerchen` Veeam-Recovery-Test ohne echten Restore abgeschlossen: Recovery-USB `VEEAMRE` bootet, SMB-Ziel `\\kallilabcore\backups\windows-images\baerchen` ist in der Recovery Environment erreichbar, Restore Point wird angezeigt, Test vor echtem Restore abgebrochen. Runbook: `ops/windows-reinstall/docs/windows-image-backup-baseline.md`.
- **Operator-Entscheidungen 2026-06-06 abgeschlossen** (Liste damit ohne offene Entscheidungen):
- **BitLocker `baerchen`: bewusst deaktiviert.** Recovery laeuft ueber Veeam-Image; kein BitLocker-Key-Management. Restrisiko physischer Diebstahl bewusst akzeptiert.
- **Veeam Storage Encryption: bewusst unverschluesselt.** Erster Full-Lauf bleibt; Image liegt auf dem lokalen SMB-Share `\\kallilabcore\backups`. Neu bewerten bei Off-host-Auslagerung des Images.
- **Stromverbrauch: bewusst ohne Messung.** Kein Messgeraet; Werte bleiben dauerhaft offen, kein Beschaffungs-Todo mehr.
- **Authelia Rest-2FA: KOMPLETT erledigt 2026-06-06.** Catch-all `*.kaleschke.info` -> `two_factor` in Repo **und** Host-Config (chirurgische Einzelzeilen-Aenderung mit Backup, OIDC-Beszel-Client + Secret unangetastet), `docker restart authelia` -> healthy + "Startup complete", Operator-2FA-Login auf einer vorher-1FA-Domain verifiziert. Nebenbei vorbestehenden Drift gefunden+bereinigt (Host-Config war vom 25. Mai, borg/code nie gemerged); Repo-Baseline an Host-Endzustand angeglichen, damit `authelia-diff.sh` clean wird sobald der Host-Mirror nachzieht. Rollback-`.bak` auf dem Host vorhanden.
- **Authelia OIDC: angehen** (neuer aktiver Block) — **Gast-/IoT-Netz: einrichten/planen** (neuer aktiver Block) — **Nextcloud 2FA: geparkt** bis OIDC die App-Login-Ebene erreicht.
--- ---
## Pflege-Regel ## Pflege-Regel
- Neue operative To-dos zuerst hier eintragen oder aus Detaildokumenten hierher uebernehmen, immer mit Status-Kategorie. - Neue operative To-dos zuerst hier eintragen, immer mit Status-Kategorie.
- Wenn ein Punkt erledigt ist, in der Detaildoku den Beleg/Report eintragen und diese Liste aktualisieren. - Erledigt: Beleg liegt im Host-Report bzw. Commit; hier nur ein Kurzlog-Eintrag (max. 3 Zeilen), aelteste Eintraege fliegen raus, sobald mehr als 5.
- Entscheidungen (auch "bewusst nein") gehoeren mit Begruendung nach `docs/DECISIONS.md`, hier nur Thema + Trigger.
- Keine vagen "pruefen"-Eintraege ohne Kommando oder Entscheidung. - Keine vagen "pruefen"-Eintraege ohne Kommando oder Entscheidung.
- Historische Drill-Reports bleiben Belegmaterial, aber nicht die fuehrende Arbeitsliste.
+27 -17
View File
@@ -1,8 +1,13 @@
# Documentation Index # Documentation Index
Stand: 2026-06-05 Typ: Einstieg/Index · Stand: 2026-06-11 · Status: aktiv
Diese Datei trennt aktive Betriebsdokumentation von historischer Arbeitsdoku. Neue operative Dokumente duerfen nur in `docs/` liegen, wenn sie heute als Einstieg, Runbook, Inventar oder offene Arbeitsliste gebraucht werden. Erledigte Audits, Chat-Handoffs, Prompt-Dateien und abgeschlossene Plaene bleiben in der Git-Historie, aber nicht als dauerhafte Arbeitskopie. Diese Datei trennt aktive Betriebsdokumentation von historischer Arbeitsdoku.
Neue operative Dokumente duerfen nur in `docs/` liegen, wenn sie heute als
Einstieg, Runbook, Inventar, Entscheidung oder Statusliste gebraucht werden.
Abgeschlossene Audits, Drills und Plaene wandern nach `archive/` oder werden
geloescht (Git-Historie ist das Archiv). Verbindliche Doku-Regeln:
`REPO_MAP.md` Abschnitt "Doku-Regeln".
## Pflicht-Einstieg ## Pflicht-Einstieg
@@ -11,19 +16,22 @@ Diese Datei trennt aktive Betriebsdokumentation von historischer Arbeitsdoku. Ne
| `../README.md` | kurzer Repo-Einstieg | | `../README.md` | kurzer Repo-Einstieg |
| `../HOMELAB_ARCHITECTURE_MASTER_V2.md` | Architektur-Quelle fuer Netz, Zugriff und Ausnahmen | | `../HOMELAB_ARCHITECTURE_MASTER_V2.md` | Architektur-Quelle fuer Netz, Zugriff und Ausnahmen |
| `WORKFLOW.md` | verbindlicher GitOps-/No-Drift-Ablauf | | `WORKFLOW.md` | verbindlicher GitOps-/No-Drift-Ablauf |
| `REPO_MAP.md` | technische Landkarte des Repositories | | `REPO_MAP.md` | technische Landkarte des Repositories + Doku-Regeln |
| `SERVICE_CATALOG.md` | produktiver Service-Katalog | | `SERVICE_CATALOG.md` | produktiver Service-Katalog |
| `DECISIONS.md` | Entscheidungs-Register (ADR-light) |
| `MASTER_TODO.md` | einzige operative Statusliste |
## Betrieb und Recovery ## Betrieb und Recovery
| Datei | Zweck | | Datei | Zweck |
|---|---| |---|---|
| `DISASTER_RECOVERY.md` | Wiederanlauf nach Host-/Systemausfall | | `DISASTER_RECOVERY.md` | Wiederanlauf nach Host-/Systemausfall |
| `RESTORE_MATRIX.md` | Restore-Quellen, Dumps, Secrets und Smoke-Tests je Dienst | | `RESTORE_MATRIX.md` | Restore-Quellen, Dumps, Secrets, Smoke-Tests und Test-Reifegrad je Dienst |
| `RESTORE_HANDBOOK.md` | praktische Restore-Anleitung |
| `SERVICES_RECOVERY.md` | Gitea-/Komodo-/Services-Bootstrap | | `SERVICES_RECOVERY.md` | Gitea-/Komodo-/Services-Bootstrap |
| `ROLLBACK.md` | Rueckweg bei GitOps-/Deploy-Fehlern | | `ROLLBACK.md` | Rueckweg bei GitOps-/Deploy-Fehlern |
| `GITOPS_DRIFT_RUNBOOK.md` | Pflichtmatrix bei Drift zwischen Git, Komodo, Docker und Host | | `GITOPS_DRIFT_RUNBOOK.md` | Pflichtmatrix bei Drift zwischen Git, Komodo, Docker und Host |
| `DR_WORKSTATION_SETUP.md` | DR-Gaming-PC einrichten (WSL2 + Borg-Client + SSH-Keys) |
| `../ops/restore-tests/README.md` | Restore-Test-Betrieb, Skripte und Kadenz |
## Inventare und Policies ## Inventare und Policies
@@ -32,12 +40,12 @@ Diese Datei trennt aktive Betriebsdokumentation von historischer Arbeitsdoku. Ne
| `STORAGE_LAYOUT.md` | verbindliche Storage-/Share-/Pfad-Regeln | | `STORAGE_LAYOUT.md` | verbindliche Storage-/Share-/Pfad-Regeln |
| `SECRETS_MAP.md` | Secret-Namen, Speicherorte und Einbindungsarten ohne Werte | | `SECRETS_MAP.md` | Secret-Namen, Speicherorte und Einbindungsarten ohne Werte |
| `AUTHELIA_OIDC_PLAN.md` | Plan & Runbook fuer app-uebergreifendes SSO via Authelia OIDC | | `AUTHELIA_OIDC_PLAN.md` | Plan & Runbook fuer app-uebergreifendes SSO via Authelia OIDC |
| `HARDWARE_INVENTORY.md` | Host-, Disk-, SMART-, USV- und Power-Baseline | | `HARDWARE_INVENTORY.md` | Host-, Disk-, SMART- und Power-Baseline |
| `NETWORK_INVENTORY.md` | Router, DNS, Tailscale, Portfreigaben und Netzthemen | | `NETWORK_INVENTORY.md` | Router, DNS, Tailscale, Portfreigaben und Netzthemen |
| `GUEST_IOT_NETWORK.md` | Sicherer Ablauf fuer FRITZ!Box-Gastnetz / IoT-Isolation | | `GUEST_IOT_NETWORK.md` | Sicherer Ablauf fuer FRITZ!Box-Gastnetz / IoT-Isolation |
| `EXTERNAL_DEPENDENCIES.md` | Provider, Konten und externe Abhaengigkeiten | | `EXTERNAL_DEPENDENCIES.md` | Provider, Konten, DR-Workstation-Kit und externe Abhaengigkeiten |
| `EXTERNAL_OPERATOR_RUNBOOK.md` | Hetzner-/Borg-/FRITZ!Box-Betreibercheck | | `EXTERNAL_OPERATOR_RUNBOOK.md` | Hetzner-/Borg-/FRITZ!Box-Betreibercheck |
| `CAPACITY_AND_LIFECYCLE.md` | Kapazitaet, Wachstum und Upgrade-Trigger | | `CAPACITY_AND_LIFECYCLE.md` | Kapazitaet, Wachstum, Upgrade-Trigger, H:/-Nearline-Einordnung |
## Monitoring und Automatisierung ## Monitoring und Automatisierung
@@ -45,18 +53,20 @@ Diese Datei trennt aktive Betriebsdokumentation von historischer Arbeitsdoku. Ne
|---|---| |---|---|
| `ALERT_RULES.md` | Prometheus-/ntfy-Regeln und Handlungslogik | | `ALERT_RULES.md` | Prometheus-/ntfy-Regeln und Handlungslogik |
| `RENOVATE.md` | Self-hosted Renovate gegen Gitea | | `RENOVATE.md` | Self-hosted Renovate gegen Gitea |
| `HOME_ASSISTANT_INFLUXDB_ECOWITT.md` | Archivierter Entwurf: Home Assistant -> InfluxDB 3 -> Grafana; nicht aktiv seit Crash | | `runbooks/komodo-bulk-deploy-dns.md` | Bulk-Deploy-Pulls scheitern an DNS bei AdGuard-Recreate |
| `H_DRIVE_NEARLINE_PULL.md` | Windows-H:/ Nearline-Pull fuer kritische Restore-Artefakte | | `../ops/h-drive-nearline/README.md` | Windows-H:/ Nearline-Pull fuer kritische Restore-Artefakte |
## Nutzer- und Planungsdoku ## Nutzer- und Statusdoku
| Datei | Zweck | | Datei | Zweck |
|---|---| |---|---|
| `FAMILY_ONBOARDING.md` | familienverstaendliche Nutzungsdoku | | `FAMILY_ONBOARDING.md` | familienverstaendliche Nutzungsdoku |
| `AUDIT_2026-05-25_TODO.md` | kompakte Restliste aus dem Audit-Zyklus | | `AI_CONTEXT.md` | kompakter Kontext fuer KI-Agenten (Regeln + Pointer, kein Status) |
| `MASTER_TODO.md` | zentrale operative Master-To-do-Liste ueber alle Bereiche | | `homelab-optimierung.md` | technisches Optimierungs-Assessment 2026-06-10 (offene Empfehlungen) |
| `WEEKEND_EXECUTION_PLAN_2026-06-05.md` | Owner-Aufteilung und Wochenendplan fuer Todo-Abschluss |
| `WEEKEND_STATUS_2026-06-05.md` | kurzlebiges Arbeitsboard fuer den laufenden Wochenend-Sprint |
| `AI_CONTEXT.md` | kompakter Kontext fuer KI-Agenten |
Windows-Neuaufsetzen-Dokumente liegen nicht mehr in `docs/`, sondern im fachlich passenden Ordner `../ops/windows-reinstall/docs/`. ## Archiv
Abgeschlossene Snapshots, Drills und Audits: `archive/README.md`.
Windows-Neuaufsetzen-Doku (Projekt abgeschlossen) liegt ebenfalls dort;
aktiv geblieben sind nur Veeam-Baseline und Laufwerksstruktur unter
`../ops/windows-reinstall/`.
+11 -5
View File
@@ -33,7 +33,8 @@ Details gilt immer die betroffene Compose-Datei oder das jeweilige Runbook.
| `docs/RESTORE_MATRIX.md` | Restore-Quelle je Dienst | | `docs/RESTORE_MATRIX.md` | Restore-Quelle je Dienst |
| `docs/SECRETS_MAP.md` | Secret-Namen und Pfade ohne Werte | | `docs/SECRETS_MAP.md` | Secret-Namen und Pfade ohne Werte |
| `docs/GITOPS_DRIFT_RUNBOOK.md` | Git/Gitea/Komodo/Docker/Host-Drift | | `docs/GITOPS_DRIFT_RUNBOOK.md` | Git/Gitea/Komodo/Docker/Host-Drift |
| `docs/AUDIT_2026-05-25_TODO.md` | aktuelle Restliste | | `docs/MASTER_TODO.md` | einzige operative Statusliste |
| `docs/DECISIONS.md` | Entscheidungs-Register (ADR-light) |
| `docs/DR_WORKSTATION_SETUP.md` | Schritt-fuer-Schritt-Runbook fuer den DR-Gaming-PC (WSL2 + Borg-Client + SSH-Keys) | | `docs/DR_WORKSTATION_SETUP.md` | Schritt-fuer-Schritt-Runbook fuer den DR-Gaming-PC (WSL2 + Borg-Client + SSH-Keys) |
| `docs/runbooks/komodo-bulk-deploy-dns.md` | Bulk-Deploy-Pulls scheitern an DNS, wenn AdGuard im selben Batch recreated wird | | `docs/runbooks/komodo-bulk-deploy-dns.md` | Bulk-Deploy-Pulls scheitern an DNS, wenn AdGuard im selben Batch recreated wird |
@@ -50,8 +51,13 @@ Details gilt immer die betroffene Compose-Datei oder das jeweilige Runbook.
| `services/authelia-diff.sh` | Authelia ACL Repo-zu-Host-Vergleich | | `services/authelia-diff.sh` | Authelia ACL Repo-zu-Host-Vergleich |
| `ops/h-drive-nearline/pull-critical-backups.ps1` | H:/ Nearline-Pull | | `ops/h-drive-nearline/pull-critical-backups.ps1` | H:/ Nearline-Pull |
## Arbeitsregel ## Doku-Regeln
Neue Doku nur anlegen, wenn sie dauerhaft als Runbook, Inventar oder Restliste 1. **Ein Fakt, ein Zuhause.** Status -> `docs/MASTER_TODO.md`; Entscheidungen -> `docs/DECISIONS.md`; Zielbild -> `HOMELAB_ARCHITECTURE_MASTER_V2.md`/Inventare/`SERVICE_CATALOG`; Ablauf -> genau ein Runbook; Beleg -> Host-Report (`/mnt/user/backups/restore-reports/`) oder Git-Commit. Alle anderen Stellen verlinken statt kopieren.
gebraucht wird. Einmalige Audits, Prompt-Kopien und lange Verlaufsprotokolle 2. **Erledigt = raus aus der Arbeitskopie.** Abgeschlossene Plaene, Sprints, Audits und Drills nach `docs/archive/` (Belege mit Referenzwert) oder loeschen (Sprint-Boards, erledigte Listen) - Git ist das Archiv.
gehoeren in Git-Commits, nicht als neue Markdown-Dateien. 3. **Neue Datei nur mit klarem Typ:** Einstieg/Index, Architektur, Inventar/Referenz, Runbook, Entscheidung, Status oder befristeter Snapshot. Sonst ist es ein Eintrag in einer bestehenden Datei.
4. **Done-Eintraege max. 3 Zeilen**, Details in Commit/Report; Kurzlog in `MASTER_TODO` max. 5 Eintraege.
5. **Datum im Dateinamen nur fuer Snapshots**; datierte Dateien im `docs/`-Root sind per Definition Aufraeum-Kandidaten.
6. **Index-Pflicht:** jede neue/geloeschte Doku-Datei aktualisiert `docs/README.md` im selben Commit.
7. **Quartals-Gaertnern (~15 min):** Datiertes archivieren, Done-/Review-Logs kuerzen, tote Links pruefen.
8. **Kopfzeile je Dokument:** `Typ: ... · Stand: YYYY-MM-DD · Status: ...`. Bestandsnamen (SCREAMING_SNAKE) bleiben; neue Dateien in Unterordnern in kebab-case.
-250
View File
@@ -1,250 +0,0 @@
# Restore Handbook - KalliLab CORE
Stand: 2026-06-03
Dieses Handbuch ist die praktische Betriebsanleitung fuer Restore-Checks und Restore-Lab in KalliLab CORE.
Es ergaenzt:
- `docs/RESTORE_MATRIX.md`
- `docs/DISASTER_RECOVERY.md`
- `ops/restore-tests/*`
---
## 1. Ziel
Dieses Handbuch beantwortet vier Fragen:
1. Was ist die Restore-Quelle?
2. Wo wird getestet?
3. Wie pruefen wir Erfolg?
4. Wie machen wir das regelmaessig mit wenig Handarbeit?
---
## 2. Grundmuster
Alle validierten Restore-Tests folgen demselben Muster:
- Quelle bleibt das produktive Borg-Repo bei Hetzner
- Borg-Zugriff laeuft ueber den vorhandenen `borg-ui`-Container
- Passphrase kommt aus `/mnt/user/appdata/secrets/borg_repo_passphrase.txt`
- Testdaten landen unter `/mnt/user/backups/restore-lab/<dienst>`
- Reports landen unter `/mnt/user/backups/restore-reports`
- Testinstanzen laufen lokal ohne Traefik und ohne produktive Domain
- nach Erfolg werden Testcontainer und Testdaten wieder entfernt
---
## 3. Bereits praktisch verifiziert
### Vaultwarden
- Erstlauf: 2026-05-07
- Nachweis: Borg-Restore, Testcontainer, Login-Seite erreichbar
### Gitea
- Erstlauf: 2026-05-07
- Nachweis: Borg-Restore, Web-UI, SSH-TCP-Port
### Paperless
- Erstlauf: 2026-05-07, Folgelauf: 2026-05-31
- Nachweis: Borg-Datei-Restore, Dump-Import in Test-Postgres, Login-Seite, Doc-Count
### Immich
- Erstlauf: 2026-05-27
- Nachweis: DB-Dump-Restore in VectorChord-Test-Postgres, HTTP-Smoke, Asset-Count
- Hinweis: Foto-Dateien-Restore ist bewusst nicht Teil des Smokes
### Authelia
- Erstlauf: 2026-06-03
- Nachweis: Config-Borg-Restore, `authelia config validate`, HTTP-Health `/api/health`
- Hinweis: Daten-Restore des produktiven Dumps ist bewusst nicht Teil des Smokes (Storage-Encryption-Key-Kopplung)
### Komodo Bootstrap
- Erstlauf: 2026-05-30
- Nachweis: Compose-Validierung, Mongo healthy, Core HTTP, Periphery running
- Hinweis: Daten-Restore aus `komodo-mongo.archive.gz` ist noch nicht getestet
---
## 4. Verzeichnisstruktur
### Produktiv
- `/mnt/user/appdata`
- `/mnt/user/services`
- `/mnt/user/documents`
- `/mnt/user/backups/borg/dumps/latest`
### Restore-Lab
- `/mnt/user/backups/restore-lab/vaultwarden`
- `/mnt/user/backups/restore-lab/gitea`
- `/mnt/user/backups/restore-lab/paperless`
- `/mnt/user/backups/restore-lab/immich`
- `/mnt/user/backups/restore-lab/authelia`
- `/mnt/user/backups/restore-lab/komodo`
- `/mnt/user/backups/restore-lab/_failed` (Diagnose-Material bei Fehllaeufen)
### Reports
- `/mnt/user/backups/restore-reports`
---
## 5. Restore-Frequenz
- jeden Montag, 06:30: Frische-Check fuer Dumps und Reports
- 1. Samstag im Monat, 07:00: Vaultwarden
- 3. Samstag im Monat, 07:15: Gitea
- 2. Samstag in ungeraden Monaten, 08:00: Paperless
- 2. Sonntag in Feb/Mai/Aug/Nov, 08:30: Immich
- 2. Samstag in geraden Monaten, 07:30: Authelia
- 1. Kalendertag im Monat, 09:00: Zufaelliger Restore aus Pool
Vollstaendiger Kalender mit Cron-Ausdruecken und Shell-Guards steht in `ops/restore-tests/schedule.md`.
---
## 6. Betriebsmodus
Stand 2026-06-03 ist der Betrieb auf V1+ (V1 mit ntfy):
- validierte Bash-Host-Jobs fuer Vaultwarden, Gitea, Paperless, Immich, Authelia, Komodo-Bootstrap
- Host-Job-Definitionen und Cron-Vorlagen liegen im Repo (`ops/restore-tests/unraid-user-scripts.md`)
- `ntfy`-Wrapper sendet Erfolg an `homelab-info`, Fehler an `homelab-alerts`
- Frische-Check prueft zusaetzlich pg-Custom-Format-Dumps per `pg_restore --list` Header-Validierung
- bei Fehlschlag wird das Restore-Lab nach `_failed/` verschoben statt geloescht
Noch geplant fuer V2:
- Hermes-Zusammenfassung ueber vorhandene Reports
- Sammelreports und Report-Rotation
- weitere Dienste (Nextcloud, Mailarchiver, Mealie)
---
## 7. User Script Jobs auf Unraid
Die Vorlagen stehen in:
- `ops/restore-tests/unraid-user-scripts.md`
Host-Repo-Pfad:
```text
/mnt/user/services/homelab-infra
```
Jobs:
1. `restore-freshness-weekly`
2. `restore-vaultwarden-monthly`
3. `restore-gitea-monthly`
4. `restore-paperless-bimonthly`
5. `restore-immich-quarterly`
6. `restore-authelia-bimonthly`
7. `monthly-random-restore`
---
## 8. Erfolgskriterien
Ein Restore-Test gilt nur dann als erfolgreich, wenn:
- Restore-Quelle lesbar war
- Daten im Restore-Lab ankamen
- Testcontainer startete
- Smoke-Test erfolgreich war
- Report geschrieben wurde
Nur `Container laeuft` reicht nicht.
---
## 9. Sicherheitsregeln
- keine produktiven Pfade beschreiben
- keine produktiven Container fuer Restore-Tests verwenden
- keine produktiven Domains fuer Testinstanzen verwenden
- keine Secrets im Repo
- keine Restore-Automatik fuer neue Dienste ohne bewusste Freigabe
---
## 10. Schnellstart
### Frische-Check
Auf dem Unraid-Host:
```bash
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh freshness
```
### Vaultwarden Restore-Check
```bash
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh vaultwarden
```
### Gitea Restore-Check
```bash
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh gitea
```
### Paperless Restore-Check
```bash
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh paperless
```
### Immich Restore-Check
```bash
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh immich
```
### Authelia Restore-Check
```bash
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh authelia
```
### Komodo Bootstrap Trockenlauf
```bash
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh komodo-bootstrap
```
### Optional mit `ntfy`
```bash
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-job-with-ntfy.sh freshness homelab-info
```
---
## 11. Naechste Ausbaustufen
1. Nextcloud-Restore-Test (mit `occ maintenance:mode`-Choreographie)
2. Mailarchiver-Restore-Test
3. Mealie-Restore-Test
4. Komodo-Mongo-Daten-Restore (echtes `mongorestore` statt reinem Bootstrap)
5. Shared-PostgreSQL-18-Cluster-Restore-Drill (globals + per-DB-Dumps)
6. Traefik-Restore-Test (mit `dynamic/` und LE-State)
7. Hermes-Zusammenfassung ueber vorhandene Reports
8. Report-Rotation (archivieren nach 12 Monaten)
9. Negativ-Test: bewusst kaputten Dump in den Frische-Check einfuettern
## 12. Report-Aufbewahrung
Reports unter `/mnt/user/backups/restore-reports` werden dauerhaft aufbewahrt. Bei wachsender Anzahl (ca. 50-60 pro Jahr) empfiehlt sich eine jaehrliche Archivierung alter Reports in einen Unterordner `_archive/YYYY/`. Der Frische-Check warnt bei `MAX_REPORT_AGE_DAYS=45`, loescht aber bewusst nicht automatisch.
+7 -166
View File
@@ -170,173 +170,14 @@ wurden alle am 2026-06-03 abgeschlossen und sind in der Reifegrad-Tabelle belegt
Verbleibende offene Restore-Pfade ohne vollstaendigen Test: Verbleibende offene Restore-Pfade ohne vollstaendigen Test:
1. **Unraid OS Flash** - Artefakt-Validierung am 2026-06-05 erfolgreich (siehe Reifegrad-Tabelle und Runbook unten); offen bleibt nur der **physische Ersatzstick-Boot-Test**. 1. **Unraid OS Flash** - Artefakt-Validierung am 2026-06-05 erfolgreich (siehe Reifegrad-Tabelle und `ops/restore-tests/unraid-flash-runbook.md`); offen bleibt nur der **physische Ersatzstick-Boot-Test**.
2. **Tailscale** - State-/Reconnect-Pfad dokumentiert testen 2. **Tailscale** - State-/Reconnect-Pfad dokumentiert testen (`ops/restore-tests/tailscale-runbook.md`)
--- ---
## Restore-Test-Runbooks (Entwurf) ## Restore-Test-Runbooks
Diese Abschnitte sind vorbereitete Checklisten fuer die noch untesteten Restore-Pfade. Die Ablaeufe je Dienst liegen als Runbooks und automatisierte Skripte unter
Sie sind **nicht** als produktive Anleitungen zu verwenden, bevor ein erster Testlauf `ops/restore-tests/` (Einstieg: `ops/restore-tests/README.md`). Fuer die noch
die konkreten Artefaktnamen und Pfade bestaetigt hat. offenen Pfade: `ops/restore-tests/unraid-flash-runbook.md` und
`ops/restore-tests/tailscale-runbook.md`.
### Unraid OS Flash
**Voraussetzungen:**
- Borg-Artefakt `unraid-flash-config.tar.gz` und `unraid-flash-config.tar.gz.sha256` unter `/mnt/user/backups/borg/dumps/latest` oder im Hetzner-Borg-Repo verfuegbar
- Neuer leerer USB-Stick (Empfehlung: 16 GB, USB 2.0 kompatibel)
- Unraid USB Flash Creator oder manueller Restore-Pfad
- Offline-gesicherte Borg-Passphrase verfuegbar
**Checkliste Artefakt-Validierung (ohne produktiven Stick):**
Automatisiert via Repo-Skript `ops/maintenance/check-unraid-flash-backup.sh`
(read-only, keine Extraktion). Manuelle Einzelschritte:
1. SHA256-Pruefung: `sha256sum -c unraid-flash-config.tar.gz.sha256`
2. Artefakt-Inhalt pruefen: `tar -tzf unraid-flash-config.tar.gz | head -40` — erwartet `config/` als Prefix
3. Kern-Configs vorhanden: `super.dat`, `disk.cfg`, `ident.cfg`, `share.cfg`, `network.cfg`, `docker.cfg`, `go`, `domain.cfg`
4. Keine produktiven Konfigurationspfade (z. B. `config/ssh/`) ausserhalb des Test-Environments extrahieren
5. Manifest-Datei auf Vollstaendigkeit pruefen
**Validierungsergebnis 2026-06-05 (read-only per SSH):** Artefakt frisch
(2026-06-05 04:00, ~16 h alt beim Test), `sha256sum -c` = OK, 390 Eintraege,
alle 8 Kern-Configs vorhanden. Das Archiv enthaelt erwartungsgemaess
Secret-Material (SSH-Host-Keys, Tailscale-State, `passwd`/`shadow`/`smbpasswd`,
`Trial.key`) und ist wie Secret-Backup zu behandeln. Es wurde nichts extrahiert,
nur Eintragsnamen gelistet. Offen bleibt der physische Ersatzstick-Boot-Test.
**Checkliste vollstaendiger Restore-Test (auf Wegwerf-Stick):**
1. Neuen USB-Stick mit Unraid USB Flash Creator formatieren und Basis-Unraid draufspielen
2. `config/`-Verzeichnis aus `unraid-flash-config.tar.gz` in den `/boot/config`-Pfad des neuen Sticks extrahieren
3. Im Testrahmen booten (kein Array starten, keine Shares mounten)
4. Pruefen: Unraid-Grundkonfiguration (Shares, Hostname, Netzwerk) ist sichtbar
5. Array-Zuordnung lesbar, ohne Drive-Assigns zu bestaetigen
**Smoke-Test-Kriterium:** Unraid bootet, Hostname ist `Kallilabcore`, Share-Konfiguration ist sichtbar, kein Array gestartet.
**Sonderregel:** Das Artefakt enthaelt Host-Konfiguration und SSH-Keys und ist wie Secret-Material zu behandeln. Nicht auf oeffentlichen oder unverschluesselten Testzielen extrahieren.
---
### AdGuard Home
**Validierungsergebnis 2026-06-06:** Automatisierter Test
`ops/restore-tests/adguard-restore-test.sh` auf Unraid erfolgreich ausgefuehrt.
Report: `/mnt/user/backups/restore-reports/adguard-2026-06-06.md`.
Getestet wurden Borg-Extract der Config, `AdGuardHome.yaml`-Struktur,
isolierter Testcontainer `restoretest-adguard` auf localhost-Ports,
HTTP `/control/status` = `401`, DNS-Smoke `git.kaleschke.info -> 192.168.178.58`,
7 Filterlisten-Eintraege. Testdaten wurden nach Erfolg bereinigt.
**Voraussetzungen:**
- Borg-Archiv mit `/mnt/user/appdata/adguard/conf` zugaenglich (produktives Repo oder Teststand)
- Testpfad unter `/mnt/user/backups/restore-lab/adguard` vorbereitet
- Docker-Faehigkeit auf dem Testhost oder in der Restore-Lab-Umgebung
**Automatisierter Test:**
```bash
/mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh adguard
```
**Manuelle Checkliste:**
1. Borg-Extract des letzten Archivs nach `/mnt/user/backups/restore-lab/adguard/conf`:
```
borg extract ::ARCHIV /mnt/user/appdata/adguard/conf
```
2. Konfigurationsdatei `AdGuardHome.yaml` auf Vollstaendigkeit pruefen (YAML-Syntax valide)
3. Testcontainer starten (kein produktiver DNS-Port 53, stattdessen z. B. `15353`):
```yaml
ports:
- "127.0.0.1:15353:53/udp"
- "127.0.0.1:13001:80/tcp"
volumes:
- /mnt/user/backups/restore-lab/adguard/conf:/opt/adguardhome/conf
```
4. `http://127.0.0.1:13001/control/status` erreichbar (`200`, `401` oder `403` sind fuer den Smoke ausreichend)
5. DNS-Aufloesung: `dig @127.0.0.1 -p 15353 git.kaleschke.info` gibt plausible Antwort
6. Testcontainer stoppen und Testpfad aufraeumen
**Smoke-Test-Kriterium:** AdGuard-Web-UI laeuft, DNS-Aufloesung antwortet, Filterlisten sind geladen.
**Keine Secrets:** AdGuard Home verwendet keine dokumentierten Repo-Secrets; Login-Credentials liegen in der `AdGuardHome.yaml` im Borg-Archiv.
---
### Tailscale
**Voraussetzungen:**
- Borg-Archiv mit `/mnt/user/appdata/tailscale` zugaenglich
- Testpfad unter `/mnt/user/backups/restore-lab/tailscale` vorbereitet
- Achtung: Der Tailscale-State ist maschinenspezifisch. Ein Restore auf denselben produktiven Host wuerde die laufende Verbindung verdraengen. Nur auf einem Wegwerf- oder Offline-Host testen.
**Checkliste Artefakt-Validierung (ohne produktiven Host):**
1. Borg-Extract nach `/mnt/user/backups/restore-lab/tailscale`
2. State-Verzeichnis auf erwartete Dateien pruefen: `tailscaled.state` vorhanden
3. Dateisystem-Rechte pruefen: `tailscaled.state` muss fuer `root` zugaenglich sein
**Checkliste Reconnect-Test (auf Wegwerf-Host oder VM):**
1. Tailscale-Container mit dem gemounteten State-Pfad starten
2. `tailscale status` zeigt `Connected` oder den erwarteten Hostnamen
3. Tailscale-Admin-Konsole (`login.tailscale.com`) zeigt Geraet als `Online`
4. SSH ueber Tailscale-IP auf den Testhost moeglich
5. Testcontainer stoppen; Wegwerf-Geraet in der Tailscale-Admin-Konsole entfernen
**Smoke-Test-Kriterium:** Container verbindet sich mit bestehendem Tailscale-Account (kein neues Re-Auth noetig), Tailscale-IP ist erreichbar.
**Hinweis:** Falls der State veraltet ist (Key expired), wird Tailscale einen Re-Auth anfordern. Das ist ein valides Testergebnis und belegt, wie lang der Reconnect-Pfad bei abgelaufenem Key ist.
---
### Redis 8 (Shared)
**Validierungsergebnis 2026-06-06:** Automatisierter Test
`ops/restore-tests/redis-restore-test.sh` auf Unraid erfolgreich ausgefuehrt.
Report: `/mnt/user/backups/restore-reports/redis-2026-06-06.md`.
Getestet wurde das Pre-Cutover-Artefakt
`/mnt/user/backups/borg/dumps/latest/shared-redis-pre-redis8-20260531-185011`
in einer isolierten Redis-8.8-Testinstanz auf `127.0.0.1:16379`.
Ergebnis: `PING` = `PONG`, `redis_version` = `8.8.0`, AOF aktiv (`1`),
`DBSIZE` = `1`. Produktiver Port und produktiver Datenpfad wurden nicht genutzt.
**Voraussetzungen:**
- Pre-Cutover-Backup unter `/mnt/user/backups/borg/dumps/latest/shared-redis-pre-redis8-<ts>` vorhanden, oder Borg-Archiv mit `/mnt/user/appdata/redis`
- Secret-Datei `redis_password.txt` fuer Testinstanz verfuegbar (aus Borg, nicht als Wert dokumentieren)
- Testpfad unter `/mnt/user/backups/restore-lab/redis` vorbereitet
**Automatisierter Test:**
```bash
/mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh redis
```
**Manuelle Checkliste:**
1. RDB/AOF-Datei aus dem Backup in den Testpfad kopieren:
```
cp /mnt/user/backups/borg/dumps/latest/shared-redis-pre-redis8-<ts>/dump.rdb \
/mnt/user/backups/restore-lab/redis/
```
(oder Borg-Extract aus dem Appdata-Archiv)
2. Testcontainer starten (kein produktiver Port 6379, stattdessen z. B. `16379`):
```yaml
ports:
- "127.0.0.1:16379:6379"
volumes:
- /mnt/user/backups/restore-lab/redis:/data
command: redis-server --requirepass <aus Secret> --appendonly yes
```
3. Verbindungstest: `redis-cli -p 16379 -a <pass> PING` antwortet `PONG`
4. Redis-Version pruefen: `redis-cli -p 16379 -a <pass> INFO server | grep redis_version` zeigt `8.x`
5. Stichprobe Key-Bestand: `redis-cli -p 16379 -a <pass> DBSIZE` zeigt plausible Zahl (nicht 0)
6. Testcontainer stoppen und Testpfad aufraeumen
**Smoke-Test-Kriterium:** Redis 8 startet mit dem Restore-Datenpfad, `PING` antwortet, `DBSIZE` ist nicht 0.
**Shared Redis Besonderheit:** Shared Redis wird produktiv nur von Paperless genutzt (AOF aktiv). Bei einem echten Restore nach App-Absturz: Erst Redis aus Backup hochziehen, dann Paperless. Nextcloud hat eigene Redis-Instanz ohne Passwort.
+14 -63
View File
@@ -1,6 +1,10 @@
# Rollback Guide - Homelab # Rollback Guide - Homelab
Typ: Runbook · Stand: 2026-06-11 · Status: aktiv
Dieses Dokument beschreibt den sicheren Rueckweg im aktuellen GitOps-Betrieb. Dieses Dokument beschreibt den sicheren Rueckweg im aktuellen GitOps-Betrieb.
Rollback-Anleitungen fuer bereits entfernte Dienste (Uptime-Kuma, Grafana-/
InfluxDB-Altstack, Stirling-PDF) liegen in der Git-Historie, nicht mehr hier.
--- ---
@@ -72,59 +76,14 @@ Bei Problemen mit Borg UI oder Dump-Automatisierung:
3. Persistenz unter `/mnt/user/appdata/borg-ui/` und `/mnt/user/backups/borg/dumps/` nicht blind loeschen 3. Persistenz unter `/mnt/user/appdata/borg-ui/` und `/mnt/user/backups/borg/dumps/` nicht blind loeschen
4. Restore zuerst in einen Testpfad schreiben, nicht direkt in Produktivpfade 4. Restore zuerst in einen Testpfad schreiben, nicht direkt in Produktivpfade
## BentoPDF / Stirling-PDF Rollback ## Monitoring-Stack Rollback
Bei Problemen mit BentoPDF: `monitoring/` ist der einzige Observability-Stack. Bei Problemen:
1. Git-Stand auf die letzte funktionierende Stirling-PDF-Compose zuruecknehmen oder gezielt `apps/bentopdf` wieder durch `apps/stirling-pdf` ersetzen
2. Commit + Push nach Gitea
3. betroffenen Stack in Komodo redeployen
4. `https://pdf.kaleschke.info` pruefen
Die alte Stirling-PDF-Persistenz unter `/mnt/user/appdata/stirling-pdf` nicht loeschen, solange der BentoPDF-Ersatz nicht fachlich abgenommen ist.
## Grafana / InfluxDB Rollback
Vor dem ersten produktiven Einsatz reicht es, den vorbereiteten Stack nicht zu deployen oder per Ruecknahme-Commit aus dem Repo zu entfernen.
Nach einem Deploy:
1. alten Grafana/InfluxDB-Stack in Komodo gestoppt lassen; der fruehere Compose-Pfad `ops/grafana-influxdb` ist seit 2026-05-26 nicht mehr im aktiven Repo
2. Persistenz unter `/mnt/user/appdata/grafana` und `/mnt/user/appdata/influxdb3` unangetastet lassen
3. Secrets unter `/mnt/user/appdata/secrets/grafana_admin_password.txt`, `/mnt/user/appdata/secrets/grafana_influxdb_token.txt` und `/mnt/user/appdata/secrets/influxdb3_admin_token.json` nur nach bewusstem Entscheid entfernen
4. Grafana-Domain und InfluxDB-Zugriff testen, bis klar ist, dass keine produktiven Dashboards oder Writer mehr davon abhaengen
## Monitoring-Zielstack Rollback
Der Zielzustand ist `monitoring/` als einziger Observability-Stack. Bei Problemen nach der Migration:
1. `monitoring` in Komodo stoppen oder auf den letzten funktionierenden Commit zurueckgehen 1. `monitoring` in Komodo stoppen oder auf den letzten funktionierenden Commit zurueckgehen
2. nur im echten Notfall die abgeloesten Altstaende aus der Git-Historie vor dem Repo-Cleanup wiederherstellen, z. B. aus Commit `ff5991c`; nicht dauerhaft parallel zum Zielstack betreiben 2. named volumes `prometheus_data`, `loki_data`, `promtail_positions`, `grafana_data` sowie `/mnt/user/appdata/influxdb3` nicht blind loeschen
3. named volumes `prometheus_data`, `loki_data`, `promtail_positions`, `grafana_data` sowie `/mnt/user/appdata/influxdb3` nicht blind loeschen 3. Secrets (`monitoring_grafana_admin_password.txt`, `monitoring_grafana_influxdb_token.txt`, `influxdb3_admin_token.json`) nur nach bewusstem Entscheid entfernen
4. Secrets `monitoring_grafana_admin_password.txt`, `monitoring_grafana_influxdb_token.txt` und `influxdb3_admin_token.json` nur nach bewusstem Entscheid entfernen 4. Grafana-Datasources `Prometheus`, `Loki` und `InfluxDB 3 Core` testen
5. Home Assistant Writer erst wieder umstellen, wenn `curl -i http://192.168.178.58:8181/` erwartbar `401 Unauthorized` liefert
6. Grafana-Datasources `Prometheus`, `Loki` und `InfluxDB 3 Core` testen
## Uptime Kuma Removal Rollback
Falls die Blackbox-/Grafana-Ablösung unerwartet nicht ausreicht:
1. per Ruecknahme-Commit `ops/uptime-kuma/docker-compose.yml`, die Blackbox-/Glance-/Authelia-Referenzen und die Restore-Freshness-Pruefung auf den letzten Uptime-Kuma-Stand zurueckbringen
2. nach Gitea pushen und den Uptime-Kuma-Stack in Komodo neu anlegen oder aus dem letzten Stack-Backup wiederherstellen
3. `/mnt/user/appdata/_archive/uptime-kuma-removed-2026-05-25` nach `/mnt/user/appdata/uptime-kuma` zurueckverschieben, falls die Archivierung bereits erfolgt ist
4. `https://uptime.kaleschke.info` und die Monitore pruefen
5. erst danach den Blackbox-/Grafana-Zielzustand erneut bewerten
## Glance Dashboard Rollback
Vor dem ersten produktiven Einsatz reicht es, den vorbereiteten Stack `ops/glance` nicht zu deployen oder per Ruecknahme-Commit aus dem Repo zu entfernen.
Nach einem Deploy:
1. `glance` in Komodo stoppen oder auf den letzten funktionierenden Commit zurueckgehen
2. keine Produktivdaten loeschen; Glance nutzt nur Repo-Konfiguration und Stack-ENV
3. pruefen, ob `https://glance.kaleschke.info` nicht mehr geroutet wird oder wieder den erwarteten Stand zeigt
4. der `glance-docker-socket-proxy` darf nicht separat als Dauercontainer laufen bleiben
--- ---
@@ -132,19 +91,11 @@ Nach einem Deploy:
Bevorzugte Quellen: Bevorzugte Quellen:
- Borg-Restore - Borg-Restore (zuerst in Testpfade unter `/mnt/user/backups/restore-lab/`)
- erzeugte PostgreSQL-/MariaDB-Dumps - erzeugte Dumps unter `/mnt/user/backups/borg/dumps/latest`
- bekannte Appdata-Snapshots - bekannte Appdata-Archivstaende unter `/mnt/user/appdata/_archive/`
Beispiele: Dienst-spezifische Restore-Quellen, Dumps und Smoke-Tests stehen in `docs/RESTORE_MATRIX.md`.
```bash
cp -r /mnt/user/appdata/<service> /mnt/user/backup/
```
```bash
pg_dumpall > /mnt/user/backup/pg_dump_$(date +%Y%m%d).sql
```
--- ---
+2 -12
View File
@@ -142,8 +142,7 @@ Erst nach erfolgreichem Komodo-Bootstrap werden produktive Stacks ueber den doku
Trockenlauf gegen Wegwerf-Pfade ist seit 2026-05-29 als Repo-Skript abgelegt: Trockenlauf gegen Wegwerf-Pfade ist seit 2026-05-29 als Repo-Skript abgelegt:
`ops/restore-tests/komodo-bootstrap-compose.test.yml`, `ops/restore-tests/komodo-bootstrap-compose.test.yml`,
`ops/restore-tests/komodo-bootstrap-test.sh`, `ops/restore-tests/komodo-bootstrap-test.sh` und
`ops/restore-tests/komodo-bootstrap-plan.md` und
`ops/restore-tests/komodo-bootstrap-runbook.md`. Aufruf: `ops/restore-tests/komodo-bootstrap-runbook.md`. Aufruf:
```bash ```bash
@@ -203,13 +202,4 @@ Authoritativ ist `docs/SECRETS_MAP.md`. Fuer den Kaltstart ist diese Reihenfolge
- Wenn Gitea und Komodo beide down sind, gewinnt der externe GitHub-Mirror als Repo-Quelle. - 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. - 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 Offene Folgepunkte werden in `docs/MASTER_TODO.md` gefuehrt.
| 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 |
+2 -2
View File
@@ -42,7 +42,7 @@ Es ist **vor** jeder Storage- oder Compose-Änderung zu lesen. Wenn ein neuer St
| Disk1 (Array) | WDC WD60EFAX-68JH4N1 (`WD-WX32D90PC0V0`) | **XFS** auf `md1p1` | 5.5T nutzbar | Nutzdaten, Backups, Services | NTFS-zu-XFS-Migration Phase 2 abgeschlossen am 2026-05-25 | | Disk1 (Array) | WDC WD60EFAX-68JH4N1 (`WD-WX32D90PC0V0`) | **XFS** auf `md1p1` | 5.5T nutzbar | Nutzdaten, Backups, Services | NTFS-zu-XFS-Migration Phase 2 abgeschlossen am 2026-05-25 |
| Parity | TOSHIBA HDWG480 (`2460A03VFA3H`) | — (keine FS) | 7.3T | Redundanz für Array | Unverändert | | Parity | TOSHIBA HDWG480 (`2460A03VFA3H`) | — (keine FS) | 7.3T | Redundanz für Array | Unverändert |
| Boot | Samsung Flash Drive (`0375125090000587`) | FAT32 | 59.8G | Unraid-OS, Konfiguration | Regelmäßig per Flash-Backup gesichert | | Boot | Samsung Flash Drive (`0375125090000587`) | FAT32 | 59.8G | Unraid-OS, Konfiguration | Regelmäßig per Flash-Backup gesichert |
| Externe Backup-Platte | H:/ `Externe HDD` am Windows-PC | NTFS | 8.0T | Nearline-Pull-Ziel für kritische Restore-Artefakte | Kein Off-site-/Airgap-Ersatz; Pull-Workflow in `docs/H_DRIVE_NEARLINE_PULL.md` | | Externe Backup-Platte | H:/ `Externe HDD` am Windows-PC | NTFS | 8.0T | Nearline-Pull-Ziel für kritische Restore-Artefakte | Kein Off-site-/Airgap-Ersatz; Pull-Workflow in `ops/h-drive-nearline/README.md` |
Physikalische Basisdaten sind aus `docs/HARDWARE_INVENTORY.md` und dem Host-Readout vom 2026-05-27 übernommen. Detailwerte zu SMART/Health bleiben dort die autoritative Quelle; dieses Dokument hält die Storage-Policy. Physikalische Basisdaten sind aus `docs/HARDWARE_INVENTORY.md` und dem Host-Readout vom 2026-05-27 übernommen. Detailwerte zu SMART/Health bleiben dort die autoritative Quelle; dieses Dokument hält die Storage-Policy.
@@ -384,4 +384,4 @@ Wenn Hermes-Worker auf weiteren Hosts skaliert: dieser Storage-Layout-Plan gilt
Status: **Active v1.4 seit 2026-05-27**. Status: **Active v1.4 seit 2026-05-27**.
Detailhistorie und alte Review-Tabellen liegen in der Git-Historie. Aktuelle Folgepunkte stehen nicht mehr hier, sondern in `docs/AUDIT_2026-05-25_TODO.md`. Detailhistorie und alte Review-Tabellen liegen in der Git-Historie. Aktuelle Folgepunkte stehen nicht mehr hier, sondern in `docs/MASTER_TODO.md`.
-151
View File
@@ -1,151 +0,0 @@
# Weekend Execution Plan - 2026-06-05 bis 2026-06-07
Ziel: Bis Ende des Wochenendes alle offenen To-dos aus `docs/MASTER_TODO.md`
entweder erledigen, verifiziert schliessen, oder bewusst als geparkt/extern
blockiert markieren. Nicht jeder Punkt ist realistisch "fertig" im Sinne von
technisch umgesetzt: Family-Onboarding, zweite Hardware, USV und WAN-Failover
brauchen Operator- oder Hardware-Entscheidungen.
## Arbeitsregeln
- Secrets niemals in Chat, Logs oder Repo schreiben.
- Homelab-Aenderungen nur via GitOps, keine direkten Komodo-/Docker-Hotfixes.
- Destruktive Windows- oder Host-Schritte nur nach expliziter Freigabe.
- Ergebnis jedes abgeschlossenen Punkts in der Detaildoku und in
`docs/MASTER_TODO.md` nachziehen.
- Am Ende: ein sauberer Commit-Block; Push erst nach Freigabe.
## Owner-Aufteilung
| Owner | Fokus | Ergebnis |
|---|---|---|
| Codex | `baerchen` Veeam, Doku-Konsolidierung, lokale Checks, Commit-Vorbereitung | Veeam-Erstbackup geprueft, Recovery-Test dokumentiert, Masterliste aktualisiert |
| Claude | Family-Onboarding-Paket, Network-/Tailscale-Entscheidungen, Hardware-/Todo-Konsolidierung, nicht-destruktive Runbooks | Konkrete Doku-Patches, ausfuehrbare Checklisten, klare Operator-Fragen statt diffuser TBDs |
| Operator | Physische/GUI-Schritte, Secrets, Familie, Hardwareentscheidungen | Recovery-USB booten, Passwoerter/Keys bereitstellen, Family-Onboarding starten/entscheiden |
## Codex-Aufgaben
| Prioritaet | Aufgabe | Abschlusskriterium |
|---|---|---|
| P1 | Veeam-Erstbackup `baerchen-c-image` pruefen | **erledigt 2026-06-05:** Full-Lauf geschrieben, Veeam-GUI 53,8 GB, Dauer 0:11:31, MetaCheck 0 Fehler/0 Warnungen; Storage Encryption war nicht aktiv und ist als Operator-Entscheidung dokumentiert |
| P1 | Recovery-USB-Test begleiten | `VEEAMRE` bootet, SMB-Ziel sichtbar, Restore Point sichtbar, vor Restore abgebrochen |
| P1 | `windows-image-backup-baseline.md` finalisieren | Erster Lauf und Teststatus mit Datum eingetragen |
| P1 | `docs/MASTER_TODO.md` nach jedem Abschluss aktualisieren | erledigte Punkte entfernt oder in "geschlossen" vermerkt |
| P2 | Alte Windows-Reinstall-Doku bereinigen | ueberholte WinRE-/Admin-To-dos als erledigt/ueberholt markiert |
| P2 | Git-Status sortieren | Eigene Aenderungen klar von vorhandenen User-Aenderungen getrennt |
| P2 | Commit vorbereiten | Commit-Message-Vorschlag und Datei-Liste bereit; kein Push ohne Freigabe |
## Claude-Aufgaben
Claude soll parallel nur repo-seitig arbeiten und keine produktiven Host-Aenderungen
ausfuehren. Die Aufgaben sind bewusst als echte Doku-/Planungsarbeit formuliert,
nicht nur als Pruefaufgaben:
| Prioritaet | Aufgabe | Abschlusskriterium |
|---|---|---|
| P1 | `docs/MASTER_TODO.md` gegen Detaildokus gegenpruefen | **erledigt 2026-06-05:** Sync-Notiz in `docs/AUDIT_2026-05-25_TODO.md`, Masterliste aktualisiert |
| P1 | Restore-Backlog aktualisieren | **erledigt 2026-06-05:** erledigte Kandidaten aus `docs/RESTORE_MATRIX.md` bereinigt |
| P1 | Family-Onboarding in ein ausfuehrbares Session-Paket umwandeln | **erledigt 2026-06-05:** `docs/FAMILY_ONBOARDING.md` enthaelt Vorbereitungs-, Termin- und Erfolgskriterien ohne Secret-Werte |
| P1 | `docs/NETWORK_INVENTORY.md` TBDs in Entscheidungen oder konkrete Operator-Fragen verwandeln | **erledigt 2026-06-05:** Tailscale IPv6/Exit Node/Subnet Router/ACL-Policy sind als Messaufgabe/Operator-Entscheidung formuliert; Gast-/WAN-Pfade sind geparkt oder mit Vorbedingungen versehen |
| P2 | Nicht-destruktive Runbooks fuer offene Restore-Tests vorbereiten | **erledigt 2026-06-05:** Runbook-Stubs fuer Unraid Flash, AdGuard, Tailscale, Redis 8 in `docs/RESTORE_MATRIX.md` |
| P2 | `docs/AUDIT_2026-05-25_TODO.md` und `MASTER_TODO.md` synchronisieren | **erledigt 2026-06-05:** keine doppelten oder widerspruechlichen P1/P2-Punkte |
| P2 | Windows-Reinstall-Altdoku auf ueberholte To-dos pruefen | **erledigt 2026-06-05:** WinRE/Admin-Check-Altlasten als erledigt/ueberholt markiert |
| P2 | Hardware-/Betriebsentscheidungen konsolidieren | **teilweise erledigt 2026-06-05:** USV und Cold-Backup-Rotation sind entschieden/geparkt; Masterliste fuehrt sie nicht mehr als aktive Umsetzungsaufgaben |
| P3 | Geparkte Punkte klassifizieren | Family/USV/WAN/CrowdSec/OIDC klar als Entscheidung statt Umsetzungsarbeit markiert |
## Operator-Aufgaben
| Prioritaet | Aufgabe | Abschlusskriterium |
|---|---|---|
| P1 | Veeam-Encryption-Entscheidung treffen | Fuer den ersten Full-Lauf ist kein Veeam-Encryption-Passwort noetig; falls Storage Encryption aktiviert wird, Passwort in Vaultwarden anlegen und neues Full erzeugen |
| P1 | Recovery-USB physisch booten | Boot ins Veeam-Recovery-System gelingt |
| P1 | Keine echten Restore-Ziele bestaetigen | Restore-Test wird vor destruktiver Datentraegerauswahl abgebrochen |
| P2 | BitLocker-Entscheidung treffen | `aktivieren`, `spaeter`, oder `bewusst aus` dokumentiert |
| P2 | Family-Onboarding real starten oder terminieren | konkreter Termin/Personenkreis statt offenem Wunsch |
| P3 | Hardware-Entscheidungen | USV/Cold-Rotation/WAN-Failover als kaufen, spaeter, oder bewusst nein markieren |
## Realistische Wochenend-Ziele
Bis Sonntagabend realistisch fertig:
- `baerchen` Veeam-Erstbackup verifiziert.
- `baerchen` Recovery-USB-Test ohne Restore verifiziert.
- Veeam-/BitLocker-Doku bereinigt.
- Master-To-do-Liste bereinigt.
- Restore-Backlog sortiert.
- Alte/ueberholte To-dos als erledigt/ueberholt markiert.
- Blockierte Punkte explizit als Betreiber-/Hardware-/Familienentscheidung markiert.
Nicht realistisch ohne externe Voraussetzungen:
- End-to-end-DR-Drill ohne zweite Hardware.
- Family-Onboarding ohne Familie/Geraete.
- USV erledigen ohne Kauf.
- WAN-Failover erledigen ohne Mobilfunk-/Router-Entscheidung.
- Dedizierter SMB-User ohne bewusste Unraid-User-/Share-Aenderung.
## Prompt fuer Claude
```text
Du bist Claude im KalliLab CORE Homelab-Repo.
Arbeitsziel fuer dieses Wochenende:
Hilf, alle offenen To-dos aus `docs/MASTER_TODO.md` bis Sonntagabend entweder
zu erledigen, sauber zu dokumentieren, oder bewusst als geparkt/blockiert zu
klassifizieren. Arbeite repo-seitig, keine produktiven Host-Aenderungen.
Pflichtregeln:
- Lies zuerst `CLAUDE.md`.
- Lies danach `HOMELAB_ARCHITECTURE_MASTER_V2.md`, `docs/WORKFLOW.md`,
`docs/README.md`, `docs/REPO_MAP.md`, `docs/MASTER_TODO.md`,
`docs/RESTORE_MATRIX.md`, `docs/DISASTER_RECOVERY.md`,
`docs/SECRETS_MAP.md` und `ops/windows-reinstall/docs/windows-image-backup-baseline.md`.
- Keine Secrets ins Repo. Nur Secret-Namen, Pfade und Ablageorte dokumentieren.
- Keine Komodo-/Docker-/Host-Hotfixes. Keine produktiven Schreibbefehle auf dem Homelab.
- Keine destruktiven Aktionen.
- Beachte vorhandene uncommitted Aenderungen; nichts revertieren, was du nicht selbst gemacht hast.
Konkrete Aufgaben:
1. Wandle `docs/FAMILY_ONBOARDING.md` von einer guten Erklaerseite in ein
ausfuehrbares Session-Paket um:
- 30-Minuten-Ablauf fuer das erste echte Onboarding
- Checkliste pro Geraet/Person ohne Namen oder Secret-Werte
- klare Abschlusskriterien fuer Vaultwarden, Immich und Mealie
- Liste der Operator-Fragen, falls Konten/Startpasswoerter fehlen
2. Bereinige `docs/NETWORK_INVENTORY.md`:
- Tailscale IPv6, Exit Node, Subnet Router und ACL-Policy nicht als
unerklaerte `TBD` stehen lassen
- wenn nicht verifizierbar: als konkrete Operator-Frage oder bewusst offene
Entscheidung formulieren
- Gast-/IoT-Zugriff als Entscheidungspfad dokumentieren, nicht als vage
Altlast
3. Ziehe `docs/MASTER_TODO.md` nach deinen Edits nach:
- echte naechste Schritte in P1/P2
- geparkte Entscheidungen nur im geparkten/geschlossenen Bereich
- keine Duplikate zu `docs/AUDIT_2026-05-25_TODO.md`
4. Falls du weitere diffuse TBDs in Hardware/Network/Family findest: nicht nur
melden, sondern in konkrete Entscheidung, geparkten Punkt oder naechsten
Operator-Schritt umformulieren.
5. Schon erledigte Restore-/Windows-Doku-Aufgaben nicht erneut bearbeiten,
ausser du findest einen klaren Widerspruch.
6. Am Ende liefere:
- geaenderte Dateien
- welche Punkte geschlossen wurden
- welche Punkte blockiert/geparkt bleiben und warum
- welche Operator-Schritte noch noetig sind
Nicht tun:
- Keine Secrets anzeigen oder erfinden.
- Kein Push.
- Kein `docker`, `ssh` oder Host-Schreibzugriff.
- Kein BitLocker, keine Veeam-Aenderung, keine Unraid-User-/Share-Aenderung.
```
## Abschlusskriterien fuer Sonntag
- `docs/MASTER_TODO.md` ist die fuehrende Liste.
- Alle erledigten Punkte haben Beleg in der Detaildoku.
- Alle nicht erledigbaren Punkte sind als blockiert/geparkt mit Grund markiert.
- `git status` ist verstanden: eigene Doku-Aenderungen vs. bestehende
User-Aenderungen sind getrennt.
- Commit ist vorbereitet, Push erfolgt nur nach Operator-Freigabe.
-41
View File
@@ -1,41 +0,0 @@
# Weekend Status - 2026-06-05
Kurzlebiges Arbeitsboard fuer den Wochenend-Sprint. Fuehrende Liste bleibt
`docs/MASTER_TODO.md`; dieses Board haelt nur den aktuellen Arbeitsstand fest.
## Jetzt laufend
| Owner | Aufgabe | Status | Naechster Schritt |
|---|---|---|---|
| Codex | Veeam-Erstbackup `baerchen-c-image` | erledigt | Erster Full-Lauf 2026-06-05 geschrieben; Recovery-Test bleibt offen |
| Codex | Veeam-Verifikationshilfe | erledigt | Hilfsskript bleibt fuer spaetere Checks verfuegbar |
| Claude | Restore-/Altdoku-Bereinigung | erledigt | Keine weitere Arbeit an Veeam/Windows/Restore-Matrix ohne neuen Widerspruch |
| Claude | Family-/Network-Ausfuehrungspaket | erledigt | Masterliste und Weekend-Plan sind nachgezogen |
## Naechste Operator-Schritte
| Zeitpunkt | Aufgabe | Ergebnis, das dokumentiert wird |
|---|---|---|
| Erledigt | Veeam-Erstbackup `baerchen-c-image` pruefen | 2026-06-05 19:46, Full-Lauf erfolgreich, Veeam-GUI 53,8 GB, Dauer 0:11:31 |
| Als naechstes | Recovery-USB `VEEAMRE` booten | Boot OK, Netzwerk OK, SMB-Ziel sichtbar |
| Im Recovery-Test | Restore Point anzeigen; falls spaeter verschluesselt: Passwort testen | Restore Point sichtbar; vor echtem Restore abgebrochen |
| Spaeter | BitLocker-Entscheidung treffen | `aktivieren`, `spaeter`, oder `bewusst aus` in `docs/MASTER_TODO.md`/Baseline nachziehen |
## Heute bereits geschlossen
| Thema | Ergebnis |
|---|---|
| WinRE/Admin-Altlasten | In Windows-Reinstall-Doku als erledigt/ueberholt markiert |
| Restore-Test-Kandidaten | Erledigte Kandidaten aus der aktiven Liste entfernt; Stubs fuer offene Kandidaten ergaenzt |
| Family-Onboarding | Aus der Familien-Doku wurde ein konkreter 30-45-Minuten-Terminablauf mit Vorbereitung und Erfolgskriterien |
| Network-TBDs | Tailscale-/Gastnetz-/WAN-Failover-Punkte wurden in Messaufgaben, Vorbedingungen oder geparkte Entscheidungen umgewandelt |
| Veeam-Erstbackup | Full-Lauf 2026-06-05 erfolgreich geschrieben: Veeam-GUI 53,8 GB, Dauer 0:11:31, MetaCheck 0 Fehler/0 Warnungen, VSS success; Veeam Storage Encryption war nicht aktiv |
| Cold-Backup-Rotation | Bewusst Hetzner-only; kein aktives Todo mehr |
| USV | Bewusst auf Q3/2026 geparkt; Power-Loss bleibt akzeptiertes Risiko |
## Nicht ohne neue Freigabe anfassen
- Keine BitLocker-Aktivierung.
- Keine Aenderung am Veeam-Job oder Encryption-Status.
- Keine Unraid-User-/Share-Aenderung.
- Keine produktiven Host- oder Docker-Schreibbefehle.
+7 -1
View File
@@ -369,7 +369,13 @@ Wenn ein Stack `webhook_enabled` in Komodo hatte, zusaetzlich pruefen, ob der zu
## Dokumentationspflicht ## Dokumentationspflicht
Nach jeder erfolgreichen Migration oder relevanten Aenderung muessen diese Dateien geprueft werden: Es gilt "ein Fakt, ein Zuhause" (`docs/REPO_MAP.md` Doku-Regeln): aktualisiert
wird das jeweils zustaendige Dokument plus `docs/README.md`-Index, nicht
mehrere Kopien. Nach jeder relevanten Aenderung pruefen, **welche** dieser
Zuhause betroffen sind:
- `docs/DECISIONS.md` falls eine bewusste Entscheidung getroffen oder revidiert wurde
- `docs/MASTER_TODO.md` falls sich der Status offener Punkte aendert
- `docs/SECRETS_MAP.md` - `docs/SECRETS_MAP.md`
- `docs/ROLLBACK.md` - `docs/ROLLBACK.md`
@@ -0,0 +1,401 @@
# Homelab-Doku-Optimierung — Analyse und Vorschlag 2026-06-11
Typ: Analyse / Optimierungsvorschlag · Stand: 2026-06-11 · Status: **umgesetzt am 2026-06-11** (archiviert; siehe `docs/DECISIONS.md` Eintrag 2026-06-11). Nicht umgesetzt blieben nur: Hermes-README-Kuerzung (beim Review 2026-07-25), PDF-Ablage extern (Operator), optionale Projekte aus Abschnitt 13.
Read-only-Analyse der gesamten Markdown-Dokumentation (Stand `master`, lokale
Arbeitskopie 2026-06-11). Es wurde nichts gelöscht, verschoben oder verändert;
dieses Dokument ist der einzige neue Inhalt. Abgrenzung: `docs/homelab-optimierung.md`
(2026-06-10) bewertet die **technische** Betriebsebene; dieses Dokument bewertet
ausschließlich die **Dokumentation und ihre Regeln**.
---
## 1. Executive Summary
Die Doku ist inhaltlich exzellent und ungewöhnlich diszipliniert gepflegt —
das Problem ist nicht Qualität oder Veralterung, sondern **Volumen, Mehrfachpflege
und fehlende Lebenszyklus-Regeln**. Kennzahlen:
- **74 versionierte Markdown-Dateien, ~9.400 Zeilen** (davon `docs/`: 35 Dateien / ~5.050 Zeilen, `ops/`: 34 Dateien).
- Praktisch alle Dateien wurden in den letzten 4 Wochen angefasst — es gibt **kein Stale-Problem, aber ein Pflegelast-Problem**.
- Ein einzelner Sachverhalt wird heute an **69 Stellen** dokumentiert (Beispiele in Abschnitt 3.1). Jede Änderung erzeugt dadurch eine Update-Kaskade über viele Dateien.
- Vier parallele Status-/To-do-Listen plus Done-Logs in fast jedem Dokument.
- Abgeschlossene Sprints, Audits und Pläne bleiben als aktive Dateien liegen, obwohl `docs/README.md` (Zeile 5) genau das verbietet — die Policy existiert, wird aber nicht durchgesetzt.
Kernempfehlung in einem Satz: **Nicht umstrukturieren, sondern konsolidieren**
jeder Fakt bekommt genau ein Zuhause, Erledigtes verlässt die Arbeitskopie,
und ein neues Entscheidungs-Register (`docs/DECISIONS.md`) ersetzt die heute
über fünf Dateien verteilten Entscheidungs-Logs. Realistisches Ziel: **docs/ von
35 auf ~22 aktive Dateien, Gesamtbestand von ~9.400 auf ~6.500 Zeilen**, ohne
Wissensverlust (Git-Historie bleibt vollständig).
---
## 2. Aktueller Eindruck
### 2.1 Bestandsaufnahme
| Bereich | Dateien | Charakter |
|---|---:|---|
| Root (`README.md`, `CLAUDE.md`, `HOMELAB_ARCHITECTURE_MASTER_V2.md`) | 3 | Einstieg, KI-Regeln, Architektur-Master (502 Zeilen) |
| `docs/` flach | 31 | Runbooks, Inventare, Statuslisten, Pläne, Snapshots — gemischt |
| `docs/audit/` | 2 | Audit-Snapshots (Workstation-Audit, DR-Readiness) |
| `docs/runbooks/` | 1 | neue Konvention, erst ein Dokument (`komodo-bulk-deploy-dns.md`) |
| `ops/restore-tests/` | 14 | README, schedule, 6× plan.md, 4× runbook.md, Hilfsdoku |
| `ops/windows-reinstall/docs/` | 8 | Workstation-Neuaufsetzen-Projekt vom Mai 2026, weitgehend abgeschlossen |
| `ops/borg-ui/`, `ops/policy-checks/`, übrige `ops/` | 12 | Tool-Doku, teils mit historischen Audits und generierten Reports |
| `monitoring/`, `services/` | 2 | Stack-/Skript-README |
`memory/` und `.serena/` sind gitignored (Tool-Caches) und nicht Teil des Korpus.
### 2.2 Stärken (bewusst erhalten)
- `docs/README.md` als gepflegter Index mit expliziter Aktiv-vs.-Historie-Policy.
- `docs/REPO_MAP.md` enthält bereits eine Anti-Wildwuchs-Arbeitsregel ("Neue Doku nur, wenn dauerhaft als Runbook, Inventar oder Restliste gebraucht").
- `docs/MASTER_TODO.md` hat Status-Kategorien (Aktiv/Entscheidung/Geparkt/Blockiert) mit Review-Triggern — das ist Best Practice.
- Runbooks sind hochwertig: konkrete Kommandos, Erfolgskriterien, Rollback (z. B. `docs/GITOPS_DRIFT_RUNBOOK.md`, `docs/GUEST_IOT_NETWORK.md`).
- Inventare trennen sauber Ist-Werte von Entscheidungen (`docs/HARDWARE_INVENTORY.md` "Betreiber-Entscheidungen").
- Secret-Hygiene ist durchgängig: nur Namen/Pfade, nie Werte.
- Konsistente Verweis-Kultur ("Verwandte Dokumente"-Blöcke).
Das eigentliche Asset — die Doku-Disziplin — soll erhalten bleiben. Die Optimierung
zielt darauf, dass dieselbe Disziplin **weniger Schreibarbeit pro Ereignis** kostet.
---
## 3. Wichtigste Probleme
### 3.1 P1 — Mehrfachpflege: ein Fakt, viele Heimaten (Hauptproblem)
Gemessene Beispiele aus dem aktuellen Bestand:
| Sachverhalt | Anzahl Stellen | Fundorte |
|---|---:|---|
| Tailscale-Docker-Stack-Abbau (2026-06-06) | **9** | `CLAUDE.md` (Ausnahmen), `HOMELAB_ARCHITECTURE_MASTER_V2.md` (§7.1 + §10), `docs/SERVICE_CATALOG.md`, `docs/RESTORE_MATRIX.md`, `docs/DISASTER_RECOVERY.md` (Phase-4-Hinweis), `docs/NETWORK_INVENTORY.md`, `docs/MASTER_TODO.md` (Done-Log), `docs/AI_CONTEXT.md` |
| Veeam-Erstbackup `baerchen` (53,8 GB / 0:11:31) | **8** | `docs/AI_CONTEXT.md`, `docs/MASTER_TODO.md` (2×), `docs/WEEKEND_STATUS_2026-06-05.md` (2×), `docs/WEEKEND_EXECUTION_PLAN_2026-06-05.md`, `docs/RESTORE_MATRIX.md`, `docs/DISASTER_RECOVERY.md` §10, `ops/windows-reinstall/docs/windows-image-backup-baseline.md` |
| Leseliste / GitOps-Hierarchie | **7** | `README.md`, `CLAUDE.md`, `docs/AI_CONTEXT.md`, `docs/WORKFLOW.md`, `HOMELAB_ARCHITECTURE_MASTER_V2.md` (§11.4 + §12), `docs/README.md`, `docs/REPO_MAP.md` |
| DR-Workstation-Smoke (2026-06-06) | **6** | `docs/EXTERNAL_DEPENDENCIES.md` (Review-Log), `docs/AUDIT_2026-05-25_TODO.md`, `docs/MASTER_TODO.md`, `docs/AI_CONTEXT.md`, `docs/audit/dr-workstation-readiness-2026-06-06.md`, `docs/DR_WORKSTATION_SETUP.md` (Einschub Schritt 6) |
| Liste der dokumentierten Ausnahmen | **5** | `CLAUDE.md`, `docs/AI_CONTEXT.md`, `HOMELAB_ARCHITECTURE_MASTER_V2.md` §10 (autoritativ), `docs/SERVICE_CATALOG.md` (Spalten), `ops/policy-checks/` (kodiert) |
| Restore-Test-Status je Dienst | **45** | `docs/RESTORE_MATRIX.md` (Reifegrad-Tabelle), `docs/RESTORE_HANDBOOK.md` §3, `ops/restore-tests/README.md` (Status), Done-Logs in `MASTER_TODO`/`AUDIT_2026-05-25_TODO` |
| Komodo-Kaltstart | **34** | `docs/DISASTER_RECOVERY.md` Phase 4 Stufe 3, `docs/SERVICES_RECOVERY.md` Stufen AF, `ops/restore-tests/komodo-bootstrap-runbook.md` (+ `-plan.md`) |
Ursache ist eine "Beleg-Kultur": jedes erledigte Ereignis wird als Nachweis in
alle thematisch berührten Dokumente kopiert, statt einmal dokumentiert und
verlinkt. Die Folge ist genau die Update-Kaskade, die `docs/WORKFLOW.md`
("Dokumentationspflicht": 7 Dateien prüfen pro Änderung) institutionalisiert.
### 3.2 P2 — Vier parallele Statuslisten plus verteilte Done-Logs
- `docs/MASTER_TODO.md` erklärt sich selbst zur führenden Liste — richtig.
- `docs/AUDIT_2026-05-25_TODO.md` bestätigt selbst, nur noch deckungsgleiche Restliste zu sein (1 offener Punkt); existiert faktisch nur als historische Hülle.
- `docs/WEEKEND_EXECUTION_PLAN_2026-06-05.md` + `docs/WEEKEND_STATUS_2026-06-05.md`: Sprint ist seit 2026-06-07 vorbei, alle Punkte erledigt; `WEEKEND_STATUS` nennt sich selbst "kurzlebig".
- `docs/AI_CONTEXT.md` führt einen eigenen Status-Block ("Aktuelle Restpunkte", "Letzte Bestaetigung", Zeilen 4484), der `MASTER_TODO` dupliziert und bei jedem Ereignis mitgepflegt werden muss.
- Dazu eigene To-do-/Backlog-Abschnitte in `docs/DISASTER_RECOVERY.md` (§11), `docs/RESTORE_HANDBOOK.md` (§11), `docs/SERVICES_RECOVERY.md` ("Naechste Aufgaben" — alle erledigt), `docs/SERVICE_CATALOG.md` ("Bekannte offene Fragen").
- Done-Logs wachsen unbegrenzt: `MASTER_TODO` besteht zu ~60 % aus dem Erledigt-Block; `docs/EXTERNAL_DEPENDENCIES.md` trägt 11 Review-Zeilen, die dieselben Ereignisse erneut erzählen.
### 3.3 P3 — Restore-/DR-Wissen auf zu viele Schichten verteilt
Sechs `docs/`-Dateien (`DISASTER_RECOVERY`, `RESTORE_MATRIX`, `RESTORE_HANDBOOK`,
`SERVICES_RECOVERY`, `ROLLBACK`, `GITOPS_DRIFT_RUNBOOK`) plus 14 Dateien unter
`ops/restore-tests/`. Konkrete Überschneidungen:
- `docs/RESTORE_MATRIX.md` enthält ab Zeile 178 **eingebettete Runbook-Entwürfe** (Unraid-Flash, AdGuard, Tailscale, Redis) — dasselbe Genre, das unter `ops/restore-tests/*-runbook.md` bereits ein Zuhause hat. AdGuard und Redis sind dort inzwischen sogar als Skript automatisiert und validiert; die Matrix-Abschnitte sind damit doppelt.
- `docs/RESTORE_HANDBOOK.md` und `ops/restore-tests/README.md` beantworten zu ~80 % dieselben Fragen (Grundmuster, Verzeichnisse, Status je Dienst, Schnellstart) — zwei Pflegeorte für einen Prozess.
- Die `*-plan.md`-Dateien (6 Stück) waren Vor-Erstlauf-Planung; nach erfolgreichem Erstlauf sind Runbook + Skript die Wahrheit, die Pläne sind Historie (z. B. `gitea-plan.md` "Noch offen vor dem ersten echten Lauf" — der Lauf war am 2026-05-07).
- Restore-Kadenz steht dreifach: `RESTORE_HANDBOOK` §5, `ops/restore-tests/schedule.md`, `ops/restore-tests/unraid-user-scripts.md`.
### 3.4 P4 — Historische Snapshots leben als aktive Doku weiter
Trotz klarer Policy in `docs/README.md` ("Erledigte Audits, Chat-Handoffs ...
bleiben in der Git-Historie, aber nicht als dauerhafte Arbeitskopie"):
- `docs/DR_DRILL_2026-06-03.md` (392 Zeilen): Findings sind laut `AUDIT_2026-05-25_TODO` vollständig in DR.md/EXTERNAL_DEPENDENCIES eingearbeitet — reines Belegmaterial.
- `docs/audit/system-audit-2026-06-05.md` (229 Zeilen): Windows-Workstation-Audit, thematisch nicht einmal Homelab-Betrieb.
- `docs/audit/dr-workstation-readiness-2026-06-06.md`: automatisch erzeugter Check-Output inkl. Rohblöcken.
- `docs/WEEKEND_*_2026-06-05.md` (2 Dateien): abgeschlossener Sprint.
- `docs/KalliLab_CORE_Audit_2026-06-06.pdf` (untracked): Binär-Report im `docs/`-Ordner.
- `ops/borg-ui/BACKUP_AUDIT_STATUS_QUO.md` (Stand 2026-04-15): Vor-Migrations-Ist-Aufnahme, von `BACKUP_SCOPE.md` abgelöst.
- `ops/policy-checks/last-report.md`: **generierter** Report, eingecheckt — bei jedem Lauf entsteht Diff-Rauschen.
- `ops/windows-reinstall/docs/` (8 Dateien, ~1.400 Zeilen): Projekt Mai 2026 ist abgeschlossen; aktiv gebraucht wird davon im Betrieb nur `windows-image-backup-baseline.md` (Veeam-Restore-Runbook, von `RESTORE_MATRIX` referenziert) und ggf. `laufwerks-neustruktur-2026-06-04.md` als Soll-Referenz.
Es fehlt eine gelebte Archiv-Konvention — entweder konsequentes Löschen (Policy
existiert) oder ein sichtbares `docs/archive/`.
### 3.5 P5 — Architektur-Master vermischt Zielbild und Entscheidungs-Log
`HOMELAB_ARCHITECTURE_MASTER_V2.md` (502 Zeilen) ist Pflichtlektüre Nr. 1, trägt
aber in §13 ein unbegrenzt wachsendes Betriebs-/Entscheidungs-Log (FCP-Incident,
Plex-Reclaim-Erzählung, Digest-Pinning-Historie ...). Entscheidungen liegen
zusätzlich in `MASTER_TODO` (Geparkt-Tabelle mit Triggern),
`HARDWARE_INVENTORY` (Betreiber-Entscheidungen), `AUDIT_2026-05-25_TODO`
("Bewusst geparkt") und den Review-Logs der Inventare. Ein zentrales,
chronologisches Entscheidungs-Register (ADR-light) fehlt —
`docs/runbooks/komodo-bulk-deploy-dns.md` nennt sich bereits selbst
"Runbook / ADR-light" und zeigt den Bedarf.
### 3.6 P6 — Einstiegs-Redundanz
`README.md`, `CLAUDE.md`, `docs/AI_CONTEXT.md`, `docs/README.md`,
`docs/REPO_MAP.md`, `docs/WORKFLOW.md` (KI-Arbeitsregel) und
`HOMELAB_ARCHITECTURE_MASTER_V2.md` (§11/§12) wiederholen alle dieselben
Grundregeln (Quelle der Wahrheit, Leselisten, Ausnahmen) in leicht
unterschiedlichen Fassungen. Bei Regeländerungen müssen bis zu 7 Dateien
angefasst werden; die Leselisten weichen bereits leicht voneinander ab.
### 3.7 P7 — Flacher Namensraum mit gemischten Typen und Zielgruppen
In `docs/` liegen 31 Dateien flach nebeneinander: Familien-Doku
(`FAMILY_ONBOARDING.md`) neben Bare-Metal-DR, Statuslisten neben Inventaren,
Snapshots neben Dauer-Runbooks. Die begonnene Untergliederung
(`docs/runbooks/` mit 1 Datei, `docs/audit/` mit 2) ist inkonsistent: ~10
Runbook-artige Dokumente liegen weiter flach. Namensstile mischen sich
(`SCREAMING_SNAKE.md` vs. `homelab-optimierung.md` vs. `komodo-bulk-deploy-dns.md`).
### 3.8 P8 — Punktuelle Doppel-Dokumente
- `docs/H_DRIVE_NEARLINE_PULL.md` (Pull-Workflow + Befund-Historie) vs. neues, untracked `ops/h-drive-nearline/README.md` (Struktur + Betrieb + Aufräum-Historie) vs. H:/-Abschnitt in `docs/CAPACITY_AND_LIFECYCLE.md` — drei Orte für ein Thema.
- `ops/restore-tests/README.md` pflegt eine manuelle Datei-Auflistung des eigenen Verzeichnisses ("Geplante Struktur", ~35 Zeilen) — das Verzeichnis listet sich selbst.
- `ops/hermes-agent/README.md` (367 Zeilen) ist überwiegend "Phase 1 Documentation Analysis" für einen Dienst, der bis mindestens 2026-07-25 deaktiviert geparkt ist.
---
## 4. Best-Practice-Abgleich (Kurzfassung)
| Prinzip | Heute | Lücke |
|---|---|---|
| Single Source of Truth pro Fakt | Git als SSoT für Konfig ✅; für Doku-Fakten ❌ (69 Kopien) | Regel "ein Fakt, ein Zuhause" fehlt |
| Trennung Architektur / Runbook / Entscheidung / Status | teilweise; Mischformen wie `RESTORE_MATRIX` (Referenz + Runbooks + Status) und Master §13 | Dokumenttypen nicht explizit definiert |
| README als Einstieg | ✅ vorhanden und gut | nur Redundanz mit 6 weiteren Einstiegen |
| ADRs für Entscheidungen | verteilt auf 5 Orte | zentrales Register fehlt |
| Runbooks für Wiederholbares | ✅ stark | doppelt gepflegt (Matrix-Einbettungen, Handbook vs. README) |
| Kurze Dokumente statt Sammeldateien | gemischt; Master 502 Z., DR 400 Z., Matrix 261 Z. | Status-/Historien-Anteile aufblähen Kerndokumente |
| Archivierung Veralteter Inhalte | Policy existiert (`docs/README.md`) | wird nicht durchgesetzt; kein `archive/` |
| Namenskonventionen | de facto SCREAMING_SNAKE | nicht dokumentiert, neue Dateien weichen ab |
| Ownership / Aktualisierungsrhythmus | Ein-Operator-Modell, Review-Trigger teils vorhanden | kein definierter Doku-Review-Rhythmus |
---
## 5. Konkrete Verschlankungsvorschläge
Bewertungslegende: Mehrwert (niedrig/mittel/hoch/sehr hoch) · Aufwand
(klein/mittel/groß) · Risiko (niedrig/mittel/hoch) · Ü = Wirkung Übersichtlichkeit,
W = Wirkung Wartbarkeit (/+/++/+++).
### 5.1 Statuslisten auf genau eine reduzieren
| Maßnahme | Mehrwert | Aufwand | Risiko | Ü | W |
|---|---|---|---|---|---|
| `WEEKEND_EXECUTION_PLAN_2026-06-05.md` + `WEEKEND_STATUS_2026-06-05.md` löschen/archivieren (Inhalt vollständig in `MASTER_TODO` Done-Log) | hoch | klein | niedrig | ++ | + |
| `AUDIT_2026-05-25_TODO.md` auflösen: den 1 offenen Punkt + "Bewusst geparkt" in `MASTER_TODO` übernehmen, Datei löschen | hoch | klein | niedrig | ++ | ++ |
| `AI_CONTEXT.md` Status-Block (Z. 4484) streichen; nur Pointer "Authoritativ: `docs/MASTER_TODO.md`" behalten → Datei schrumpft auf ~35 Zeilen reine Regeln/Pointer | hoch | klein | niedrig | + | +++ |
| `MASTER_TODO` Done-Log auf die letzten ~5 Einträge begrenzen; ältere Einträge ersatzlos streichen (Git-Historie + Host-Reports sind der Beleg) | hoch | klein | niedrig | ++ | +++ |
| To-do-Restabschnitte in Detail-Dokumenten entfernen: `SERVICES_RECOVERY` "Naechste Aufgaben" (alles erledigt), `RESTORE_HANDBOOK` §11 → als Einzeiler nach `MASTER_TODO` | mittel | klein | niedrig | + | ++ |
### 5.2 Restore-/DR-Cluster konsolidieren
| Maßnahme | Mehrwert | Aufwand | Risiko | Ü | W |
|---|---|---|---|---|---|
| `RESTORE_MATRIX.md` auf Referenz reduzieren: eingebettete Runbook-Entwürfe (Z. 178343) nach `ops/restore-tests/` verschieben bzw. löschen, wo Skript + Runbook schon existieren (AdGuard, Redis); Matrix behält nur Tier-Tabellen + Reifegrad | hoch | mittel | niedrig | ++ | ++ |
| `RESTORE_HANDBOOK.md` und `ops/restore-tests/README.md` zu **einem** Betriebsdokument zusammenführen (Empfehlung: `ops/restore-tests/README.md` als Zuhause, da Skripte dort liegen; `docs/README.md`-Index verlinkt) | hoch | mittel | niedrig | ++ | ++ |
| Die 6 `*-plan.md` unter `ops/restore-tests/` archivieren/löschen — Runbook + Skript sind seit den Erstläufen die Wahrheit | mittel | klein | niedrig | + | + |
| Restore-Status nur noch in der Reifegrad-Tabelle der `RESTORE_MATRIX` führen; `ops/restore-tests/README.md` "Status"-Abschnitt durch Link ersetzen | mittel | klein | niedrig | + | ++ |
| Komodo-Kaltstart: `SERVICES_RECOVERY.md` bleibt kanonisch (Stufen AF); `DISASTER_RECOVERY.md` Phase 4 Stufe 3 auf Verweis + 3 Kern-Stolperfallen kürzen | mittel | klein | niedrig | + | ++ |
| `ROLLBACK.md`: abgeschlossene Service-Rollbacks (Uptime-Kuma, Grafana/InfluxDB-Altstack, BentoPDF/Stirling) streichen — Rollback-Pfade für entfernte Dienste gehören in die Git-Historie | mittel | klein | niedrig | + | + |
### 5.3 Entscheidungs-Register einführen (wichtigste strukturelle Maßnahme)
| Maßnahme | Mehrwert | Aufwand | Risiko | Ü | W |
|---|---|---|---|---|---|
| Neues `docs/DECISIONS.md` (ADR-light, eine Datei, neueste oben): Datum, Entscheidung, Kontext, Alternativen, Review-Trigger — je Eintrag 515 Zeilen | sehr hoch | mittel | niedrig | ++ | +++ |
| `HOMELAB_ARCHITECTURE_MASTER_V2.md` §13 dorthin migrieren; §9 (historische Migration) auf 3 Zeilen kürzen → Master schrumpft von 502 auf ~300 Zeilen reines Zielbild | sehr hoch | mittel | mittel* | +++ | +++ |
| Künftige Entscheidungen **nur noch** dort; `MASTER_TODO` "Geparkt" verlinkt auf DECISIONS-Einträge statt sie zu wiederholen | hoch | klein | niedrig | ++ | +++ |
*Risiko "mittel" nur, weil der Master Pflichtlektüre für alle Agenten ist —
Migration als ein sauberer Commit mit Verweis im Master ("Entscheidungs-Log:
siehe `docs/DECISIONS.md`") entschärft das vollständig.
### 5.4 Historisches archivieren
| Maßnahme | Mehrwert | Aufwand | Risiko | Ü | W |
|---|---|---|---|---|---|
| `docs/archive/` anlegen (oder konsequent löschen — Operator-Frage 1); dorthin: `DR_DRILL_2026-06-03.md`, `docs/audit/*` (beide), `HOME_ASSISTANT_INFLUXDB_ECOWITT.md` (selbst als archiviert markiert), Weekend-Dateien | hoch | klein | niedrig | +++ | ++ |
| `ops/windows-reinstall/docs/`: nur `windows-image-backup-baseline.md` (aktives Veeam-DR-Runbook) und `laufwerks-neustruktur-2026-06-04.md` (Soll-Referenz) bleiben aktiv; die übrigen 6 Dateien archivieren | mittel | klein | niedrig | ++ | + |
| `ops/borg-ui/BACKUP_AUDIT_STATUS_QUO.md` archivieren (`BACKUP_SCOPE.md` ist das aktive Zielbild) | mittel | klein | niedrig | + | + |
| `ops/policy-checks/last-report.md` aus Git entfernen und in `.gitignore` aufnehmen (generiertes Artefakt) | mittel | klein | niedrig | + | ++ |
| `docs/KalliLab_CORE_Audit_2026-06-06.pdf` nicht committen; Ablage auf Share/H: statt im GitOps-Repo | mittel | klein | niedrig | + | + |
### 5.5 Punktuelle Zusammenführungen
| Maßnahme | Mehrwert | Aufwand | Risiko | Ü | W |
|---|---|---|---|---|---|
| H:/-Thema: `ops/h-drive-nearline/README.md` (neu, derzeit untracked) committen und zur einzigen H:/-Doku machen; `docs/H_DRIVE_NEARLINE_PULL.md` auf Kurzverweis reduzieren oder auflösen; Befund-Historie 2026-05/06 → `DECISIONS.md` oder Git | mittel | klein | niedrig | + | ++ |
| `ops/restore-tests/README.md`: manuelle Datei-Auflistung ("Geplante Struktur") auf die 5 Einstiegs-Skripte kürzen | niedrigmittel | klein | niedrig | + | + |
| `ops/hermes-agent/README.md` beim Hermes-Review (Deadline 2026-07-25) von 367 auf ~60 Zeilen Betriebs-README kürzen oder mit dem Stack entfernen | niedrig | klein | niedrig | + | + |
| Leselisten vereinheitlichen: `README.md` und `CLAUDE.md` behalten je **eine** Leseliste; `WORKFLOW`/`Master §12`/`AI_CONTEXT` verweisen nur noch darauf | mittel | klein | niedrig | + | ++ |
---
## 6. Vorgeschlagene Zielstruktur
Bewusst **keine** Big-Bang-Umordnung: Massen-Verschiebungen brechen die
Querverweise in ~30 Dokumenten, die Pflicht-Leselisten in `CLAUDE.md` und die
Pfade im Host-Spiegel. Die Struktur bleibt erkennbar, wird aber dünner und
bekommt drei neue Sammelpunkte:
```text
/ (unverändert)
├── README.md Einstieg, eine Leseliste
├── CLAUDE.md KI-Arbeitsregeln (verweist statt wiederholt)
├── HOMELAB_ARCHITECTURE_MASTER_V2.md nur noch Zielbild (~300 Z.)
├── docs/
│ ├── README.md Index (Pflicht, wie heute)
│ ├── MASTER_TODO.md EINZIGE Statusliste
│ ├── DECISIONS.md NEU: Entscheidungs-Register (ADR-light)
│ ├── AI_CONTEXT.md verschlankt: Regeln + Pointer, kein Status
│ ├── WORKFLOW.md / REPO_MAP.md unverändert
│ ├── SERVICE_CATALOG.md Referenz (unverändert)
│ ├── Inventare (6): HARDWARE_, NETWORK_, STORAGE_LAYOUT,
│ │ EXTERNAL_DEPENDENCIES, CAPACITY_, SECRETS_MAP
│ ├── Runbooks (flach, Bestand): DISASTER_RECOVERY, RESTORE_MATRIX (schlank),
│ │ SERVICES_RECOVERY, ROLLBACK, GITOPS_DRIFT_RUNBOOK,
│ │ GUEST_IOT_NETWORK, EXTERNAL_OPERATOR_RUNBOOK,
│ │ DR_WORKSTATION_SETUP, AUTHELIA_OIDC_PLAN,
│ │ FAMILY_ONBOARDING, RENOVATE, ALERT_RULES
│ ├── runbooks/ NEUE themenspezifische Runbooks (kebab-case),
│ │ Bestand bleibt wo er ist
│ └── archive/ NEU: abgeschlossene Snapshots/Drills/Audits
└── ops/<tool>/ Tool-Doku bleibt beim Tool (README + Runbook)
```
Netto-Effekt: `docs/` aktiv 35 → ~22 Dateien; Gesamtbestand ~74 → ~50 aktive
Dateien; geschätzt ~2.900 Zeilen weniger Pflegefläche.
---
## 7. Empfohlene Dokumenttypen
Jede Datei bekommt genau einen Typ (im Kopf deklariert):
| Typ | Zweck | Beispiele (Bestand) | Lebenszyklus |
|---|---|---|---|
| **Einstieg/Index** | Navigation, Regeln | `README.md`, `docs/README.md`, `CLAUDE.md` | dauerhaft, klein halten |
| **Architektur/Zielbild** | Soll-Zustand, Prinzipien, Ausnahmen | `HOMELAB_ARCHITECTURE_MASTER_V2.md` | dauerhaft; Änderungen via DECISIONS begründet |
| **Inventar/Referenz** | Ist-Werte, Kataloge, Matrizen | `SERVICE_CATALOG`, `NETWORK_INVENTORY`, `RESTORE_MATRIX` | dauerhaft; nur Ist-Stand, keine Verlaufserzählung |
| **Runbook** | wiederholbare Abläufe mit Erfolgskriterium + Rollback | `GITOPS_DRIFT_RUNBOOK`, `DR_WORKSTATION_SETUP`, `ops/restore-tests/*-runbook.md` | dauerhaft; bei Ablösung archivieren |
| **Entscheidung (ADR-light)** | Was, warum, Alternativen, Review-Trigger | NEU: `docs/DECISIONS.md` | append-only, neueste oben |
| **Status/To-do** | offene Arbeit | `MASTER_TODO.md` (einzige Instanz) | lebend; Done-Einträge max. ~5 |
| **Snapshot/Beleg** | Audits, Drills, Sprint-Boards, Messungen | `DR_DRILL_*`, `audit/*`, `WEEKEND_*`, `mem-limits-baseline` | **befristet**: nach Einarbeitung → `archive/` oder löschen |
---
## 8. Merge-/Archivierungs-Kandidaten (Gesamtliste, priorisiert)
| # | Kandidat | Aktion | Prio |
|---|---|---|---|
| 1 | `docs/WEEKEND_EXECUTION_PLAN_2026-06-05.md`, `docs/WEEKEND_STATUS_2026-06-05.md` | löschen/archivieren | sofort |
| 2 | `docs/AUDIT_2026-05-25_TODO.md` | Rest in `MASTER_TODO` mergen, löschen | sofort |
| 3 | `docs/AI_CONTEXT.md` Z. 4484 | streichen (Pointer auf MASTER_TODO) | sofort |
| 4 | `ops/policy-checks/last-report.md` | entgitten + `.gitignore` | sofort |
| 5 | `docs/KalliLab_CORE_Audit_2026-06-06.pdf` (untracked) | nicht committen, extern ablegen | sofort |
| 6 | `docs/DR_DRILL_2026-06-03.md`, `docs/audit/*` (2), `docs/HOME_ASSISTANT_INFLUXDB_ECOWITT.md` | → `docs/archive/` | Woche 1 |
| 7 | `ops/h-drive-nearline/README.md` + `docs/H_DRIVE_NEARLINE_PULL.md` | committen + zu einem Dokument | Woche 1 |
| 8 | `HOMELAB_ARCHITECTURE_MASTER_V2.md` §13 (+§9 kürzen) | → neues `docs/DECISIONS.md` | Woche 2 |
| 9 | `docs/ROLLBACK.md` historische Service-Abschnitte | streichen | Woche 2 |
| 10 | `docs/RESTORE_HANDBOOK.md` + `ops/restore-tests/README.md` | zu einem Dokument | Woche 3 |
| 11 | `docs/RESTORE_MATRIX.md` eingebettete Runbooks (Z. 178343) | ausgliedern/löschen | Woche 3 |
| 12 | `ops/restore-tests/*-plan.md` (6) | archivieren/löschen | Woche 3 |
| 13 | `docs/SERVICES_RECOVERY.md` Done-Tabelle; `RESTORE_HANDBOOK` §11-Backlog | streichen / nach MASTER_TODO | Woche 3 |
| 14 | `ops/windows-reinstall/docs/` (6 von 8 Dateien) | archivieren | Woche 4 |
| 15 | `ops/borg-ui/BACKUP_AUDIT_STATUS_QUO.md` | archivieren | Woche 4 |
| 16 | `MASTER_TODO` Done-Log, `EXTERNAL_DEPENDENCIES` Review-Log | auf jüngste Einträge kürzen | Woche 4 |
| 17 | `ops/hermes-agent/README.md` | beim Hermes-Review 2026-07-25 kürzen/entfernen | später |
---
## 9. Empfohlene Namenskonventionen
1. **Bestand nicht umbenennen.** `SCREAMING_SNAKE.md` bleibt für die etablierte Kern-Doku in `docs/` — Renames erzeugen nur Link-Brüche ohne Informationsgewinn.
2. **Neue Dateien in Unterordnern in `kebab-case.md`** (so wie `docs/runbooks/komodo-bulk-deploy-dns.md` es bereits vormacht).
3. **Datum im Dateinamen nur für Snapshots** (`YYYY-MM-DD`), und Snapshots gehören nach `docs/archive/YYYY/`. Eine datierte Datei im `docs/`-Root ist künftig per Definition ein Aufräum-Kandidat.
4. **Kopfzeilen-Konvention** (3 Felder, eine Zeile, wie in diesem Dokument): `Typ: … · Stand: YYYY-MM-DD · Status: aktiv | geparkt (Trigger: …) | archiviert`. Viele Dokumente haben "Stand:" bereits — nur Typ/Status ergänzen.
5. **Archiv-Pfad:** `docs/archive/YYYY/<datum>-<thema>.md`, oben ein Einzeiler "Archiviert am …, abgelöst durch …".
---
## 10. Minimale Doku-Regeln für die Zukunft
Vorschlag als Ersatz/Ergänzung der bestehenden Arbeitsregel in `docs/REPO_MAP.md`
(und Kurzfassung in `CLAUDE.md`):
1. **Ein Fakt, ein Zuhause.** Status → `MASTER_TODO`. Entscheidung → `DECISIONS`. Zielbild → Architektur/Inventar/Katalog. Ablauf → genau ein Runbook. Beleg → Host-Report (`/mnt/user/backups/restore-reports/`) oder Git-Commit. Alle anderen Stellen **verlinken**.
2. **Erledigt = raus aus der Arbeitskopie.** Abgeschlossene Pläne, Sprints, Audits und Drill-Reports wandern nach `docs/archive/` oder werden gelöscht — Git ist das Archiv (bestehende Policy aus `docs/README.md`, jetzt durchgesetzt).
3. **Neue Datei nur, wenn sie einem der 7 Typen aus Abschnitt 7 entspricht** — sonst ist es ein Eintrag in einer bestehenden Datei.
4. **Done-Einträge maximal 3 Zeilen.** Wer mehr Beleg braucht, verlinkt Commit oder Report. Done-Logs werden bei >5 Einträgen gekürzt.
5. **Snapshot-Dateien tragen ihr Ablaufdatum** ("Status: befristet bis …") und werden danach archiviert.
6. **Index-Pflicht bleibt:** jede neue/gelöschte Datei aktualisiert `docs/README.md` im selben Commit.
7. **Quartals-Gärtnern (15 min):** datierte Dateien im `docs/`-Root archivieren, Done-Logs kürzen, tote Links prüfen — passt zum bestehenden Quartals-Rhythmus (DR-Smoke, Restore-Drills).
---
## 11. 30-Tage-Plan
**Woche 1 — Quick Wins + Archiv-Fundament** (alles klein, risikolos):
Uncommitted Arbeitskopie klären (6 modifizierte Dateien, 2 untracked — deckt
sich mit `docs/homelab-optimierung.md` Empfehlung 9) · Kandidaten #1#7 aus
Abschnitt 8 · `docs/archive/` anlegen.
**Woche 2 — Entscheidungs-Register:**
`docs/DECISIONS.md` anlegen (Vorlage: 5 Felder) · Master §13 migrieren, §9
kürzen, Verweis im Master setzen · `ROLLBACK.md` entschlacken · verstreute
"Bewusst geparkt"-Entscheidungen als DECISIONS-Einträge mit Review-Trigger
zusammenziehen.
**Woche 3 — Restore-Cluster:**
`RESTORE_HANDBOOK``ops/restore-tests/README.md` zusammenführen ·
`RESTORE_MATRIX` auf Tabellen reduzieren, Runbook-Entwürfe ausgliedern ·
`*-plan.md` archivieren · Restore-Status auf einen Ort (Reifegrad-Tabelle).
**Woche 4 — Regeln verankern + Abschluss:**
Regeln aus Abschnitt 10 in `REPO_MAP.md`/`CLAUDE.md` einarbeiten · Leselisten
vereinheitlichen · `windows-reinstall`-Doku abschließen/archivieren ·
Done-/Review-Logs kürzen · `docs/README.md`-Index final neu aufbauen ·
dieses Dokument selbst nach `docs/archive/` verschieben (Regel 2 gilt auch hier).
Jeder Schritt ist ein eigener kleiner Commit → Rollback ist immer ein
`git revert`; keine produktiven Pfade, keine Compose-Dateien betroffen.
---
## 12. Quick Wins unter 30 Minuten
| Quick Win | Wirkung |
|---|---|
| Weekend-Dateien (2) löschen | 161 Zeilen, eine Statusliste weniger |
| `AUDIT_2026-05-25_TODO.md` in `MASTER_TODO` auflösen | 57 Zeilen, Sync-Pflicht entfällt dauerhaft |
| `AI_CONTEXT` Status-Block streichen | KI-Kontext wird wartungsfrei |
| `last-report.md` entgitten + `.gitignore` | kein Diff-Rauschen pro Policy-Lauf |
| `docs/archive/` anlegen + 5 Snapshots verschieben | `docs/`-Root zeigt nur noch Aktives |
| `ops/h-drive-nearline/README.md` committen, `H_DRIVE_NEARLINE_PULL` zum Pointer machen | H:/-Thema hat ein Zuhause |
| PDF aus `docs/` entfernen (extern ablegen) | keine Binärdateien im GitOps-Repo |
| `MASTER_TODO` Done-Log auf 5 Einträge kürzen | 60 Zeilen in der führenden Liste |
---
## 13. Größere Aufräumprojekte (später, bewusst optional)
1. **Ordner-Restruktur `docs/{runbooks,inventory}/`** für den Bestand: nur angehen, wenn der flache Namensraum nach der Konsolidierung noch stört. Aufwand groß (Link-Churn in ~30 Dateien, `CLAUDE.md`-Leselisten, Host-Spiegel), Mehrwert nach der Verschlankung nur noch mittel, Risiko mittel.
2. **Doku-Linter im Policy-Check:** `ops/policy-checks/check_repo.ps1` um DOC-Checks erweitern — tote relative Links, datierte Dateien im `docs/`-Root, fehlende Typ/Stand-Kopfzeile. Passt zur bestehenden Check-Kultur; Aufwand mittel, Mehrwert hoch für die Dauerhaftigkeit der Regeln.
3. **Index-Generierung:** `docs/README.md`-Tabellen aus den Kopfzeilen generieren statt manuell pflegen. Nice-to-have für ein Ein-Personen-Lab; erst nach 2.
4. **Workstation-Doku entflechten:** prüfen, ob `baerchen`-Lifecycle-Doku (windows-reinstall, System-Audits) langfristig in ein eigenes Repo gehört; im Homelab-Repo bleibt nur das DR-relevante Veeam-Runbook. Mehrwert mittel, Aufwand mittel.
5. **Master-Diät Stufe 2:** Spalten-Überlappung zwischen Master §7-Tabellen und `SERVICE_CATALOG` reduzieren (Status/Netze doppelt). Vorsichtig angehen — beide sind Pflichtlektüre; erst nachdem DECISIONS etabliert ist.
---
## 14. Offene Fragen an den Operator
1. **Archivieren oder löschen?** `docs/archive/` macht Historie sichtbar, widerspricht aber der bestehenden "Git-Historie reicht"-Policy. Präferenz? (Empfehlung: `archive/` für Drill-/Audit-Belege mit Referenzwert, Löschen für Sprint-Boards und erledigte Pläne.)
2. **Wer konsumiert `docs/AI_CONTEXT.md`** außer Claude (Codex? Hermes? Gemini-Sessions)? Wenn nur Claude: mit `CLAUDE.md` zusammenlegen und eine Datei einsparen. Wenn mehrere: schlank behalten wie vorgeschlagen.
3. **`docs/audit/` als dauerhafte Konvention?** Sollen künftige Audit-Snapshots überhaupt ins Repo, oder reichen Host-Reports unter `/mnt/user/backups/restore-reports/` plus ein DECISIONS-/TODO-Eintrag?
4. **Folder-Restruktur (Projekt 13.1) gewünscht oder bewusst nie?** Eine klare Nein-Entscheidung wäre auch ein legitimer DECISIONS-Eintrag und beendet das Thema.
5. **Die 6 uncommitteten Doku-Änderungen** in der Arbeitskopie (u. a. `AI_CONTEXT`, `AUDIT_2026-05-25_TODO`, `WEEKEND_STATUS`, windows-reinstall-Dateien): committen oder verwerfen? Das sollte vor Umsetzung der Wochen-1-Schritte geklärt sein, damit Merges sauber bleiben.
6. **Soll `docs/WORKFLOW.md` "Dokumentationspflicht"** (7 Dateien pro Änderung prüfen) nach Einführung von Regel 1 ("ein Fakt, ein Zuhause") entsprechend verkürzt werden? Empfehlung: ja — die Prüfliste schrumpft auf "betroffenes Zuhause + Index".
@@ -45,7 +45,8 @@ Noch offen:
- Manuelle Screenshots in `H:\Windows-Neuaufsetzen-Backup\14_Screenshots` ablegen. - Manuelle Screenshots in `H:\Windows-Neuaufsetzen-Backup\14_Screenshots` ablegen.
- BitLocker-Status mit Adminrechten pruefen. **Nachlauf 2026-06-05:** Status - BitLocker-Status mit Adminrechten pruefen. **Nachlauf 2026-06-05:** Status
wurde geprueft; C:/D:/E:/G:/H: sind `FullyDecrypted`, Protection `Off`. wurde geprueft; C:/D:/E:/G:/H: sind `FullyDecrypted`, Protection `Off`.
Offen bleibt nur die bewusste BitLocker-Entscheidung. **Entscheidung 2026-06-06:** BitLocker bleibt bewusst deaktiviert; Recovery
laeuft ueber Veeam-Image, kein BitLocker-Key-Management.
- Passwortmanager, 2FA-Recovery-Codes und Browser-Sync manuell pruefen. **Erledigt 2026-06-06 laut Operator-Bestaetigung.** - Passwortmanager, 2FA-Recovery-Codes und Browser-Sync manuell pruefen. **Erledigt 2026-06-06 laut Operator-Bestaetigung.**
- Banking4-Speicherort explizit pruefen. **Erledigt 2026-06-06 laut Operator-Bestaetigung.** - Banking4-Speicherort explizit pruefen. **Erledigt 2026-06-06 laut Operator-Bestaetigung.**
- Banking4 im Programm selbst oeffnen und aktuellen Datentresor/Backup-Export bestaetigen. Der Key und der Datentresor sind bereits lokal auf H: gesichert. **Erledigt 2026-06-06 laut Operator-Bestaetigung.** - Banking4 im Programm selbst oeffnen und aktuellen Datentresor/Backup-Export bestaetigen. Der Key und der Datentresor sind bereits lokal auf H: gesichert. **Erledigt 2026-06-06 laut Operator-Bestaetigung.**
@@ -469,7 +470,7 @@ Direkt nach der Installation:
- Windows-Aktivierung prüfen - Windows-Aktivierung prüfen
- Laufwerksbuchstaben sauber vergeben - Laufwerksbuchstaben sauber vergeben
- Windows Defender und Firewall prüfen - Windows Defender und Firewall prüfen
- BitLocker bewusst aktivieren oder deaktiviert lassen - BitLocker bewusst deaktiviert lassen (Entscheidung 2026-06-06)
- Wiederherstellungspunkt erstellen - Wiederherstellungspunkt erstellen
Basisprogramme: Basisprogramme:
+25
View File
@@ -0,0 +1,25 @@
# Archiv
Typ: Index · Stand: 2026-06-11 · Status: aktiv
Abgeschlossene Snapshots, Drills, Audits und abgeloeste Plaene mit Referenzwert.
Inhalte hier werden nicht mehr gepflegt; die fuehrenden Quellen stehen in der
Spalte "Abgeloest durch". Sprint-Boards und erledigte Arbeitslisten werden nicht
archiviert, sondern geloescht (Git-Historie ist das Archiv).
## 2026
| Datei | Was es war | Abgeloest durch / Ergebnis eingearbeitet in |
|---|---|---|
| `2026/BACKUP_AUDIT_STATUS_QUO_2026-04-15.md` | Ist-Aufnahme Backup vor der Borg-Migration | `ops/borg-ui/BACKUP_SCOPE.md` |
| `2026/DR_DRILL_2026-06-03.md` | DR-Tabletop-Drill, 23 Befunde | Doku-Fixes in `docs/DISASTER_RECOVERY.md` und `docs/EXTERNAL_DEPENDENCIES.md` |
| `2026/system-audit-baerchen-2026-06-05.md` | Read-only-Audit der Windows-Workstation | Befunde abgearbeitet bzw. Operator-Entscheidungen in `docs/DECISIONS.md` |
| `2026/dr-workstation-readiness-2026-06-06.md` | Automatischer Readiness-Check DR-Workstation | `docs/EXTERNAL_DEPENDENCIES.md` Abschnitt "DR-Workstation Bare-Metal-Kit" |
| `2026/HOME_ASSISTANT_INFLUXDB_ECOWITT.md` | Zielbild-Entwurf HA -> InfluxDB 3; HA existiert seit Crash nicht mehr | Neuaufbau braucht neue Inventur; Entwurf nur Referenz |
| `2026/windows-neuaufsetzen-masterplan.md` | Masterplan Windows-Neuaufsetzen Mai 2026 (abgeschlossen) | Aktiv bleibt nur `ops/windows-reinstall/` (Skripte, Veeam-Baseline, Laufwerksstruktur) |
| `2026/postdelta-2026-06-04.md` | PostDelta-Datenstand nach Neuinstallation | Projekt abgeschlossen |
| `2026/programme-entscheidung-2026-06-04.md` | Programm-Reinstall-Entscheidungen | Projekt abgeschlossen |
| `2026/boot-cleanup-plan-2026-06-04.md` | BCD-/Boot-Bereinigungsplan | Umgesetzt; Endzustand im System-Audit belegt |
| `2026/postinstall-erstes-ziel-codex.md` | Postinstall-Arbeitsauftrag | Projekt abgeschlossen |
| `2026/baerchen-app-license-readiness-2026-06-06.md` | App-/Lizenz-Readiness-Check | Projekt abgeschlossen |
| `2026/homelab-doku-optimierung-2026-06-11.md` | Analyse + Vorschlag zur Doku-Konsolidierung | umgesetzt 2026-06-11; Regeln in `docs/REPO_MAP.md`, Entscheidung in `docs/DECISIONS.md` |
+82
View File
@@ -0,0 +1,82 @@
# H:/ Nearline-Backup — Struktur und Betrieb
Stand: 2026-06-10
## Rolle der H:/
Die externe HDD (asmedia ASM235, 7.4 TB, Laufwerk `H:`) dient ausschließlich als
**Nearline-Backup-Spiegel** für kritische Dumps und Git-Bundles.
Sie ist kein Primär-Backup (das ist Hetzner/Borg) und kein dauerhaftes Archiv.
## Sollzustand
```
H:\
└── kallilab-nearline-backups\
├── borg-dumps\latest\ ← aktuelle DB-Dumps (per Script)
├── git-bundles\gitea\ ← Gitea-Repo-Bundles (per Script)
├── _dr-kit\ ← SSH-Keys, Offline-Secrets (manuell)
├── _logs\ ← Robocopy-Logs je Lauf
└── _reports\ ← Markdown-Reports je Lauf
```
Nichts weiteres gehört dauerhaft auf die H:/.
Temporäre Recovery- oder Backup-Ordner aus Notfallsituationen sind nach
Abschluss zu löschen.
## Automatischer Pull
`pull-critical-backups.ps1` zieht per Robocopy vom Unraid-SMB-Share:
- `\\192.168.178.58\backups\borg\dumps\latest``borg-dumps\latest\`
- `\\192.168.178.58\backups\git-bundles\gitea``git-bundles\gitea\`
Der Windows Scheduled Task `KalliLab H Drive Nearline Pull` laeuft seit
2026-05-28 taeglich 05:30. Das Script kopiert bewusst **nicht** mit `/MIR` und
loescht nichts auf H:/; alte Artefakte werden nur nach manueller Sichtpruefung
entfernt. Aufruf zum Testen:
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File G:\Gitea_Clone\homelab-infra\ops\h-drive-nearline\pull-critical-backups.ps1 -WhatIf
```
Das Script schließt bewusst aus:
- `unraid-flash-config.tar.gz` (0600 root:root, nicht per SMB zugänglich → Restore aus Hetzner-Borg)
- Migration-/Cutover-Verzeichnisse (`immich-vectorchord-*`, `pg18-major-*`, `redis8-*` etc.)
## _dr-kit
Enthält offline hinterlegte Schlüssel und Secrets für den DR-Fall:
- `dr-hetzner` / `dr-hetzner.pub` — SSH-Key für Hetzner Storage Box
- `dr-readonly` / `dr-readonly.pub` — Read-only Deploy-Key
- `KOmodo Secrets.txt` — Komodo Stack ENV-Offline-Dokumentation
Diese Dateien sind **manuell** zu pflegen und **nicht** vom Pull-Script verwaltet.
## Archiv-Ordner
Temporäre Notfall-Artefakte verbleiben als `_archiv-*`-Ordner bis zur bewussten
Löschentscheidung:
| Ordner | Inhalt | Anlassdatum |
|---|---|---|
| `kallilab-recovery\_archiv-nvme-crash-image-2026-05-14\` | nvme0n1 Disk-Image (1863 GB) + Crash-Runbooks aus dem Mai-2026-Ausfall | 2026-05-14 |
## Aufräum-Historie
| Datum | Aktion |
|---|---|
| 2026-06-10 | `OneDrive - Stroetmann Group\` gelöscht (leer) |
| 2026-06-10 | SSH-Keys + Secrets aus nearline-Root in `_dr-kit\` verschoben |
| 2026-06-10 | Migration-Artefakt-Verzeichnisse in `borg-dumps\latest\` gelöscht (immich-vectorchord-*, pg18-major-*, redis8-*, nextcloud-redis-pre-redis8-*, shared-redis-pre-redis8-*) |
| 2026-06-10 | Pre-major-prod-Dumps gelöscht (PG17→PG18-Migration abgeschlossen) |
| 2026-06-10 | `kallilab-recovery\2026-05-15\` gelöscht (DNS-Restore-Reste) |
| 2026-06-10 | `kallilab-recovery\2026-05-14\``_archiv-nvme-crash-image-2026-05-14\` umbenannt |
| 2026-06-10 | `kallilab-recovery\disk1-phase2-2026-05-23\` gelöscht (1677 GB Media-Share-Kopie; Unraid-Share verifiziert vollständig) |
## Offene Punkte
- `Windows-Neuaufsetzen-Backup\` (48 GB): nach vollständiger Rückspielung auf D:\ löschen
- `_archiv-nvme-crash-image-2026-05-14\` (1863 GB): löschen sobald sicher, dass nichts mehr aus dem alten System benötigt wird
- Log-Rotation für `_logs\` und `_reports\`: manuell oder per Script, Empfehlung 30 Tage
-29
View File
@@ -1,29 +0,0 @@
# Policy Check Report
## Summary
- Compose files checked: 29
- Critical findings: 0
- Warnings: 1
- Info findings: 13
## Critical
- none
## Warnings
- [USER001] monitoring\docker-compose.yml :: influxdb3-core: Runs as user 0. Documented exception, keep visible for hardening.
## Info
- [PORT001] core\gitea\docker-compose.yml :: gitea: Allowed host port mapping: 222:22
- [PORT001] host-services\Adguard\docker-compose.yml :: adguard: Allowed host port mapping: 53:53/tcp
- [PORT001] host-services\Adguard\docker-compose.yml :: adguard: Allowed host port mapping: 53:53/udp
- [PORT001] host-services\Adguard\docker-compose.yml :: adguard: Allowed host port mapping: 100.80.98.33:8082:80
- [HOSTNET001] host-services\plex\docker-compose.yml :: plex: network_mode: host is a documented exception.
- [HOSTNET001] host-services\tailscale\docker-compose.yml :: tailscale: network_mode: host is a documented exception.
- [IMAGE002] infra\ddns-updater\docker-compose.yml :: ddns-updater: Image uses a latest tag but is digest-pinned and documented as an exception.
- [PORT001] monitoring\docker-compose.yml :: influxdb3-core: Allowed host port mapping: ${INFLUXDB_BIND_IP:-127.0.0.1}:8181:8181
- [IMAGE002] ops\glances\docker-compose.yml :: glances: Image uses a latest tag but is digest-pinned and documented as an exception.
- [IMAGE002] ops\scrutiny\docker-compose.yml :: scrutiny: Image uses a latest tag but is digest-pinned and documented as an exception.
- [PRIV001] ops\scrutiny\docker-compose.yml :: scrutiny: Privileged mode is a documented exception.
- [PORT001] traefik\docker-compose.yml :: traefik: Allowed host port mapping: 80:80
- [PORT001] traefik\docker-compose.yml :: traefik: Allowed host port mapping: 443:443
+63 -87
View File
@@ -1,109 +1,85 @@
# Restore Tests # Restore-Tests - Betrieb und Werkzeuge
Kontrollierte Restore-Tests fuer `homelab-infra`. Typ: Runbook/Tool-Doku · Stand: 2026-06-11 · Status: aktiv
Ziel: Kontrollierte Restore-Tests fuer `homelab-infra`. Dieses Dokument ist das
**einzige** Betriebsdokument fuer Restore-Tests (das fruehere
`docs/RESTORE_HANDBOOK.md` ist hierin aufgegangen). Verwandt:
- Backups durch echte Test-Restores verifizieren - `docs/RESTORE_MATRIX.md` - Restore-Quellen, Secrets, Smoke-Tests und **Test-Reifegrad je Dienst** (einziger Status-Ort)
- produktive Pfade nicht beschreiben - `docs/DISASTER_RECOVERY.md` - echter Wiederanlauf
- Testlaeufe spaeter weitgehend automatisieren - `schedule.md` - Kadenz, Cron-Ausdruecke und Shell-Guards
- `unraid-user-scripts.md` - Unraid-User-Script-Vorlagen fuer die Host-Jobs
## Grundregeln ## Grundregeln
- Restore-Quelle bleibt im Backup-Bereich, z. B. `/mnt/user/backups/borg` - Restore-Quelle bleibt das produktive Borg-Repo bei Hetzner; Zugriff ueber den vorhandenen `borg-ui`-Container
- Test-Restores laufen nur in `/mnt/user/backups/restore-lab` - Passphrase kommt aus `/mnt/user/appdata/secrets/borg_repo_passphrase.txt`, nie aus UI-Interna
- Reports landen in `/mnt/user/backups/restore-reports` - Testdaten landen nur unter `/mnt/user/backups/restore-lab/<dienst>`; bei Fehlschlag wird nach `_failed/` verschoben statt geloescht
- Test-Container nutzen das Praefix `restoretest-` - Reports landen unter `/mnt/user/backups/restore-reports`
- keine produktiven Volumes schreibend mounten - Testcontainer nutzen das Praefix `restoretest-`, localhost-Ports, keine produktive Domain, keine Traefik-Route
- keine produktiven Domains fuer Testinstanzen uebernehmen - keine produktiven Volumes schreibend mounten, keine produktiven Pfade beschreiben
- keine Restore-Automatik fuer neue Dienste ohne bewusste Freigabe
## Geplante Struktur ## Erfolgskriterien
- `schedule.md`: Intervalle und Verantwortlichkeiten Ein Restore-Test gilt nur dann als erfolgreich, wenn Quelle lesbar war, Daten
- `common.sh`: gemeinsame Helfer fuer Borg-Lookup, Borg-Extract und Compose-Cleanup; prueft vor Borg-Operationen auch `borg-ui:/data/borg.db` und `borg-ui:/local/secrets/borg_repo_passphrase.txt` im Restore-Lab ankamen, der Testcontainer startete, der **fachliche**
- `vaultwarden-restore-test.ps1`: erster Mini-Restore-Ablauf Smoke-Test gelang und ein Report geschrieben wurde. "Container laeuft" allein
- `vaultwarden-restore-test.sh`: hosttauglicher Vaultwarden-Restore-Job reicht nicht.
- `vaultwarden-plan.md`: konkreter Vaultwarden-Testplan
- `vaultwarden-compose.test.yml`: isolierte Testinstanz fuer Vaultwarden
- `gitea-restore-test.ps1`: Gitea-Mini-Restore-Ablauf
- `gitea-restore-test.sh`: hosttauglicher Gitea-Restore-Job
- `gitea-plan.md`: konkreter Gitea-Testplan
- `gitea-compose.test.yml`: isolierte Testinstanz fuer Gitea
- `paperless-restore-test.ps1`: Paperless-Mini-Restore-Ablauf
- `paperless-restore-test.sh`: hosttauglicher Paperless-Restore-Job
- `paperless-plan.md`: konkreter Paperless-Testplan
- `paperless-compose.test.yml`: isolierte Testinstanz fuer Paperless inkl. Test-Postgres und Test-Redis
- `immich-restore-test.ps1`: Immich-Mini-Restore-Ablauf als Plan-/Windows-Scaffold
- `immich-restore-test.sh`: hosttauglicher Immich-Restore-Job, erster echter Lauf noch offen
- `immich-plan.md`: konkreter Immich-Testplan
- `immich-runbook.md`: Operator-Runbook fuer den ersten Immich-Lauf
- `immich-compose.test.yml`: isolierte Testinstanz fuer Immich inkl. VectorChord/pgvector-Test-Postgres und Test-Redis
- `authelia-restore-test.sh`: Authelia-Restore-Job (Config-Smoke; Erstlauf 2026-06-03 erfolgreich)
- `authelia-compose.test.yml`: isolierte Testinstanz fuer Authelia inkl. Test-Postgres, Filesystem-Notifier (kein echter SMTP-Versand)
- `authelia-plan.md`: konkreter Authelia-Testplan
- `authelia-runbook.md`: Operator-Runbook fuer den ersten Authelia-Lauf
- `adguard-restore-test.sh`: AdGuard-Home-Restore-Job (Config + isolierter Container + HTTP/DNS-Smoke; Erstlauf 2026-06-06 erfolgreich)
- `adguard-compose.test.yml`: isolierte AdGuard-Testinstanz auf localhost-Ports `13001` und `15353`
- `redis-restore-test.sh`: Redis-8-Restore-Job (Pre-Cutover-Artefakt + isolierter Container + PING/INFO/DBSIZE; Erstlauf 2026-06-06 erfolgreich)
- `redis-compose.test.yml`: isolierte Redis-8-Testinstanz auf localhost-Port `16379`
- `nextcloud-restore-test.sh`: Nextcloud-Restore-Job (Scaffold; **blockiert** durch Unraid shfs-chmod-Inkompatibilitaet - siehe unten)
- `nextcloud-compose.test.yml`: isolierte Testinstanz fuer Nextcloud inkl. Test-Postgres und Test-Redis
- `check-restore-freshness.ps1`: woechentlicher Frische-Check fuer Dumps und Reports ## Aufbau des Verzeichnisses
- `run-restore-checks.ps1`: einfacher Dispatcher fuer Restore-Jobs
- `check-restore-freshness.sh`: hosttauglicher Frische-Check
- `negative-freshness-alert-test.sh`: sicherer Negativtest fuer den Frische-Alarmweg; nutzt synthetische leere Testpfade unter `/mnt/user/backups/restore-lab/freshness-negative`, veraendert keine produktiven Dumps und sendet bei erkanntem Fehler einen Test-Alert nach `homelab-alerts`
- `run-restore-checks.sh`: hosttauglicher Dispatcher
- `common.sh`: gemeinsame Host-Helferfunktionen
- `automation-plan.md`: Host-Job- und Automatisierungsmodell
## Automatisierungsmodell Pro Dienst existieren bis zu drei Artefakte:
- Ausfuehrung: Unraid User Script / Host-Job - `<dienst>-restore-test.sh` - automatisierter Host-Job (produktive Wahrheit)
- Logik: Repo-Skripte in diesem Verzeichnis - `<dienst>-compose.test.yml` - isolierte Testinstanz
- Ergebnis: Markdown-Report - `<dienst>-runbook.md` - manueller Ablauf bzw. Besonderheiten
- Meldung: `ntfy`
- Hermes: optional nur fuer Zusammenfassung und Auswertung
Wichtig: Dazu zentrale Helfer:
- die Bash-Skripte `*.sh` sind die produktive Host-Variante - `run-restore-checks.sh` - Dispatcher (Host), `run-restore-checks.ps1` (lokale Planvariante)
- `check-restore-freshness.ps1` und die `*.ps1`-Dateien bleiben als lokale Plan-/Hilfsvariante nutzbar - `run-restore-job-with-ntfy.sh` - Wrapper: Erfolg -> `homelab-info`, Fehler -> `homelab-alerts`
- im Windows-Clone fehlen die `/mnt/user/...`-Pfade naturgemaess - `check-restore-freshness.sh` / `.ps1` - woechentlicher Frische-Check fuer Dumps und Reports (prueft pg-Dumps per `pg_restore --list`)
- `negative-freshness-alert-test.sh` - sicherer Negativtest des Alarmwegs (synthetischer Leerpfad, quartalsweise)
- `common.sh` - gemeinsame Borg-/Compose-Helfer
- `automation-plan.md` - Host-Job- und Automatisierungsmodell
## Validiertes Grundmuster ## Betriebsmodus
Stand nach dem ersten echten Vaultwarden-Test: Stand 2026-06-11 ist der Betrieb auf V1+ (validierte Bash-Host-Jobs mit ntfy):
- Borg-Quelle bleibt das produktive Remote-Repo bei Hetzner - Host-Jobs laufen als Unraid User Scripts vom Repo-Spiegel `/mnt/user/services/homelab-infra`
- Borg-Zugriff laeuft praktisch ueber den vorhandenen `borg-ui`-Container - Kadenz und Cron-Ausdruecke: `schedule.md` (woechentlicher Frische-Check, monatliche/quartalsweise Dienst-Rotation, monatlicher Zufalls-Restore)
- SSH-Trust wird ueber `known_hosts` im `borg-ui`-Container hergestellt - Job-Vorlagen: `unraid-user-scripts.md`
- die Borg-Passphrase kommt fuer Restore-Tests aus einer Host-Secret-Datei
- Restore-Ziel liegt immer getrennt unter `/mnt/user/backups/restore-lab`
- Reports liegen unter `/mnt/user/backups/restore-reports`
- Testinstanzen bekommen keine produktive Domain und keine Traefik-Route
Das ist das bevorzugte Muster fuer weitere dateibasierte Restore-Tests wie `gitea`. ## Schnellstart
Fuer datenbankgestuetzte Dienste wie `paperless` kommt zusaetzlich ein isolierter Dump-Restore in Test-Postgres dazu. ```bash
# Frische-Check
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh freshness
## Status # Dienst-Restore-Check (vaultwarden|gitea|paperless|immich|authelia|adguard|redis|komodo-bootstrap|nextcloud)
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh <dienst>
Aktuell ist das erste validierte Muster vorhanden. # Negativtest des Alarmwegs (quartalsweise)
bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-checks.sh freshness-negative
- echter Vaultwarden-Restore am 2026-05-07 erfolgreich verifiziert # Mit ntfy-Meldung
- echter Gitea-Restore am 2026-05-07 erfolgreich verifiziert bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-job-with-ntfy.sh freshness homelab-info
- echter Paperless-Restore am 2026-05-07 erfolgreich verifiziert ```
- Immich-Restore-Test am 2026-05-27 erfolgreich verifiziert; Test-Postgres wurde nach der VectorChord-Migration am 2026-05-31 auf das produktive Immich-Postgres-Image umgestellt
- Authelia-Restore-Smoke am 2026-06-03 erfolgreich verifiziert; bewusst ohne produktiven Dump-Restore wegen Storage-Encryption-Key-Kopplung
- AdGuard-Home-Restore-Smoke am 2026-06-06 erfolgreich verifiziert; Borg-Config-Restore, HTTP `/control/status` 401, DNS-Smoke ok, 7 Filterlisten-Eintraege, Report `/mnt/user/backups/restore-reports/adguard-2026-06-06.md`
- Redis-8-Restore-Smoke am 2026-06-06 erfolgreich verifiziert; Pre-Cutover-Artefakt, Redis 8.8, PING ok, AOF aktiv, DBSIZE 1, Report `/mnt/user/backups/restore-reports/redis-2026-06-06.md`
- Bash-Dispatcher und Bash-Restore-Jobs am 2026-05-07 erfolgreich hostseitig verifiziert
- Restore-Lab und Report-Pfade auf dem Host angelegt
- `ntfy`-Wrapper ist fuer Host-Jobs verfuegbar
- Frische-Negativtest ist als sicherer Host-Job verfuegbar und am 2026-06-06 auf Unraid validiert: `ops/restore-tests/run-restore-checks.sh freshness-negative`. Ergebnis: synthetischer leerer Dump-Pfad erzeugte 10 Criticals, Test-Alert ging nach `homelab-alerts`, produktive Dump-Pfade blieben unangetastet. Report: `/mnt/user/backups/restore-reports/freshness-negative-2026-06-06-130320.md`.
- Nextcloud-Restore-Test: Scaffold existiert, aber **blockiert**. Nextcloud 33 fuehrt zur Laufzeit `chmod()` auf Dateien unter `/var/www/html` aus (`OC_Util.php:486`). Auf Unraids FUSE/shfs User-Shares ist `chmod` strukturell nicht moeglich, was zu permanenter 503 fuehrt. Loesungsoptionen: (a) Restore-Lab auf ein Cache-Drive statt User Share legen, (b) Docker-Volumes statt Bind-Mounts verwenden, (c) tmpfs-Mount fuer html/ + `rsync` der Borg-Daten hinein. Bis dahin ist Nextcloud als Backlog-Item dokumentiert.
- Komodo-Mongo-Daten-Restore am 2026-06-03 erfolgreich: 86904 Dokumente (inkl. 32 Stacks), Report `/mnt/user/backups/restore-reports/komodo-mongo-restore-2026-06-03.md`
- naechste grosse Kandidaten sind Mailarchiver und Mealie; Nextcloud bleibt blockiert (shfs-chmod)
Vor dem ersten echten Testlauf je neuem Dienst muessen Zielpfade, Quellpfade und Bereinigungsschritte bewusst freigegeben werden. ## Status je Dienst
Einziger Status-Ort ist die **Reifegrad-Tabelle** in `docs/RESTORE_MATRIX.md`
(letzter Test, Typ, naechster Lauf). Hier nur Besonderheiten:
- **Nextcloud:** Test am 2026-06-03 erfolgreich, aber mit Unraid-shfs-Eigenheit: Nextcloud fuehrt `chmod()` unter `/var/www/html` aus, was auf FUSE/shfs scheitert. Das Skript patcht `check_data_directory_permissions: false` und legt den `.ncdata`-Marker an.
- **Authelia:** bewusst Config-Smoke ohne produktiven Dump-Restore (Storage-Encryption-Key-Kopplung).
- **Immich:** Foto-Dateien-Restore ist bewusst nicht Teil des Smokes (separater DR-Drill); Test-Postgres nutzt das produktive VectorChord-Image.
- **Unraid-Flash / Tailscale:** noch ohne vollstaendigen Erstlauf - `unraid-flash-runbook.md`, `tailscale-runbook.md`; offene Schritte in `docs/MASTER_TODO.md`.
## Naechste Ausbaustufen
1. Hermes-Zusammenfassung ueber vorhandene Reports (geparkt mit Hermes)
2. Report-Rotation: Reports werden dauerhaft aufbewahrt; bei wachsender Anzahl jaehrlich nach `_archive/YYYY/` verschieben. Der Frische-Check warnt ab `MAX_REPORT_AGE_DAYS=45`, loescht aber nie automatisch.
-89
View File
@@ -1,89 +0,0 @@
# Authelia Restore Test Plan
## Ziel
Nachweisen, dass die Authelia-Konfiguration aus dem produktiven Borg-Archiv in einer isolierten Testumgebung wieder lauffaehig ist und der HTTP-Health-Endpunkt antwortet, ohne dass dabei produktive Secrets, produktives Postgres oder produktiver SMTP-Versand beruehrt werden.
Bewusst **nicht** Teil dieses Tests:
- Restore mit produktiven Authelia-Secrets. Der Test nutzt ausschliesslich Wegwerf-Werte fuer `AUTHELIA_SESSION_SECRET`, `AUTHELIA_STORAGE_ENCRYPTION_KEY` und `AUTHELIA_STORAGE_POSTGRES_PASSWORD`. SMTP- und Legacy-JWT-Env-Werte werden bewusst nicht gesetzt, damit Authelia keinen `notifier.smtp`-Block oder deprecated `jwt_secret` aus Env erzeugt.
- SMTP-Realanruf an GMX. Die minimale Test-Konfiguration setzt nur den Filesystem-Notifier.
- Forward-Auth gegen Traefik. Test laeuft nur auf `127.0.0.1:19091`, keine Traefik-Route.
- WebAuthn-/Duo-/OIDC-Identity-Provider-Endpunkte. Smoke prueft `/api/health`.
- **pg_restore des produktiven `postgresql17-authelia.dump`**. Authelia verschluesselt Storage-Werte mit `AUTHELIA_STORAGE_ENCRYPTION_KEY`. Ein Restore mit produktiven Daten in eine Test-Instanz mit Wegwerf-Key schlaegt im Startup-Check **by design** fehl ("the configured encryption key does not appear to be valid for this database"). Frische des produktiven Dumps wird ueber `check-restore-freshness.sh` ueberwacht; Daten-Decrypt-Drill ist eine separate DR-Aufgabe und braucht eine eigene Sicherheits-Choreographie mit kontrollierter Schluessel-Verwendung. Beobachtet im Erstlauf 2026-06-03 (Commit-Reihe `cacf77b..8d71dfb`); seit dem 2026-06-03-Folgecommit ist der Dump-Restore explizit aus dem Smoke entfernt.
## Quelle
- Backup-Quelle: produktives Borg-Archiv (`hetzner_borg_appdata_critical`)
- fachlich relevante Pfade im Archiv:
- `local/appdata/authelia/config` (verpflichtend)
- `local/borg-dumps/latest/postgresql17-authelia.dump` (existiert ggf. im Archiv; wird vom Smoke bewusst NICHT eingespielt, siehe oben)
- produktive Secrets unter `/mnt/user/appdata/secrets/authelia_*.txt` werden **nicht** gemountet
## Test-Ziel
- Restore-Lab: `/mnt/user/backups/restore-lab/authelia`
- Testdatenpfade:
- `/mnt/user/backups/restore-lab/authelia/config` (restaurierte Originalkonfiguration + `configuration.yml.original`)
- `/mnt/user/backups/restore-lab/authelia/test-config` (Runtime-Mount mit minimaler Test-`configuration.yml`)
- `/mnt/user/backups/restore-lab/authelia/postgres` (Test-Postgres-Datadir)
- `/mnt/user/backups/restore-lab/authelia/dumps/latest/postgresql17-authelia.dump` (falls extrahiert)
- `/mnt/user/backups/restore-lab/authelia/test-config/notifier/notifications.txt` (Filesystem-Notifier-Ausgabe)
- Testcontainer:
- `restoretest-authelia` (Image-Pin wie Produktion)
- `restoretest-authelia-postgres` (postgres:18.4, gleiche Major wie shared Postgres)
- Testport: `127.0.0.1:19091:9091`
- Report-Ziel: `/mnt/user/backups/restore-reports/authelia-YYYY-MM-DD.md`
## Schutzregeln
- produktive Pfade `/mnt/user/appdata/authelia/*` werden **nicht** beschrieben
- produktive Secret-Dateien `/mnt/user/appdata/secrets/authelia_*.txt` werden **nicht** gemountet
- produktive shared PostgreSQL 18 wird **nicht** angesprochen (`test-config/configuration.yml` definiert nur Test-Postgres)
- echter SMTP-Versand wird **nicht** ausgeloest (`test-config/configuration.yml` definiert nur Filesystem-Notifier)
- produktive Domain `auth.kaleschke.info` wird **nicht** uebernommen
- Testcontainer publishen nur auf `127.0.0.1`, keine LAN-/Tailscale-Bindung
- Borg-Passphrase wird aus `/mnt/user/appdata/secrets/borg_repo_passphrase.txt` gelesen und nirgendwo geloggt
## Geplanter Ablauf
1. Restore-Lab-Pfade leer anlegen
2. `local/appdata/authelia/config` aus dem aktuellsten Borg-Archiv extrahieren
3. minimale `test-config/configuration.yml` erzeugen; restaurierte Begleitdateien wie `users_database.yml` bleiben im Runtime-Mount, produktive externe Abhaengigkeiten werden nicht uebernommen; `notifier` auf Filesystem, `ntp.disable_startup_check: true`, `storage` auf Test-Postgres
4. Test-Postgres mit `ops/restore-tests/authelia-compose.test.yml` **frisch** hochfahren (keine Daten aus Dump - siehe Encryption-Key-Begruendung oben)
5. `authelia config validate` gegen `test-config/configuration.yml` laufen lassen
6. `restoretest-authelia` starten und HTTP-Health `http://127.0.0.1:19091/api/health` pollen
7. Report unter `/mnt/user/backups/restore-reports/authelia-YYYY-MM-DD.md` schreiben
8. Testcontainer stoppen und Restore-Lab bereinigen (`--keep-data` ueberschreibt)
## Smoke-Test
Minimal erfolgreich:
- Borg-Extract der Authelia-Config gelingt
- Test-Postgres startet `healthy`
- `authelia config validate` laeuft ohne Fehler durch
- HTTP `200` auf `/api/health` innerhalb 120 s
Optional spaeter:
- vollstaendigen Auth-Flow gegen Test-User aus `users_database.yml` durchspielen
- WebAuthn-Endpunkt /api/secondfactor/webauthn pruefen
- ForwardAuth-Pfad gegen Mock-Backend testen
## Bekannte Komplikationen
| Risiko | Beschreibung | Mitigation |
|---|---|---|
| Testkonfig-Schema-Drift | Authelia erwartet nach Upgrade andere Keys in der Minimal-Konfig | bei `config validate`-Fehler Test-Block im Skript anpassen |
| SMTP-Startup-Check blockiert Start | Wenn Authelia trotz `disable_startup_check` SMTP probiert | Container-Logs lesen, ggf. Notifier-Block weiter haerten |
| NTP-Lookup im Test-Netz | Container hat keinen DNS-Resolver fuer `time.cloudflare.com` | im Smoke per `ntp.disable_startup_check: true` deaktiviert |
| Storage-Encryption-Key vs. Dump | siehe "Bewusst nicht Teil dieses Tests" - der Smoke laeuft FRISCH ohne Dump | by design - Daten-Decrypt-Drill ist separate Aufgabe |
| identity_validation Schema-Drift | Aelteres/neueres Authelia-Schema erwartet andere Keys | Validate-Config Output lesen, ggf. Test-Block anpassen |
| users_database.yml mit produktiven Hashes | Daten werden ins Restore-Lab kopiert, aber niemals gemountet auf produktive Domain | OK; Testpfad ist isoliert, kein Browser-Zugang ueber LAN |
## Status
- Skript- und Compose-Scaffold abgelegt am 2026-06-02
- Erstlauf am 2026-06-03 erfolgreich: Config aus Borg, minimale Test-Konfiguration, frisches Test-Postgres, HTTP `/api/health` `200`, Report `/mnt/user/backups/restore-reports/authelia-2026-06-03.md`
- Fuer die Rotation vorgesehen: zweiter Samstag in geraden Monaten, 07:30
-59
View File
@@ -1,59 +0,0 @@
# Gitea Restore Test Plan
## Ziel
Nachweisen, dass ein Gitea-Backup in einer isolierten Testumgebung wieder startbar ist und sowohl Web-UI als auch SSH-Port wieder verfuegbar sind.
## Quelle
- Backup-Quelle: Borg / Share-Backup
- fachlich relevanter Datenpfad: `/mnt/user/services/gitea/data`
- keine separaten Secret-Dateien dokumentiert
## Test-Ziel
- Restore-Lab: `/mnt/user/backups/restore-lab/gitea`
- Testdatenpfad: `/mnt/user/backups/restore-lab/gitea/data`
- Testcontainer: `restoretest-gitea`
- Testports:
- Web: `127.0.0.1:13000:3000`
- SSH: `127.0.0.1:12222:22`
- Report-Ziel: `/mnt/user/backups/restore-reports/gitea-YYYY-MM-DD.md`
## Schutzregeln
- produktiven Pfad `/mnt/user/services/gitea/data` nie beschreiben
- produktive Domain `git.kaleschke.info` nicht fuer die Testinstanz uebernehmen
- produktiven SSH-Port `222` nicht fuer die Testinstanz uebernehmen
- keine Traefik-Labels fuer die Testinstanz
- Testcontainer nur gegen Restore-Lab-Daten starten
## Geplanter Ablauf
1. Restore-Ziel unter `/mnt/user/backups/restore-lab/gitea` vorbereiten
2. Gitea-Daten aus Backup in `restore-lab/gitea/data` wiederherstellen
3. Testinstanz mit `ops/restore-tests/gitea-compose.test.yml` starten
4. lokalen Smoke-Test gegen `http://127.0.0.1:13000` und `127.0.0.1:12222` ausfuehren
5. Report unter `/mnt/user/backups/restore-reports/` schreiben
6. Testcontainer stoppen und Testumgebung bereinigen oder bewusst stehen lassen
## Smoke-Test
Minimal erfolgreich:
- Container startet
- Web-UI antwortet
- mindestens ein bestehendes Repository-Verzeichnis ist im Restore-Lab sichtbar
- SSH-Port reagiert auf Verbindungsaufbau
Optional spaeter:
- Login-Seite gezielt pruefen
- SQLite-Datei `gitea.db` oder Nachfolger explizit bestaetigen
- `gitea doctor` oder interner Healthcheck als Zusatz
## Noch offen vor dem ersten echten Lauf
- exakter Borg-Restore-Befehl bzw. Restore-Quelle auf dem Host
- Bereinigungsstrategie fuer alte Restore-Lab-Daten
- ob Reports spaeter zusaetzlich per `ntfy` referenziert werden
-89
View File
@@ -1,89 +0,0 @@
# Immich Restore Test Plan
## Ziel
Nachweisen, dass `immich.dump` aus dem produktiven Borg-Archiv in einer isolierten Testumgebung wieder einspielbar ist und Immich-Server damit anlaufen, einloggen und Asset-Metadaten anzeigen kann.
Bewusst **nicht** Teil dieses Tests:
- Wiederherstellung produktiver Foto-Dateien aus `/mnt/user/photos/immich` und `/mnt/user/photos/family_archive`. Der Smoke-Test bleibt DB-/UI-zentriert.
- Machine-Learning-Container. Spart Image-Pull-Zeit und Resource-Last; ML-Features sind im Smoke-Test nicht erforderlich.
- Echte Browser-Login-Sequenz. Smoke-Test prueft nur, dass die Login-Seite ausgeliefert wird und die DB-Tabellen `asset` und `"user"` lesbar sind.
## Quelle
- Backup-Quelle: produktives Borg-Archiv (`hetzner_borg_appdata_critical` oder lokales Mirror)
- fachlich relevanter Dump im Archiv:
- `local/borg-dumps/latest/immich.dump`
- Erzeuger: `ops/borg-ui/scripts/pre-backup-dumps.sh`, Funktion `dump_pg_db immich_postgres ... immich immich` mit `pg_dump -Fc`
- produktive Foto-Pfade werden im Smoke-Test bewusst **nicht** angefasst
## Test-Ziel
- Restore-Lab: `/mnt/user/backups/restore-lab/immich`
- Testdatenpfade:
- `/mnt/user/backups/restore-lab/immich/postgres` (Test-Postgres-Datadir)
- `/mnt/user/backups/restore-lab/immich/upload` (leeres Upload-Volume, Immich-Server braucht den Pfad nur als Mountpoint)
- `/mnt/user/backups/restore-lab/immich/dumps/latest/immich.dump` (extrahierter Dump)
- Testcontainer:
- `restoretest-immich-server`
- `restoretest-immich-postgres` (`ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0` - identisch zur Produktion, weil VectorChord-Backups ein Image mit VectorChord brauchen)
- `restoretest-immich-redis` (`redis:8.8.0-alpine`, rebuildbar)
- Testport Web: `127.0.0.1:12283:2283`
- Report-Ziel: `/mnt/user/backups/restore-reports/immich-YYYY-MM-DD.md`
## Schutzregeln
- produktive Pfade `/mnt/user/photos/immich` und `/mnt/user/photos/family_archive` werden **nicht** in den Test-Container gemountet
- produktive Domain `immich.kaleschke.info` wird **nicht** uebernommen
- keine Traefik-Labels fuer die Testinstanz
- keine produktive `immich_postgres`-/`immich_redis`-Instanz fuer den Test verwenden
- ML-Container bleibt weg
- Testcontainer publishen nur auf `127.0.0.1`, nicht auf LAN- oder Tailscale-Interface
- Borg-Passphrase wird aus `/mnt/user/appdata/secrets/borg_repo_passphrase.txt` gelesen und niemals in Logs, Reports oder Doku geschrieben
## Geplanter Ablauf
1. Restore-Ziel unter `/mnt/user/backups/restore-lab/immich` vorbereiten (postgres, upload, dumps/latest)
2. `local/borg-dumps/latest/immich.dump` aus dem aktuellsten Borg-Archiv extrahieren
3. Test-Postgres (Immich-Postgres mit VectorChord) und Test-Redis mit `ops/restore-tests/immich-compose.test.yml` starten
4. `immich.dump` in Test-Postgres importieren (`pg_restore -Fc --clean --if-exists --no-owner --no-privileges`)
5. Testinstanz `restoretest-immich-server` starten
6. lokalen Smoke-Test gegen `http://127.0.0.1:12283` ausfuehren und Asset/User-Count aus DB lesen
7. Report unter `/mnt/user/backups/restore-reports/immich-YYYY-MM-DD.md` schreiben
8. Testcontainer stoppen und Restore-Lab bereinigen
## Smoke-Test
Minimal erfolgreich:
- Test-Postgres startet `healthy`
- `pg_restore -Fc` laeuft ohne Fehler durch
- Immich-Server liefert HTTP `200`, `302` oder `303` auf `/`
- Response enthaelt mindestens einen der Marker `Immich`, `Login`, `Signin`
- `select count(*) from asset;` und `select count(*) from "user";` sind lesbar
Optional spaeter:
- Echte Login-Form via API ansprechen
- VectorChord-/pgvector-Extensions explizit per `\dx` pruefen
- Test mit gemountetem **read-only** Foto-Sample-Pfad und Thumbnail-Rendering
- Test inkl. ML-Container, sobald genug Test-Ressourcen verfuegbar
## Bekannte Komplikationen
| Risiko | Beschreibung | Mitigation |
|---|---|---|
| Dump-Groesse unbekannt | `pg_dump -Fc` der Immich-DB kann je nach Asset-/Face-Tabellen mehrere GB sein | Erster Lauf bewusst mit `--what-if`, anschliessend Operator-Test mit Zeitmessung |
| `pg_restore`-Dauer unbekannt | Index-/Constraint-Aufbau und VectorChord-Index-Build koennen lange dauern | Test-Postgres mit Health-Polling startet; Lauf nicht abbrechen ohne `pg_restore`-Exit |
| VectorChord-/pgvector-Extension-Mismatch | Wenn das Test-Postgres-Image nicht zu Produktion passt, kann der Restore oder Immich-Start fehlschlagen | Compose pinnt denselben Digest wie `apps/immich/docker-compose.yml` |
| Immich-Server-Migrations beim Start | Immich fuehrt beim ersten Start DB-Migrations aus; das kann nach Restore noch laufen, bevor Web-UI antwortet | Smoke-Test pollt HTTP bis zu 120 s, bevor er als Fehler markiert |
| Asset-Files fehlen | Der Test mountet kein Foto-Volume; Immich zeigt "missing" auf Asset-Detail-Seiten | Smoke-Test prueft nur Login-Page und DB-Counts, nicht Asset-Rendering |
| ML-Endpoint unreachable | Immich-Server kann ML-Endpoint nicht erreichen | `IMMICH_MACHINE_LEARNING_URL` zeigt bewusst auf einen nicht erreichbaren Hostnamen; Login bleibt funktional, ML-Features bleiben deaktiviert |
## Noch offen vor dem ersten echten Lauf
- Dump-Groesse `immich.dump` auf dem Host bestimmen (`ls -lh /mnt/user/backups/borg/dumps/latest/immich.dump`)
- Erwartete Restore-Dauer durch ersten Lauf mit `--keep-data` messen
- Pruefen, ob die Immich-Tabellen `assets`/`users` im aktuellen Schema noch existieren (Schema-Drift bei Major-Update wuerde die Asset-Count-Query brechen, das Skript faengt das tolerant ab)
- Schedule-Eintrag in `ops/restore-tests/schedule.md`: aktuell ist Immich nur als "spaeter, eigener Sprint" gefuehrt. Erst nach erstem erfolgreichen Lauf in Schedule aufnehmen, z. B. quartalsweise.
-1
View File
@@ -34,7 +34,6 @@ Vor dem ersten Lauf muss Operator entscheiden:
- `ops/restore-tests/immich-compose.test.yml` - `ops/restore-tests/immich-compose.test.yml`
- `ops/restore-tests/immich-restore-test.sh` - `ops/restore-tests/immich-restore-test.sh`
- `ops/restore-tests/immich-restore-test.ps1` (Scaffold, kein Live-Run) - `ops/restore-tests/immich-restore-test.ps1` (Scaffold, kein Live-Run)
- `ops/restore-tests/immich-plan.md`
- `ops/restore-tests/immich-runbook.md` - `ops/restore-tests/immich-runbook.md`
## Erster Lauf - trockene Variante ## Erster Lauf - trockene Variante
@@ -1,88 +0,0 @@
# Komodo Bootstrap Trockenlauf - Plan
## Ziel
Nachweisen, dass `ops/komodo/docker-compose.yml` als Recovery-Anker fuer einen Komodo-Kaltstart tauglich ist, ohne den produktiven Komodo-Stack anzufassen.
Bewusst **nicht** Teil dieses Tests:
- Restore aus dem produktiven `komodo-mongo.archive.gz`-Dump (eigene Folgeaufgabe; dieser Test prueft nur das Compose-Bootstrap, nicht den Daten-Restore).
- docker.sock-Mount fuer die Test-Periphery (die Test-Periphery darf nie produktive Container managen).
- Traefik-Route oder Authelia-Anbindung (Test laeuft ausschliesslich auf `127.0.0.1:19120`).
## Quelle
- Bootstrap-Anker: `ops/komodo/docker-compose.yml` (Soll-Stand laut `docs/SERVICES_RECOVERY.md` Stufe A-F).
- Image-Digests: identisch zur Produktion fuer komodo-core und komodo-periphery; Mongo-Image identisch.
## Test-Ziel
- Restore-Lab: `/mnt/user/backups/restore-lab/komodo`
- Wegwerf-Pfade:
- `/mnt/user/backups/restore-lab/komodo/mongo` (Test-Mongo-Datadir)
- `/mnt/user/backups/restore-lab/komodo/core` (Repo-Cache)
- `/mnt/user/backups/restore-lab/komodo/keys` (gemeinsamer Keys-Pfad fuer Core+Periphery)
- `/mnt/user/backups/restore-lab/komodo/periphery` (Periphery-Etc)
- Testcontainer:
- `restoretest-komodo-mongo`
- `restoretest-komodo-core` (Test-Port `127.0.0.1:19120`)
- `restoretest-komodo-periphery` (ohne docker.sock)
- Compose-Project: `restoretest-komodo` (isoliert von Produktions-Project `komodo`)
- Report-Ziel: `/mnt/user/backups/restore-reports/komodo-bootstrap-YYYY-MM-DD.md`
## Schutzregeln
- produktive Datadirs `/mnt/user/appdata/komodo/{mongo,core,periphery}` werden **nicht** gemountet
- produktive Container `komodo-mongo`, `komodo-core`, `komodo-periphery` werden **nicht** gestoppt
- produktive `KOMODO_*`-Secrets werden **nicht** verwendet
- Test-Compose enthaelt nur Wegwerf-Werte fuer `KOMODO_SECRET_KEY`, `KOMODO_WEBHOOK_SECRET`, `KOMODO_JWT_SECRET`, `KOMODO_PASSKEY` und Mongo-Root-Password
- Test-Periphery laeuft ohne docker.sock-Mount und ohne `/mnt/user/services`-Mount
- Test-Port nur auf `127.0.0.1:19120`, keine LAN-/Tailscale-Bindung
## Geplanter Ablauf
1. Restore-Lab-Pfade leer anlegen
2. `docker compose config` auf dem Test-Compose validieren
3. Mongo und Core hochfahren, auf Mongo-`healthy` warten
4. HTTP-Smoke gegen `http://127.0.0.1:19120` (Login-Seite oder Auth-Redirect erwartet)
5. Periphery dazustarten, kurz beobachten
6. Mongo-`authenticated ping` mit Test-Credentials
7. Report schreiben
8. Cleanup `docker compose down -v` und Restore-Lab loeschen (ausser `--keep-data`)
## Smoke-Test
Minimal erfolgreich:
- `docker compose config` valid
- Test-Mongo erreicht `healthy`
- Mongo-Authentifizierung mit Test-Creds funktioniert (`db.adminCommand({ping:1}).ok = 1`)
- Komodo-Core HTTP `200`, `302`, `303` oder `401` (alles ist ein valider Lebenszeichen)
- Test-Periphery container state `running`
Optional spaeter:
- Periphery-Verbindung gegen Test-Core verifizieren (braucht Periphery-Konfig mit `core_url`)
- Echtes Restore aus `komodo-mongo.archive.gz`-Dump in die Test-Mongo
- Schreiben einer Wegwerf-Resource (Server/Stack) ueber die API
## Bekannte Komplikationen
| Risiko | Beschreibung | Mitigation |
|---|---|---|
| Image-Drift | Komodo-Images aktualisieren ihre Major-Tag-Digests | Compose pinnt denselben Digest wie Produktion; bei Image-Update auch Test-Compose nachziehen |
| Port-Konflikt | wenn 19120 anderweitig belegt ist | nur `127.0.0.1`-Bind; bei Konflikt Port im Compose anpassen |
| Volume-Reste | unterbrochener Lauf laesst Wegwerf-Datadir liegen | Skript loescht Restore-Lab vor jedem Lauf; `--keep-data` ueberschreibt das bewusst |
| Periphery-Erreichbarkeit | Core sucht Periphery initial nicht aktiv | Test prueft nur Periphery `State.Status=running`; voller Handshake ist optional |
## Bestaetigte Laeufe
| Datum | Mode | Ergebnis | Report |
|---|---|---|---|
| 2026-05-30 | `--what-if` | Plan-Ausgabe wie erwartet | (kein Report, nur stdout) |
| 2026-05-30 | `--keep-data` | `SUCCESS`, 5/5 Checks gruen, Core HTTP `200`, Mongo healthy in ~6 s | `/mnt/user/backups/restore-reports/komodo-bootstrap-2026-05-30.md` |
## Folgeschritte
- Quartals-Belegung: Komodo-Bootstrap passt zum DR-Sanity-Check (`ops/restore-tests/schedule.md` Q2/Q4) und kann ohne Borg-Archiv jederzeit wiederholt werden.
- Optional fuer kuenftige Laeufe: echtes Restore aus `komodo-mongo.archive.gz` in die Test-Mongo, danach Schreiben einer Wegwerf-Resource ueber die API.
-72
View File
@@ -1,72 +0,0 @@
# Paperless Restore Test Plan
## Ziel
Nachweisen, dass ein Paperless-Backup in einer isolierten Testumgebung wieder startbar ist und sowohl Dokumentenpfade als auch PostgreSQL-Dump sauber zusammenlaufen.
## Quelle
- Backup-Quelle: Borg / Share-Backup
- fachlich relevante Dateipfade:
- `/mnt/user/appdata/paperless-ngx/data`
- `/mnt/user/documents/paperless`
- `/mnt/user/documents/paperless/export`
- `/mnt/user/documents/scans_inbox`
- fachlich relevanter Dump:
- `/mnt/user/backups/borg/dumps/latest/postgresql17-paperless.dump`
## Test-Ziel
- Restore-Lab: `/mnt/user/backups/restore-lab/paperless`
- Testdatenpfade:
- `/mnt/user/backups/restore-lab/paperless/data`
- `/mnt/user/backups/restore-lab/paperless/media`
- `/mnt/user/backups/restore-lab/paperless/export`
- `/mnt/user/backups/restore-lab/paperless/consume`
- `/mnt/user/backups/restore-lab/paperless/postgres`
- Testcontainer:
- `restoretest-paperless`
- `restoretest-paperless-postgres`
- `restoretest-paperless-redis`
- Testport Web: `127.0.0.1:18120:8000`
- Report-Ziel: `/mnt/user/backups/restore-reports/paperless-YYYY-MM-DD.md`
## Schutzregeln
- produktive Pfade nie beschreiben
- produktive Domain `paperless.kaleschke.info` nicht fuer die Testinstanz uebernehmen
- keine Traefik-Labels fuer die Testinstanz
- keine produktive PostgreSQL- oder Redis-Instanz fuer den Test verwenden
- Testcontainer nur gegen Restore-Lab-Daten und isolierte Test-Backends starten
## Geplanter Ablauf
1. Restore-Ziel unter `/mnt/user/backups/restore-lab/paperless` vorbereiten
2. Paperless-Dateipfade aus Borg in das Restore-Lab wiederherstellen
3. Test-Postgres und Test-Redis mit `ops/restore-tests/paperless-compose.test.yml` starten
4. `postgresql17-paperless.dump` in Test-Postgres importieren
5. Testinstanz `restoretest-paperless` starten
6. lokalen Smoke-Test gegen `http://127.0.0.1:18120` ausfuehren
7. Report unter `/mnt/user/backups/restore-reports/` schreiben
8. Testcontainer stoppen und Testumgebung bereinigen
## Smoke-Test
Minimal erfolgreich:
- Test-Postgres startet
- Dump-Import gelingt
- Paperless-Web-UI antwortet
- mindestens ein Dokument liegt im Restore-Lab-Medienpfad
Optional spaeter:
- Login-Seite gezielt pruefen
- Dokumentanzahl aus UI oder DB querpruefen
- OCR-/Task-Worker-Status verifizieren
## Noch offen vor dem ersten echten Lauf
- exakter Borg-Restore-Befehl fuer alle vier Dateipfade
- exakter `pg_restore`-Befehl im Test-Postgres
- wie stark wir `consume` im ersten Lauf ueberhaupt brauchen
+34
View File
@@ -0,0 +1,34 @@
# Tailscale - Restore-Runbook
Typ: Runbook · Stand: 2026-06-11 · Status: aktiv (noch kein Erstlauf)
Restore-Pfad fuer den Tailscale-State. Wichtig: Tailscale laeuft als
**natives Unraid-Plugin**; der funktionale State liegt unter
`/boot/config/plugins/tailscale/state` und ist Teil des Flash-Backups
(`docs/RESTORE_MATRIX.md` Tier 1).
## Voraussetzungen
- Zugriff auf das Flash-Backup-Artefakt bzw. ein Borg-Archiv mit dem State-Pfad
- Testpfad unter `/mnt/user/backups/restore-lab/tailscale` vorbereitet
- **Achtung:** Der Tailscale-State ist maschinenspezifisch. Ein Restore auf den produktiven Host wuerde die laufende Verbindung verdraengen. Nur auf einem Wegwerf- oder Offline-Host testen.
## Artefakt-Validierung (ohne produktiven Host)
1. State-Verzeichnis in den Testpfad extrahieren
2. Erwartete Dateien pruefen: `tailscaled.state` vorhanden
3. Dateisystem-Rechte pruefen: `tailscaled.state` muss fuer `root` zugaenglich sein
## Reconnect-Test (auf Wegwerf-Host oder VM)
1. Tailscale mit dem gemounteten State-Pfad starten
2. `tailscale status` zeigt `Connected` oder den erwarteten Hostnamen
3. Tailscale-Admin-Konsole zeigt das Geraet als `Online`
4. SSH ueber Tailscale-IP auf den Testhost moeglich
5. Testinstanz stoppen; Wegwerf-Geraet in der Tailscale-Admin-Konsole entfernen
**Smoke-Test-Kriterium:** Instanz verbindet sich mit bestehendem Tailscale-Account (kein neues Re-Auth noetig), Tailscale-IP ist erreichbar.
**Hinweis:** Falls der State veraltet ist (Key expired), fordert Tailscale ein
Re-Auth an. Das ist ein valides Testergebnis und belegt, wie lang der
Reconnect-Pfad bei abgelaufenem Key ist.
+45
View File
@@ -0,0 +1,45 @@
# Unraid OS Flash - Restore-Runbook
Typ: Runbook · Stand: 2026-06-11 · Status: aktiv (Stick-Boot-Test offen)
Restore-Pfad fuer die Unraid-Flash-Konfiguration. Artefakt-Validierung ist
automatisiert und belegt; offen bleibt nur der physische Ersatzstick-Boot-Test
(siehe `docs/MASTER_TODO.md`).
## Voraussetzungen
- Borg-Artefakt `unraid-flash-config.tar.gz` und `.sha256` unter `/mnt/user/backups/borg/dumps/latest` oder im Hetzner-Borg-Repo verfuegbar
- Neuer leerer USB-Stick (Empfehlung: 16 GB, USB 2.0 kompatibel)
- Unraid USB Flash Creator oder manueller Restore-Pfad
- Offline-gesicherte Borg-Passphrase verfuegbar
## Artefakt-Validierung (ohne produktiven Stick)
Automatisiert via Repo-Skript `ops/maintenance/check-unraid-flash-backup.sh`
(read-only, keine Extraktion). Manuelle Einzelschritte:
1. SHA256-Pruefung: `sha256sum -c unraid-flash-config.tar.gz.sha256`
2. Artefakt-Inhalt pruefen: `tar -tzf unraid-flash-config.tar.gz | head -40` — erwartet `config/` als Prefix
3. Kern-Configs vorhanden: `super.dat`, `disk.cfg`, `ident.cfg`, `share.cfg`, `network.cfg`, `docker.cfg`, `go`, `domain.cfg`
4. Keine produktiven Konfigurationspfade (z. B. `config/ssh/`) ausserhalb des Test-Environments extrahieren
5. Manifest-Datei auf Vollstaendigkeit pruefen
Letzte Validierung: 2026-06-05, Exit 0, sha256 OK, 390 Eintraege, 8/8
Kern-Configs (siehe Reifegrad-Tabelle in `docs/RESTORE_MATRIX.md`).
## Vollstaendiger Restore-Test (auf Wegwerf-Stick)
1. Neuen USB-Stick mit Unraid USB Flash Creator formatieren und Basis-Unraid draufspielen
2. `config/`-Verzeichnis aus `unraid-flash-config.tar.gz` in den `/boot/config`-Pfad des neuen Sticks extrahieren
3. Im Testrahmen booten (kein Array starten, keine Shares mounten)
4. Pruefen: Unraid-Grundkonfiguration (Shares, Hostname, Netzwerk) ist sichtbar
5. Array-Zuordnung lesbar, ohne Drive-Assigns zu bestaetigen
**Smoke-Test-Kriterium:** Unraid bootet, Hostname ist `Kallilabcore`, Share-Konfiguration ist sichtbar, kein Array gestartet.
## Sonderregel
Das Artefakt enthaelt Host-Konfiguration und Secret-Material (SSH-Host-Keys,
Tailscale-State, `passwd`/`shadow`/`smbpasswd`, Lizenz-Key) und ist wie
Secret-Backup zu behandeln. Nicht auf oeffentlichen oder unverschluesselten
Testzielen extrahieren.
-56
View File
@@ -1,56 +0,0 @@
# Vaultwarden Restore Test Plan
## Ziel
Nachweisen, dass ein Vaultwarden-Backup in einer isolierten Testumgebung wieder startbar und fachlich nutzbar ist.
## Quelle
- Backup-Quelle: Borg / Share-Backup
- fachlich relevanter Datenpfad: `/mnt/user/appdata/vaultwarden`
- Produktives Admin-Token wird fuer den Restore-Smoke bewusst nicht gemountet;
die Testinstanz nutzt einen Wegwerf-Wert aus `vaultwarden-compose.test.yml`.
## Test-Ziel
- Restore-Lab: `/mnt/user/backups/restore-lab/vaultwarden`
- Testdatenpfad: `/mnt/user/backups/restore-lab/vaultwarden/data`
- Testcontainer: `restoretest-vaultwarden`
- Testport: `127.0.0.1:18080:80`
- Report-Ziel: `/mnt/user/backups/restore-reports/vaultwarden-YYYY-MM-DD.md`
## Schutzregeln
- produktiven Pfad `/mnt/user/appdata/vaultwarden` nie beschreiben
- produktive Domain `vault.kaleschke.info` nicht fuer die Testinstanz uebernehmen
- keine Traefik-Labels fuer die Testinstanz
- Testcontainer nur gegen Restore-Lab-Daten starten
## Geplanter Ablauf
1. Restore-Ziel unter `/mnt/user/backups/restore-lab/vaultwarden` vorbereiten
2. Vaultwarden-Daten aus Backup in `restore-lab/vaultwarden/data` wiederherstellen
3. Testinstanz mit `ops/restore-tests/vaultwarden-compose.test.yml` starten
4. lokalen Smoke-Test gegen `http://127.0.0.1:18080` ausfuehren
5. Report unter `/mnt/user/backups/restore-reports/` schreiben
6. Testcontainer stoppen und Testumgebung bereinigen oder bewusst stehen lassen
## Smoke-Test
Minimal erfolgreich:
- Container startet
- Login-Seite antwortet
- Vaultwarden-Daten sind vorhanden
Optional spaeter:
- Admin-Endpunkt nur mit separatem Wegwerf-Token pruefen
- Websocket-Endpunkt pruefen
- Anzahl/Vorhandensein zentraler Daten artefaktisch verifizieren
## Noch offen vor dem ersten echten Lauf
- exakter Borg-Restore-Befehl bzw. Restore-Quelle auf dem Host
- Bereinigungsstrategie fuer alte Restore-Lab-Daten
- ob Reports nur auf dem Host liegen oder zusaetzlich per ntfy referenziert werden
+14 -7
View File
@@ -1,11 +1,18 @@
# Windows Reinstall Helpers # Windows Reinstall Helpers
Diese Skripte sind bewusst versionierte Operator-Hilfen fuer den Windows-Neuaufsetzen-/Dual-Boot-Kontext vom Mai 2026. Typ: Runbook/Tool-Doku · Stand: 2026-06-11 · Status: aktiv (Projekt Mai 2026 abgeschlossen)
- `backup-delta-after-2026-05-07.ps1` kopiert nach einem definierten Cutoff lokale Nutzdaten in ein Backup-Ziel. Versionierte Operator-Hilfen rund um die Windows-Workstation `baerchen`.
- `repair-disk0-boot-to-new-windows.ps1` repariert EFI/Bootdateien fuer das neue Windows auf der Intel-SSD und verlangt Adminrechte. Das Neuaufsetzen-Projekt vom Mai 2026 ist abgeschlossen; die zugehoerigen
- `cleanup-dualboot-bcd.ps1` bereinigt BCD-Bootmenueeintraege und verlangt eine explizite Textbestaetigung. Plaene und Snapshots liegen in `docs/archive/2026/`.
- `ops/windows-reinstall/docs/windows-neuaufsetzen-masterplan.md` und `ops/windows-reinstall/docs/postinstall-erstes-ziel-codex.md` enthalten die zugehoerigen Operator-Notizen.
- `ops/windows-reinstall/docs/postdelta-2026-06-04.md` dokumentiert den PostDelta-Stand vom 2026-06-04: aktuellster Banking4-Tresor, WISO-Ergaenzungen, Overwatch-2-Config, iCUE/Corsair-Maussettings und `D:\Users\michi`-Admincheck.
Die Skripte enthalten keine Secrets, arbeiten aber mit lokalen Windows-Datentraegern und duerfen nur interaktiv und mit vorheriger Sichtpruefung ausgefuehrt werden. Aktiv bleiben:
- `docs/windows-image-backup-baseline.md` — Veeam-Image-Backup-/Restore-Runbook fuer `baerchen` (DR-relevant, referenziert aus `docs/RESTORE_MATRIX.md`).
- `docs/laufwerks-neustruktur-2026-06-04.md` — Soll-Referenz der Laufwerks-/Ordnerstruktur.
- `backup-delta-after-2026-05-07.ps1` — kopiert nach einem definierten Cutoff lokale Nutzdaten in ein Backup-Ziel.
- `repair-disk0-boot-to-new-windows.ps1` — repariert EFI/Bootdateien (Adminrechte noetig).
- `cleanup-dualboot-bcd.ps1` — bereinigt BCD-Bootmenueeintraege (explizite Textbestaetigung noetig).
Die Skripte enthalten keine Secrets, arbeiten aber mit lokalen Windows-Datentraegern
und duerfen nur interaktiv und mit vorheriger Sichtpruefung ausgefuehrt werden.
@@ -221,7 +221,7 @@ Kopier-/Doppelbestand:
## Offene Punkte ## Offene Punkte
- ~~WinRE/Secure Boot/TPM Admin-Check~~ **Erledigt 2026-06-05** (siehe Abschnitt "Admin-Nachlauf 2026-06-05"): WinRE aktiviert, Secure Boot `True`, TPM ready/enabled. - ~~WinRE/Secure Boot/TPM Admin-Check~~ **Erledigt 2026-06-05** (siehe Abschnitt "Admin-Nachlauf 2026-06-05"): WinRE aktiviert, Secure Boot `True`, TPM ready/enabled.
- **BitLocker-Entscheidung offen:** Alle Laufwerke `FullyDecrypted`, Protection `Off`. Vor Aktivierung: Recovery Keys fuer mindestens `C:` und `D:` an drei Orten sichern (Vaultwarden, `D:\30_Finanzen\BitLocker-RecoveryKey-baerchen-<DATUM>.txt`, physisch). Verweis: `docs/MASTER_TODO.md` Abschnitt "Windows / Workstation baerchen". - **BitLocker bewusst deaktiviert (Entscheidung 2026-06-06):** Alle Laufwerke `FullyDecrypted`, Protection `Off`. Recovery laeuft ueber das Veeam-Image; kein BitLocker-Key-Management. Bei spaeterer Aktivierung waere ein neuer Aenderungsblock mit Recovery-Key-Ablage noetig.
- Optional: `D:\11_Bilder` ReadOnly-Attribut beobachten; fuer Windows-Shell-Ordner ist das in der Praxis meist unkritisch. - Optional: `D:\11_Bilder` ReadOnly-Attribut beobachten; fuer Windows-Shell-Ordner ist das in der Praxis meist unkritisch.
- Optional: `D:\13_Musik` bleibt leer, solange aus dem Backup keine Musikdaten nachgezogen werden muessen. - Optional: `D:\13_Musik` bleibt leer, solange aus dem Backup keine Musikdaten nachgezogen werden muessen.
- Optional: `G:\Apps`, `G:\Workspace`, `D:\WSL` in der Homelab-/Dev-Doku ergaenzen. - Optional: `G:\Apps`, `G:\Workspace`, `D:\WSL` in der Homelab-/Dev-Doku ergaenzen.
@@ -314,7 +314,7 @@ Admin-Nachlauf 2026-06-05:
- TPM: vorhanden, ready, enabled, activated, owned - TPM: vorhanden, ready, enabled, activated, owned
- BitLocker-Status geprueft: - BitLocker-Status geprueft:
- `C:`, `D:`, `E:`, `G:`, `H:` sind `FullyDecrypted`, Protection `Off` - `C:`, `D:`, `E:`, `G:`, `H:` sind `FullyDecrypted`, Protection `Off`
- BitLocker wurde nicht automatisch aktiviert, weil dafuer eine bewusste Recovery-Key- und Lockout-Entscheidung noetig ist. - BitLocker wurde bewusst nicht aktiviert (Entscheidung 2026-06-06); Recovery laeuft ueber das Veeam-Image.
- OneDrive Per-Machine Standalone Update Task wurde deaktiviert. - OneDrive Per-Machine Standalone Update Task wurde deaktiviert.
- SSH-Aliases angelegt und getestet: - SSH-Aliases angelegt und getestet:
- `kallilabcore` -> `root@100.80.98.33` - `kallilabcore` -> `root@100.80.98.33`
@@ -322,4 +322,4 @@ Admin-Nachlauf 2026-06-05:
Weiter offen: Weiter offen:
- BitLocker-Entscheidung fuer mindestens `C:` und `D:` treffen. Vor Aktivierung Recovery Keys extern sichern. - Kein BitLocker-Todo mehr. Spaetere Aktivierung nur als neuer bewusster Aenderungsblock mit externer Recovery-Key-Ablage.
@@ -1,6 +1,6 @@
# Windows Image Backup Baseline - baerchen # Windows Image Backup Baseline - baerchen
Stand: 2026-06-05 Stand: 2026-06-06
Dieses Runbook beschreibt den Windows-Image-Backup-Workflow fuer den frisch Dieses Runbook beschreibt den Windows-Image-Backup-Workflow fuer den frisch
aufgesetzten Windows-11-Rechner `baerchen`. Ziel ist ein schneller Bare-Metal- aufgesetzten Windows-11-Rechner `baerchen`. Ziel ist ein schneller Bare-Metal-
@@ -22,7 +22,7 @@ Unraid-SMB-Share `backups`.
| Share-Modell | bestehender Unraid-Share `backups`, kein neuer Share | | Share-Modell | bestehender Unraid-Share `backups`, kein neuer Share |
| SMB-User | `micha` (bestehender Unraid-User mit Read/Write auf `backups`) | | SMB-User | `micha` (bestehender Unraid-User mit Read/Write auf `backups`) |
| Veeam Job | `baerchen-c-image` | | Veeam Job | `baerchen-c-image` |
| Verschluesselung | Stand erster Lauf: Veeam Storage Encryption **nicht aktiv** (`StorageEncryptionEnabled=False` im Job-Log); optional separat aktivieren und neues Full-Backup erzeugen | | Verschluesselung | Veeam Storage Encryption **bewusst nicht aktiv** (`StorageEncryptionEnabled=False` im Job-Log); neu bewerten nur bei Off-host-Auslagerung des Windows-Images |
| Recovery Media | USB-Stick `VEEAMRE` auf Laufwerk F: erstellt | | Recovery Media | USB-Stick `VEEAMRE` auf Laufwerk F: erstellt |
## Bewusste Entscheidungen ## Bewusste Entscheidungen
@@ -33,8 +33,8 @@ Unraid-SMB-Share `backups`.
- Es wurde vorerst kein dedizierter SMB-User `veeam-baerchen` angelegt, um - Es wurde vorerst kein dedizierter SMB-User `veeam-baerchen` angelegt, um
keine Unraid-Share-/User-Aenderung zu erzwingen. Der produktive Job nutzt keine Unraid-Share-/User-Aenderung zu erzwingen. Der produktive Job nutzt
den bestehenden User `micha`. den bestehenden User `micha`.
- BitLocker wurde am 2026-06-05 nicht aktiviert. TPM, Secure Boot und WinRE - BitLocker bleibt bewusst deaktiviert (Entscheidung 2026-06-06). Recovery
wurden geprueft; BitLocker bleibt ein separater Security-Schritt. laeuft ueber das Veeam-Image; kein BitLocker-Key-Management.
- Der Recovery-Stick ist Teil des Restore-Pfads und muss getrennt vom Rechner - Der Recovery-Stick ist Teil des Restore-Pfads und muss getrennt vom Rechner
aufbewahrt werden. aufbewahrt werden.
@@ -65,14 +65,13 @@ Veeam Agent -> Job `baerchen-c-image`
- Shared folder: `\\kallilabcore\backups\windows-images\baerchen` - Shared folder: `\\kallilabcore\backups\windows-images\baerchen`
- Credentials: bestehender Unraid-SMB-User `micha` - Credentials: bestehender Unraid-SMB-User `micha`
- Compression: `Optimal` - Compression: `Optimal`
- Storage encryption: Stand erster Lauf **nicht aktiv** - Storage encryption: **bewusst nicht aktiv**
- Schedule: Workstation-Schedule in Veeam; Stand 2026-06-05: taeglich nachts - Schedule: Workstation-Schedule in Veeam; Stand 2026-06-05: taeglich nachts
eingerichtet. eingerichtet.
Wenn Veeam Storage Encryption spaeter aktiviert wird, ist das Wenn Veeam Storage Encryption spaeter doch aktiviert wird, ist das ein neuer
Veeam-Job-Passwort nicht aus dem Repo wiederherstellbar. Es muss dann in bewusster Aenderungsblock: Passwort in Vaultwarden anlegen, Job umstellen,
Vaultwarden als eigener Eintrag/Secure Note liegen und vor dem ersten neues Full-Backup erzeugen und Recovery-Test wiederholen.
verschluesselten Full-Backup getestet werden.
## Secrets und Ablageorte ## Secrets und Ablageorte
@@ -80,9 +79,9 @@ Keine Secret-Werte in dieses Repository schreiben.
| Secret | Ablage | | Secret | Ablage |
|---|---| |---|---|
| Veeam Job Encryption Password | nur noetig, falls Veeam Storage Encryption aktiviert wird; Ziel: Vaultwarden Secure Note `Veeam baerchen backup encryption password` | | Veeam Job Encryption Password | nicht noetig, solange Veeam Storage Encryption bewusst deaktiviert bleibt; Ziel bei spaeterer Aktivierung: Vaultwarden Secure Note `Veeam baerchen backup encryption password` |
| SMB Credential fuer Backup-Ziel | bestehender Unraid/Vaultwarden-Eintrag fuer User `micha` | | SMB Credential fuer Backup-Ziel | bestehender Unraid/Vaultwarden-Eintrag fuer User `micha` |
| BitLocker Recovery Key | noch nicht aktiv; Ziel bei Aktivierung: `D:\30_Finanzen\BitLocker-RecoveryKey-baerchen-<DATUM>.txt`, Vaultwarden Secure Note, physischer Ausdruck | | BitLocker Recovery Key | nicht noetig, weil BitLocker bewusst deaktiviert ist; Ziel bei spaeterer Aktivierung: `D:\30_Finanzen\BitLocker-RecoveryKey-baerchen-<DATUM>.txt`, Vaultwarden Secure Note, physischer Ausdruck |
## Recovery Media ## Recovery Media
@@ -173,12 +172,10 @@ den Job erfolgreich schreibt, liegt das meist an getrennten Credentials:
Veeam nutzt gespeicherte Job-Credentials, waehrend die interaktive Windows- Veeam nutzt gespeicherte Job-Credentials, waehrend die interaktive Windows-
Sitzung zusaetzlich per `net use` authentifiziert werden muss. Sitzung zusaetzlich per `net use` authentifiziert werden muss.
## Offene Punkte ## Verbleibende Optionen
- Entscheiden, ob Veeam Storage Encryption nachtraeglich aktiviert werden soll.
Wenn ja: Passwort in Vaultwarden anlegen, Job umstellen und ein neues Full-
Backup erzeugen.
- Optional: BitLocker C: separat aktivieren und Recovery-Key an den drei
vorgesehenen Orten sichern.
- Optional: spaeter dedizierten SMB-User `veeam-baerchen` anlegen, falls die - Optional: spaeter dedizierten SMB-User `veeam-baerchen` anlegen, falls die
Unraid-User-/Share-Policy wieder angefasst wird. Unraid-User-/Share-Policy wieder angefasst wird.
- Veeam Storage Encryption und BitLocker sind keine offenen Entscheidungen mehr;
beide bleiben bewusst deaktiviert und werden nur bei neuem Risiko-/Ablageprofil
erneut bewertet.