Files
homelab-infra/docs/AUDIT_2026-05-25.md
T

57 KiB
Raw Blame History

Homelab-Audit KalliLab CORE

Stand: 2026-05-25 Methode: Repo-basierter Audit auf master (lokaler Clone). Keine Live-Messung gegen den Host. Querverweise auf Audit-Live-Daten aus docs/AUDIT_2026-05-23_LIVE.md, wo verfuegbar. Auftrag: externer, kritischer Audit-Blick zusaetzlich zur internen docs/STRATEGISCHE_BEWERTUNG_2026-05-23.md.

Wichtige Vorbemerkung

Es gibt seit dem 23.05. eine fundierte interne Bewertung (docs/STRATEGISCHE_BEWERTUNG_2026-05-23.md) und eine konsolidierte Hausaufgabenliste (docs/CODEX_KONSOLIDIERUNG_2026-05-23.md). Davon wurden seit dem 25.05. bereits umgesetzt:

  • Jellyfin entfernt (MASTER 7.8)
  • Homepage entfernt (MASTER 7.8)
  • Uptime-Kuma entfernt (MASTER 7.8, SECRETS_MAP 29)
  • Monitoring-Stack produktiv (AUDIT_FINAL 9), Altstaende-Container down
  • Disk1 NTFS -> XFS Phase 2 abgeschlossen am 2026-05-25 (STORAGE_LAYOUT 3)
  • Unraid-Flash-Backup live (unraid-flash-config.tar.gz im Borg-Lauf)
  • GitHub-Push-Mirror michaelkaleschke-spec/homelab-infra aktiv (DR 10, MASTER 7.1)

Diese geloesten Punkte werden hier nicht wiederholt. Dieser Audit konzentriert sich auf das, was nach dem 23.05.-Sprint noch offen ist und auf das, was die strategische Bewertung nicht oder nur kurz angerissen hat.


Phase 1: Repo-Inventar

Ordnerstruktur (Ist-Zustand)

homelab-infra/
├── apps/          9 Stacks (bentopdf, immich, mail-archiver, mealie, nextcloud, ntfy, paperless, paperless-gpt, unbound)
├── core/          1 Stack (gitea)
├── docs/          28 Markdown-Dokumente
├── env/           2 *.example
├── host-services/ 3 Stacks (Adguard, plex, tailscale)
├── infra/         3 Stacks (ddns-updater, postgresql17, redis)
├── monitoring/    1 Compose mit 10 Services + Provisioning
├── ops/           17 Verzeichnisse (Semaphore, borg-ui, code-server, filebrowser, glance, glances, grafana-influxdb [Altstand], hermes-agent, komodo, loki [Altstand], policy-checks, restore-tests, scrutiny, speedtest, uptime-kuma [Altrest], windows-reinstall)
├── security/      2 Stacks (authelia, vaultwarden)
├── services/      1 posture-check (Host-Skripte)
└── traefik/       1 Compose + dynamic/ (3 Files)

Inventar-Befund:

  • ~30 Compose-Dateien, 1 zentraler Compose-Multi-Service (monitoring/).
  • 29 Composes wurden vom Policy-Checker validiert (ops/policy-checks/last-report.md): 0 Critical, 4 Warnings, 9 Info.
  • Doku-Dichte ist hoch (REPO_MAP, SERVICE_CATALOG, RESTORE_MATRIX, DISASTER_RECOVERY, SECRETS_MAP, WORKFLOW, STORAGE_LAYOUT, GITOPS_DRIFT_RUNBOOK, ALERTING_MAP).
  • Restore-Tests sind als echte Scripts versioniert (ops/restore-tests/). Ueberdurchschnittlich.

Gut dokumentierte Bereiche (Belegt)

Bereich Quelle
Architektur, Netze, Ausnahmen HOMELAB_ARCHITECTURE_MASTER_V2.md
GitOps-Workflow, Drift docs/WORKFLOW.md, docs/GITOPS_DRIFT_RUNBOOK.md
Backup-Scope, Restore-Wege, Tier-Modell docs/RESTORE_MATRIX.md, docs/DISASTER_RECOVERY.md, ops/borg-ui/BACKUP_SCOPE.md
Storage / Cache-Policy / FS / Posture docs/STORAGE_LAYOUT.md (zum Audit-Zeitpunkt noch docs/STORAGE_LAYOUT.draft.md)
Secret-Inventur docs/SECRETS_MAP.md
Alert-Pfade docs/ALERTING_MAP.md

Luecken / Unklar (vermutet bzw. Rueckfrage noetig)

Luecke Warum es ein Audit-Loch ist
docs/STORAGE_LAYOUT.draft.md ist Draft 1.3, nicht Active Stand zum Audit-Zeitpunkt 2026-05-25: mehrere Hard Rules (12 Constitution) galten formal noch nicht. Hard Rule 11 (kein Stack ohne Restore-Pfad in RESTORE_MATRIX) wurde schon eingehalten — also nur Formal-Luecke. Folgearbeit: als docs/STORAGE_LAYOUT.md Active heben.
docs/SERVICES_RECOVERY.md ist als verbindlich angekuendigt (STORAGE_LAYOUT 4), aber nicht im Repo Konkrete Mirror-Mechanik fuer services/gitea/git/repositories/ ≤ 6 h ist nirgends spezifiziert.
Hardware-Inventar: kein zentrales Dokument Keine Stelle im Repo nennt CPU-Modell, RAM-Groesse, NIC-Speed, Mainboard, Parity-Disk-Groessen — nur "Samsung 970 EVO Plus 2 TB" steht in STORAGE_LAYOUT 3.
USV: keine Erwaehnung Keine Datei nennt eine USV. Unklar, ob vorhanden.
Familien-/User-Onboarding-Doku Keine Doku, die deine Frau/Kinder lesen muessten ("So loggst du dich in Nextcloud ein"). Aktuell ist alles Operator-Doku.

Fuer den Audit besonders wichtige Dateien (verwendet)

  • HOMELAB_ARCHITECTURE_MASTER_V2.md — komplett
  • docs/WORKFLOW.md, docs/REPO_MAP.md, docs/SERVICE_CATALOG.md — komplett
  • docs/DISASTER_RECOVERY.md, docs/RESTORE_MATRIX.md, docs/SECRETS_MAP.md — komplett
  • docs/STORAGE_LAYOUT.md (zum Audit-Zeitpunkt docs/STORAGE_LAYOUT.draft.md), docs/STRATEGISCHE_BEWERTUNG_2026-05-23.md — komplett
  • docs/AUDIT_2026-05-23_LIVE.md, docs/AUDIT_2026-05-23_FINAL.md
  • ops/policy-checks/last-report.md
  • monitoring/docker-compose.yml, monitoring/prometheus/alerts.yml
  • traefik/docker-compose.yml, traefik/dynamic/middlewares.yml
  • security/authelia/configuration.yml, security/authelia/docker-compose.yml
  • apps/paperless/docker-compose.yml, apps/immich/docker-compose.yml, apps/nextcloud/docker-compose.yml
  • host-services/Adguard/docker-compose.yml

A. Executive Summary

Was schon stark ist:

  • GitOps-Disziplin: Gitea als Sollzustand, Komodo als Consumer, dokumentierter Drift-Runbook, Stop-Regel ("zwei Fehlversuche -> Pflichtmatrix"). Seltene Reife.
  • Backup-Architektur: Pre-Backup-Dumps + Borg + Restore-Tests mit echtem Smoke-Test-Kriterium ("Container startet ≠ Erfolg"). 15 frische Dumps < 24 h alt (AUDIT_LIVE 9.4).
  • Architektur-Klarheit: frontend_net / backend_net / app-interne Netze, keine Sammelnetze, dokumentierte Ausnahmen.
  • Image-Pinning: Tier-1-Stateful mit <minor>@sha256:.... Konsequent durchgezogen.
  • Secrets-Hygiene: Keine Secret-Werte im Repo, _FILE-Mounts + Komodo Stack ENV, explizit dokumentierte Ausnahmen.
  • Policy-as-Code: check_repo.ps1 mit 0 Critical und sauber dokumentierten Exceptions.

Was kritisch ist:

  • AdGuard Admin-Port 8082 ohne Authelia/2FA am LAN gebunden (host-services/Adguard/docker-compose.yml:16) — dokumentierte "Operator-Entscheidung" 2026-05-25. Im Heim-LAN tolerierbar, mit IoT/Gaeste-WLAN potenziell ein Pfad zur DNS-Manipulation. Niedrigster Aufwand: Bind nur auf Tailscale-Interface.
  • Authelia ACL: 2FA nur fuer files.kaleschke.info und scrutiny.kaleschke.info (security/authelia/configuration.yml:44-48). Borg-UI, Code-Server, Filebrowser, Glance — alles nur one_factor. Bei Pwd-Kompromittierung des Operator-Accounts ist Borg-UI + Code-Server der direkteste Pfad zur Datenexfiltration.
  • Authelia-Repo-Baseline ↔ Host-Config-Drift "by design" (docs/REPO_MAP.md:48, SERVICE_CATALOG 23). User-DB, OIDC-Clients und Secrets sind hostseitig, Manual-Merge-Pflicht. Stelle, an der Drift mit Anlauf passiert.
  • Komodo Self-Bootstrap-Problem ist nur dokumentiert, nicht geloest (MASTER 13: Self-Stack Drift-Recovery 2026-05-04). Bei Recovery vom kalten Host musst du Komodo aus compose.yaml neu erzeugen — dafuer brauchst du die .env mit KOMODO_*-Secrets, die nur auf Host und ggf. Vaultwarden liegen.
  • Backup-Off-Site-Diversitaet: BorgBase Hetzner ist Single-Provider; Borg-Passphrase analog gesichert ist als TODO markiert (docs/DISASTER_RECOVERY.md:64,401). Wenn Hetzner-Account verloren geht, ist das halbe DR-Versprechen weg.

Was unnoetig komplex ist:

  • Drei dokumentierte Monitoring-/Logging-Pfade gleichzeitig im Repo: ops/grafana-influxdb (Altstand), ops/loki (Altstand), monitoring/ (Ziel). Die Altstaende sind als Container down, aber Verzeichnisse noch im Repo — Doppelpflege-Risiko. Der versprochene Repo-Cleanup (git rm) fehlt.
  • Hermes-Agent: NAS-Stack bewusst deaktiviert ("VM-seitig offen"), aber Stack-Verzeichnis und Compose mit Dashboard-Domain bleiben im Repo. Mehr "Schwebezustand" als operativer Wert.
  • BentoPDF: "vorbereitet", noch nie produktiv abgenommen (SERVICE_CATALOG 52, MASTER 7.5).
  • infra/redis ist als shared Cache deklariert, wird de facto nur von Paperless genutzt (Authelia nicht, Immich/Nextcloud/Mealie haben eigene Redis). Das "shared" stimmt im Repo nicht mit der Realitaet ueberein.

Groesster Hebel:

Authelia OIDC-Provider aktivieren — wenn Nextcloud, Immich, Grafana (und perspektivisch Mealie via OIDC-Bridge) per SSO laufen, gewinnst du gleichzeitig:

  • (a) Familien-Onboarding-Komfort (ein Login),
  • (b) zentrale Brute-Force-Regulation und Audit,
  • (c) Voraussetzung fuer sinnvolles CrowdSec/Fail2Ban,
  • (d) zentrale 2FA-Pflicht statt App-by-App.

Das ist ein Sprint, nicht ein Quartal, und macht aus deinem "Admin-Authelia" ein echtes Identity-System.

Was ein erfahrener Homelabber sofort aendern wuerde:

  1. AdGuard-Admin-Port nur auf Tailscale-Interface binden (5 Min, Compose-Edit).
  2. Borg-Passphrase auf Papier in Bankschliessfach (15 Min, off-system).
  3. scrutiny und ddns-updater no-new-privileges Warning aufraeumen (10 Min) — kosmetisch, aber Policy-Check sollte clean sein.
  4. Altstaende ops/grafana-influxdb/ und ops/loki/ aus Repo entfernen (Backup-Branch dann git rm).
  5. Renovate-Bot gegen Gitea einrichten — beendet manuelle Digest-Pflicht.

B. Scorecard (1 = exzellent, 10 = ungenuegend)

Bereich Note Begruendung
Hardware nicht bewertbar Keine Inventar-Doku im Repo. Nur Cache-NVMe genannt. Siehe Phase H.
Ordnerstruktur 2 Klare Trennung apps/infra/ops/security/core; konsistente Namenskonvention (mit Migrationsplan in STORAGE_LAYOUT 6). Kleinerer Haenger: host-services/Adguard/ mit Grossbuchstabe.
Storage 3 (Repo-Stand) / 2 (mit STORAGE_LAYOUT Active) Cache-XFS, Disk1-XFS jetzt erreicht. Pfad-Disziplin via /mnt/user/.... Posture-Check etabliert. Note durch Draft-Status und fehlendes SERVICES_RECOVERY.md gedrueckt.
Docker-Architektur 2 Netzmodell klar, Healthchecks fehlen grossflaechig, latest@sha256 als bewusster Kompromiss bei einigen Images dokumentiert. Keine Memory-Limits.
Reverse Proxy / Zugriff 2 DNS-Challenge, Wildcard-faehig, Authelia ForwardAuth, dynamic config sauber getrennt. Manuelle Host-Sync-Ausnahme ist pragmatisch.
Security 3 Solides Fundament (Authelia Argon2id, no-new-privileges-Standard, Webhook-Allowlist, cloudflare_dns_api_token als Docker Secret), aber: nur 2 Domains mit 2FA, AdGuard-Admin direkt am LAN, kein WAF/Bouncer, Authelia Regulation 5-Min-Ban ist gentil.
Netzwerk / DNS 2 AdGuard + Unbound + Tailscale-Trias ist Best-of-Class-Homelab. FritzBox als Router nicht im Repo dokumentiert, daher Note nicht 1.
Backup 2 Borg, Pre-Dumps, Tier-Modell, dokumentierter Scope. Punkt-Abzug: Single-Provider Off-Site, Passphrase nicht analog, Komodo-Mongo-Dump-Verifikation nicht im Auto-Cron.
Restore-Faehigkeit 2 RESTORE_MATRIX mit Smoke-Test je Dienst, Restore-Test-Schedule + Validierungen fuer Vaultwarden/Gitea/Paperless dokumentiert. Punkt-Abzug: Immich-Restore noch nie geuebt — groesster Datentopf.
GitOps 1-2 Webhook-Pflicht fuer neue Stacks, Source-of-Truth-Hierarchie, Drift-Runbook. Self-Bootstrap-Problem von Komodo zieht von 1 auf 2.
Monitoring 3 Stack produktiv, aber Altstaende noch im Repo, Family-View-Dashboard fehlt, Alerts (alerts.yml) sehr knapp (5 Regeln), keine Cert-Expiry-Alert auf Prometheus-Ebene (Cert-Token-Check laeuft separat).
Dokumentation 1 Aussergewoehnlich. SERVICE_CATALOG ist Gold. Einziger Punkt: kein End-User-/Familien-Onboarding.
Automatisierung 3 Borg-Dumps automatisiert, posture-check Host-Cron, Alert->ntfy-Pipe. Aber: keine CI gegen Repo, kein Renovate, kein automatisches Image-Update-Tracking.
Wartbarkeit 2 Doku traegt; Sprintpflege-Disziplin sichtbar (MIGRATION_LOG, AUDIT_FINAL). Risiko: Authelia-Drift, Hermes-Schwebezustand.
Nerd-Faktor 2- Komodo + Borg-UI + ntfy-Bridge + Posture-Check + Restore-Lab + Hermes-Experiment + Push-Mirror + Digest-Pinning. Liegt zwischen "Solider Senior" und "Spielwiese halten lernen".

Gesamteindruck: 2 (gut). Strukturell weit ueber durchschnittlichem Homelab; konkrete Luecken sind klar benennbar und nicht systemisch.


C. Top-20 Findings

Format: priorisiert nach Risiko-zu-Aufwand-Hebel. Jeder Eintrag hat Fundstelle, Empfehlung und Prio.

F-01 · AdGuard-Admin am LAN ohne Auth

  • Kategorie: Security / Zugriff
  • Fundstelle: host-services/Adguard/docker-compose.yml:16, MASTER 10, docs/SERVICE_CATALOG.md:14
  • Beobachtung: Port 8082:80 direkt auf alle Interfaces. Bewusste Operator-Entscheidung 2026-05-25.
  • Risiko: Jedes Geraet im LAN kann DNS-Filterregeln, Upstream und Logging manipulieren. IoT-Kompromittierung oder Gast-WLAN -> DNS-Hijack moeglich.
  • Best Practice: Admin-UIs nicht im LAN ohne Auth. Entweder hinter Traefik+Authelia mit two_factor oder Bind auf Tailscale-Interface (z. B. 100.x.y.z:8082:80).
  • Empfehlung: Schritt 1 — Bind auf Tailscale-IP (S, 5 Min). Schritt 2 — optional spaeter Traefik-Route hinter Authelia.
  • Prioritaet: Sollte zeitnah
  • Aufwand: S
  • Validierung: ss -ltnp | grep :8082 zeigt nur Tailscale-IP; LAN-Browser-Zugriff schlaegt fehl.
  • Rollback: Compose-Diff zurueck, Komodo redeploy.

F-02 · Borg-Passphrase nicht analog gesichert

  • Kategorie: Backup / DR
  • Fundstelle: docs/DISASTER_RECOVERY.md:64,401, docs/SECRETS_MAP.md:48
  • Beobachtung: borg_repo_passphrase.txt liegt im Host-Filesystem unter /mnt/user/appdata/secrets/. Doku weist explizit darauf hin, dass eine externe analoge Sicherung Operator-Aufgabe ist.
  • Risiko: Wenn Unraid-Host und ggf. Vaultwarden gleichzeitig defekt sind, ist das verschluesselte Borg-Repo bei Hetzner nutzlos.
  • Empfehlung: Auf Papier ausdrucken, in Bankschliessfach oder bei vertrauter Person versiegelt. Zusaetzlich in Vaultwarden hinterlegen (aber Vaultwarden hilft nicht, wenn es selbst restauriert werden muss).
  • Prioritaet: Muss sofort
  • Aufwand: S
  • Validierung: Du kannst den Wert ohne Host wiederherstellen.

F-03 · Single-Provider Off-Site Backup

  • Kategorie: Backup
  • Fundstelle: ops/borg-ui/BACKUP_SCOPE.md, docs/RESTORE_MATRIX.md:77-96, STORAGE_LAYOUT 8.1
  • Beobachtung: Hetzner Storage Box als alleiniges Off-Site-Borg-Ziel. STORAGE_LAYOUT 8.1 sieht zusaetzlich lokales Borg-Repo auf /mnt/user/backups/borg/ vor (gleicher Host) und eine externe Wechselplatte (manuell rotiert).
  • Risiko: Hetzner-Account-Verlust (Payment-Issue, Account-Hack, Provider-Outage) = halbes 3-2-1.
  • Best Practice: Zweites Off-Site-Ziel mit unterschiedlichem Provider oder Cold-Wechselplatte mit fester Rotationskadenz.
  • Empfehlung: (a) Wechselplatten-Rotation in fester Kadenz dokumentieren (zwei Platten, monatlicher Tausch). Oder (b) zweites Borg-Repo bei rsync.net / BorgBase EU2 / privatem 2. Standort.
  • Prioritaet: Sollte zeitnah
  • Aufwand: M
  • Validierung: borg list gegen beide Repos, beide < 7 Tage alt.

F-04 · Authelia 2FA-Pflicht zu schmal

  • Kategorie: Security
  • Fundstelle: security/authelia/configuration.yml:44-53
  • Beobachtung: Nur files.kaleschke.info und scrutiny.kaleschke.info sind two_factor. Tier-1-Operator-UIs wie Borg-UI, Code-Server, Filebrowser (zweite Route?), Komodo (eigene Auth), Glance, Grafana laufen mit one_factor.
  • Risiko: Operator-Passwort-Kompromittierung (Phishing, Keylogger, Browser-Save-Leak) gibt ohne 2FA Vollzugriff auf Code-Server (Repo + Workspace), Borg-UI (Restore-Pfade), Filebrowser (Documents/Photos).
  • Empfehlung: ACL erweitern: two_factor fuer borg.kaleschke.info, code.kaleschke.info, files.kaleschke.info (schon), glance.kaleschke.info (debattierbar), traefik.kaleschke.info. Komodo bleibt Ausnahme.
  • Prioritaet: Muss sofort
  • Aufwand: S
  • Validierung: Nach Login auf borg.kaleschke.info wird 2FA-Prompt erzwungen.
  • Rollback: ACL-Block zurueck.

F-05 · Repo-Altstaende ops/grafana-influxdb/ und ops/loki/ nicht entfernt

  • Kategorie: Wartbarkeit / GitOps
  • Fundstelle: Repo-Wurzeln ops/grafana-influxdb/, ops/loki/; MASTER 7.6, SERVICE_CATALOG 68-70,80-81, AUDIT_FINAL 9
  • Beobachtung: Container down, aber Compose-Dateien + Provisioning bleiben im Repo. Doku referenziert beide gleichzeitig. Risiko: jemand (zukuenftiges Ich, KI) deployt versehentlich den Altstand.
  • Empfehlung: git rm der beiden Verzeichnisse, Tag pre-monitoring-cleanup fuer Rollback, MIGRATION_LOG-Eintrag.
  • Prioritaet: Sollte zeitnah
  • Aufwand: S
  • Validierung: policy-checks laeuft clean, Repo enthaelt nur noch monitoring/.

F-06 · Hermes-Agent im Schwebezustand

  • Kategorie: App-Landschaft / Wartbarkeit
  • Fundstelle: ops/hermes-agent/docker-compose.yml, MASTER 7.5, SERVICE_CATALOG 82-83
  • Beobachtung: "NAS-Stack bewusst deaktiviert" wegen offener VM-Seite. Dashboard-Domain (hermes.kaleschke.info) + Authelia-ACL + Secret-Pfade dokumentiert.
  • Risiko: Schleichender Verfall — in 6 Monaten verstehst du Model-C nicht mehr ohne ops/hermes-agent/README.md. Bei jeder Authelia-/Compose-Aenderung musst du Hermes mitpruefen, obwohl es nichts tut.
  • Empfehlung: Operator-Entscheidung mit 60-Tage-Deadline ehrlich treffen. Wenn nicht produktiv bis 2026-07-25: git rm ops/hermes-agent/, Domain aus DNS, ACL-Eintrag raus.
  • Prioritaet: Sollte zeitnah (Entscheidung)
  • Aufwand: S (Entfernen) / L (echte Produktiv-Aktivierung)
  • Validierung: Entweder Smoke-Test auf hermes.kaleschke.info mit funktionalem Use-Case-Beleg, oder Repo-clean.

F-07 · Monitoring-Stack ohne Digest-Pin

  • Kategorie: Reproduzierbarkeit / GitOps
  • Fundstelle: monitoring/docker-compose.yml:3,28,66,84,100,118,276,296
  • Beobachtung: Prometheus, Alertmanager, Blackbox, Loki, Promtail, Grafana, node-exporter, cAdvisor sind alle nur per Tag gepinnt (prom/prometheus:v3.7.3, grafana/grafana:12.4.3, ...). Nur influxdb3-core hat @sha256:. Das widerspricht der Image-Versionierungs-Disziplin der Tier-1-Stateful-Dienste.
  • Risiko: Wenn upstream einen Tag erneut pushed (Versionsdrift, Supply Chain), wird beim Rebuild ein anderer Container deployed — gerade Monitoring sollte stabil sein.
  • Empfehlung: Beim naechsten Komodo-Redeploy aktuellen Digest auslesen und einpinnen. Vorbereitung fuer Renovate (F-12).
  • Prioritaet: Nice to have
  • Aufwand: S
  • Validierung: grep '@sha256' monitoring/docker-compose.yml listet alle 10 Services.

F-08 · Alert-Regeln zu duenn

  • Kategorie: Monitoring
  • Fundstelle: monitoring/prometheus/alerts.yml
  • Beobachtung: Exakt 5 Regeln: ExternalConnectivityDown, EndpointDown, EndpointSlow, DiskAlmostFull, MemoryHighUsage, Traefik5xx. Es fehlen:
    • Borg-Lauf-Frische (ueber node_exporter textfile collector oder Pushgateway).
    • Zertifikatslaufzeit (Blackbox kann probe_ssl_earliest_cert_expiry, aber keine Alert-Regel dafuer).
    • Container-down-Alert (cAdvisor liefert container_last_seen).
    • PostgreSQL-Connection-Saturation.
    • Loki ingestion-rate / log-volume spike.
    • InfluxDB-Disk-Pressure.
    • Backup-Job-Failure.
  • Risiko: Du siehst Probleme nicht, bevor sie weh tun. Cert-Expiry und Borg-Stale sind die schmerzhaftesten Blind-Spots.
  • Empfehlung: Mindestens zwei Regeln nachziehen: BorgArchiveStale (>30 h, Pushgateway oder textfile) und TLSCertExpiryNear (<14 Tage). Rest als Folge-Sprint.
  • Prioritaet: Sollte zeitnah
  • Aufwand: M
  • Validierung: Alerts feuern in Test-Bedingung (Borg-Dump-File touch -d backwards).

F-09 · Komodo-Self-Bootstrap-Problem

  • Kategorie: GitOps / DR
  • Fundstelle: MASTER 13: Komodo Self-Stack Drift-Recovery 2026-05-04
  • Beobachtung: Du hattest schon einen Drift-Vorfall (Komodo-Core ran aus /tmp/*repair.yml, Mongo-Pfad fehlte). Recovery-ENV liegt als "temporaeres Tier-1-Secret-Material" unter /mnt/user/appdata/secrets/_komodo_stack_env_recovery_2026-05-04.env (Doku-Stand).
  • Risiko: Bei Totalausfall musst du Komodo aus Compose-Datei wiederbeleben, dafuer brauchst du die Stack-ENV mit KOMODO_SECRET_KEY, KOMODO_MONGO_PASSWORD, KOMODO_PERIPHERY_PASSKEY etc., die nur als Komodo Stack ENV existieren. Klassisches Henne-Ei.
  • Empfehlung: Komodo-Self-Stack aus Komodos eigener Verwaltung herausnehmen und als handgepflegten docker compose-Service in services/komodo-bootstrap/ halten. Stack-ENV als versiegelte Datei unter /mnt/user/appdata/secrets/ mit deterministischem Restore-Pfad in RESTORE_MATRIX.
  • Prioritaet: Sollte zeitnah
  • Aufwand: M
  • Validierung: Komodo-Stack-Datei lebt im Repo unter services/, nicht in Komodos eigener Workspace-Sicht.

F-10 · Authelia Repo↔Host Drift "by design"

  • Kategorie: GitOps / Security
  • Fundstelle: docs/REPO_MAP.md:48, security/authelia/configuration.yml, SERVICE_CATALOG 23
  • Beobachtung: Repo enthaelt Baseline ohne Secrets, OIDC, Users-DB. Manuelles Merge auf den Host noetig. Es gibt keine automatische Konsistenz-Pruefung.
  • Risiko: Repo-Aenderung (z. B. neue ACL-Regel) wird gepusht, aber nie auf den Host gemerged -> Drift, Authelia hinkt der Wahrheit hinterher.
  • Empfehlung: Symmetrisch zum Traefik-Dynamic-Workflow (manueller Sync explizit als Pflicht in WORKFLOW.md). Zusaetzlich ein einfaches Diff-Script services/authelia-diff.sh, das diff zwischen Repo-Baseline und Host-Datei zeigt, und das im posture-check als Warning auftaucht, wenn die ACL-Sektion differiert.
  • Prioritaet: Sollte zeitnah
  • Aufwand: S
  • Validierung: Script laeuft, posture-check kennt einen neuen Check authelia_config_drift.

F-11 · Immich-Restore noch nie geuebt

  • Kategorie: Backup / Restore
  • Fundstelle: docs/RESTORE_MATRIX.md:49, Restore-Test-Schedule
  • Beobachtung: Vaultwarden / Gitea / Paperless haben Mini-Restore-Tests (2026-05-07). Immich nicht. Immich ist der groesste Datentopf (Familien-Fotos).
  • Risiko: Silent Corruption in Postgres-pgvecto-rs-Daten bemerkst du erst beim Restore-Versuch.
  • Empfehlung: Eigener Sprint: Immich-Restore-Test gegen /mnt/user/backups/restore-lab/immich/ mit Sub-Set der immich.dump und einem Foto-Sample. Smoke-Test = "10 Fotos im Browser sichtbar nach Restore".
  • Prioritaet: Sollte zeitnah
  • Aufwand: M
  • Validierung: Report unter /mnt/user/backups/restore-reports/immich-<datum>.json.

F-12 · Keine Image-Update-Automatik (Renovate o. ae.)

  • Kategorie: Wartbarkeit
  • Fundstelle: Repo-weit; docs/WORKFLOW.md:282-288 (Image-Versionierung)
  • Beobachtung: Digest-Pinning ist konsequent, aber rein manuell. Bei ~30 Images bedeutet das, du musst monatlich fuer Patch-Updates manuell Digests auslesen — oder es bleibt liegen.
  • Risiko: CVE-Patches werden nicht eingespielt, weil "der laufende Stand ist stabil".
  • Empfehlung: Renovate Bot (self-hosted, gegen Gitea), Gitea-Actions-Runner. Renovate oeffnet PRs fuer Patch-/Minor-Updates; Major-Updates werden mit Labels separiert.
  • Prioritaet: Sollte zeitnah (oder Nice to have, je nach Schmerz)
  • Aufwand: M (Initial-Setup ist substantiell)
  • Validierung: Renovate hat erste PRs in Gitea geoeffnet, du mergst eines davon kontrolliert.

F-13 · Keine OIDC-SSO fuer User-Apps

  • Kategorie: Security / UX
  • Fundstelle: security/authelia/configuration.yml, docs/SECRETS_MAP.md
  • Beobachtung: Authelia kann OIDC, ist aber nur als ForwardAuth konfiguriert. Nextcloud, Immich, Grafana, Mealie laufen mit eigenen User-DBs.
  • Risiko: N getrennte Passwortspeicher, N getrennte 2FA-Setups, keine zentrale Sperrung bei Account-Kompromittierung. Familie hat keinen einfachen Onboarding-Pfad.
  • Empfehlung: OIDC-Provider in Authelia aktivieren, Nextcloud (via Plugin), Immich (nativer OIDC-Support), Grafana (nativer OIDC-Support) als Clients konfigurieren. Vaultwarden via OIDC-Bridge nur, wenn der Aufwand klar mehrwertig ist — sonst bewusst auslassen.
  • Prioritaet: Sollte zeitnah (groesster Hebel laut Executive)
  • Aufwand: L
  • Validierung: Familienkonto kann sich mit einem Login bei Nextcloud + Immich + Grafana anmelden.

F-14 · Kein WAF / Bouncer vor oeffentlichen Apps

  • Kategorie: Security
  • Fundstelle: traefik/docker-compose.yml, oeffentliche Hosts in docs/REPO_MAP.md:127-152
  • Beobachtung: Sechs oeffentliche Apps mit nativer Auth (vault, paperless, mealie, ntfy, git, immich, cloud) ohne IP-Bouncer. Authelia-Regulation greift nur fuer die ForwardAuth-Pfade; Apps mit eigener Auth bekommen den vollen Traffic.
  • Risiko: Credential-Stuffing-Bot-Wellen treffen die App selbst (Nextcloud, Immich) — Logs sind im Loki, aber kein Sperr-Mechanismus.
  • Empfehlung: CrowdSec als Bouncer fuer Traefik (crowdsecurity/traefik-bouncer). Nutzt Loki/Logs fuer Erkennung, sperrt IPs auf Traefik-Ebene, bevor sie die Apps treffen.
  • Prioritaet: Sollte zeitnah
  • Aufwand: M
  • Validierung: CrowdSec-Dashboard zeigt erste Sperren; Test-Brute-Force gegen nextcloud.kaleschke.info wird bei N Versuchen geblockt.

F-15 · Healthchecks fehlen grossflaechig

  • Kategorie: Docker / Operations
  • Fundstelle: Spot-checks: apps/paperless/docker-compose.yml, apps/immich/docker-compose.yml, security/authelia/docker-compose.yml, traefik/docker-compose.yml — keiner hat healthcheck:-Block.
  • Beobachtung: Restart-Policy ist ueberall unless-stopped, aber ohne Healthcheck kann Docker keinen Crash-Loop bei "Container laeuft, aber App tot" erkennen.
  • Risiko: Bei Soft-Failure (Postgres-Connection-Pool tot, Authelia haengt im Storage-Connect) merkst du nichts, weil Container "running" bleibt.
  • Empfehlung: Fuer Tier-1 (Traefik wget /ping, Authelia /api/health, PostgreSQL pg_isready, Komodo wget /api/healthcheck) Healthchecks ergaenzen. Fuer Tier-2 schrittweise.
  • Prioritaet: Sollte zeitnah
  • Aufwand: M (pro Stack 515 Min)
  • Validierung: docker ps zeigt (healthy) neben den Tier-1-Containern.

F-16 · infra/redis als "shared" deklariert, faktisch nur Paperless

  • Kategorie: Architektur-Konsistenz
  • Fundstelle: infra/redis/docker-compose.yml, docs/SERVICE_CATALOG.md:31 ("shared Redis Cache")
  • Beobachtung: Immich, Nextcloud, Mealie haben jeweils eigene Redis-Instanzen. Authelia nutzt bewusst kein Redis (MASTER 13). Paperless nutzt es laut Compose. Effektiv "Paperless-Redis im Frack des shared-Caches".
  • Risiko: Niedrig. Aber: Wenn du infra/redis fuer etwas anderes wegnimmst, denkst du, es kostet Paperless was — und das waere der Fall.
  • Empfehlung: Doku-Update: SERVICE_CATALOG 31 praezisieren ("dediziertes Redis fuer Paperless; andere Stacks haben eigene Redis-Instanzen"). Architektur bleibt, nur Etikett ehrlich machen. Alternativ: in apps/paperless/ als App-internes Netz konsolidieren wie Mealie.
  • Prioritaet: Nice to have
  • Aufwand: S (Doku) / M (Architektur)

F-17 · Plex bleibt als Host-Net-Stack

  • Kategorie: Security / Architektur
  • Fundstelle: host-services/plex/docker-compose.yml, MASTER 7.4
  • Beobachtung: Plex laeuft als Host-Net wegen Discovery/GDM. Dokumentierte Ausnahme.
  • Risiko: Plex hat hoehere Angriffsoberflaeche als Apps mit Traefik. Plex-Login wurde mehrfach Ziel von Account-Uebernahmen (Plex.tv-Auth-Issues 2024/25). Bei Plex.tv-Kompromittierung greift Authelia nicht — Plex authentifiziert gegen Plex.tv.
  • Empfehlung: Plex bewusst beibehalten (Doku stuetzt), aber: (a) "Remote Access" in Plex-UI deaktivieren, wenn nur lokal/Tailscale genutzt. (b) Plex-Server nicht in frontend_net (waere schaedlich) — bleibt Host-Net, korrekt.
  • Prioritaet: Nice to have
  • Aufwand: S
  • Validierung: Plex Remote Access UI zeigt "disabled".

F-18 · Nextcloud ohne ForwardAuth, ohne dedizierte Brute-Force-Doku

  • Kategorie: Security
  • Fundstelle: apps/nextcloud/docker-compose.yml, MASTER 13: Nextcloud-Entscheidung
  • Beobachtung: Bewusste Ausnahme (WebDAV/CardDAV). In Nextcloud selbst sind Brute-Force-Schutz, 2FA-Pflicht und App-Passwords konfigurierbar, aber nicht im Repo dokumentiert.
  • Risiko: Familien-Konto mit schwachem Passwort + Nextcloud oeffentlich = direkter Pfad zu Dokumenten/Fotos.
  • Empfehlung: apps/nextcloud/POST_INSTALL.md mit Pflicht-Checkliste: Brute-Force-Plugin aktiv, 2FA-Provider TOTP installiert, Admin-Account hat 2FA, "Enforce 2FA for admin group" gesetzt. Optional: OCC-Befehle als Skript in services/nextcloud-policy/.
  • Prioritaet: Sollte zeitnah
  • Aufwand: S
  • Validierung: Test-Login ohne 2FA als Admin schlaegt fehl.

F-19 · Keine Container-Memory-Limits

  • Kategorie: Docker / Hardware-Schutz
  • Fundstelle: Spot-checks aller Composes
  • Beobachtung: Keine mem_limit: oder deploy.resources.limits Sektion in Tier-1- oder Tier-2-Stacks.
  • Risiko: Bei Image-Bug oder Memory-Leak (z. B. Immich-ML, Paperless-OCR-Loop) kann ein Container den Host in OOM treiben. Posture-Check + Docker-Critical-Events sehen das nachher, aber praeventiver waere Container-Limit + Docker-OOM-Kill fuer den richtigen Prozess.
  • Empfehlung: Fuer Tier-1 (Postgres, Authelia, Traefik, Komodo) sanfte Limits setzen (z. B. Postgres 2 GB, Authelia 256 MB, Traefik 256 MB). Fuer Immich-ML-Container ein hartes Limit, das Verhungern verhindert.
  • Prioritaet: Nice to have
  • Aufwand: M
  • Validierung: docker stats zeigt MEM USAGE / LIMIT ungleich unlimited.

F-20 · Paperless-DBPass weiter als Stack-ENV (dokumentierte Ausnahme)

  • Kategorie: Secrets
  • Fundstelle: MASTER 13: Secrets in Komodo Stacks, docs/SECRETS_MAP.md:25
  • Beobachtung: Paperless unterstuetzt _FILE nicht fuer DB-Pass. Bewusste Ausnahme.
  • Risiko: Stack-ENV liegt in Komodo-DB (Mongo), nicht im Repo. Bei Komodo-Mongo-Backup-Luecke fehlt das Passwort beim Restore.
  • Empfehlung: Erweiterung der Disaster-Recovery-Doku: explizite Liste aller "Stack-ENV-only"-Secrets mit Zeiger, dass komodo-mongo.archive.gz fuer Restore zwingend ist, oder die ENV manuell vorgehalten werden muss (in Vaultwarden + externer Notiz).
  • Prioritaet: Nice to have
  • Aufwand: S
  • Validierung: DR-Doc Abschnitt "Stack-ENV-Werte" referenziert konkrete Restore-Pfade.

D. Risiko-Matrix

Risiko Bereich Wahrscheinlichkeit Auswirkung Prioritaet Massnahme
Borg-Passphrase weg -> Restore unmoeglich Backup niedrig katastrophal P0 F-02 analoge Sicherung
Hetzner-Account-Verlust -> halbes 3-2-1 Backup niedrig-mittel hoch P0/P1 F-03 Zweitziel
AdGuard-Admin-Manipulation aus LAN Security niedrig hoch (DNS-Hijack) P0 F-01 Bind auf Tailscale
Operator-Pwd-Leak -> 2FA fehlt fuer Borg-UI/Code-Server Security mittel hoch P0 F-04 2FA-ACL erweitern
Komodo-Self-Bootstrap-Failure nach Totalausfall DR niedrig hoch P1 F-09 Bootstrap-Datei in services/
Authelia Repo↔Host Drift unbemerkt GitOps/Security mittel mittel P1 F-10 Diff-Check
Immich Silent Corruption -> kein Restore-Test belegt Backup niedrig sehr hoch (Familien-Fotos) P1 F-11 Restore-Test
Cert-Expiry unbemerkt -> Public Apps down Operations niedrig mittel P1 F-08 Alert-Regel
Nextcloud Brute-Force ohne Bouncer Security mittel mittel-hoch P1 F-14 CrowdSec / F-18 Nextcloud-Haerten
Image-Update-Stillstand -> CVE bleibt Security mittel mittel P1 F-12 Renovate
Hermes-Wartungsschuld Wartbarkeit hoch niedrig P1 F-06 Entscheidung
Repo-Altstaende ueberleben -> Doppel-Deploy GitOps mittel niedrig P1 F-05 Cleanup
OOM durch unlimitierte Container Hardware niedrig mittel P2 F-19 mem_limit
Healthcheck-Luecke -> Soft-Failure stumm Operations mittel niedrig P2 F-15 Healthchecks
Monitoring-Stack ohne Digest-Pin Reproduzierbarkeit niedrig niedrig P2 F-07 Digests + Renovate
Hardware-SPOF (kein zweiter Host) Hardware niedrig sehr hoch P3 Cold-Standby / 2. Host

E. Zielarchitektur (realistisch fuer privates Homelab)

Hardware

  • 1× Unraid-Host (bestehend) als Production. CPU mit AVX2/AVX-512 fuer Immich-ML. ≥ 32 GB RAM (fuer 2× Postgres + Immich-ML + Loki/Prometheus + 2 VMs).
  • 2× NVMe als BTRFS-RAID1-Cache, sobald Cache-Auslastung > 70 % (STORAGE_LAYOUT 15.3).
  • Parity-Disk ≥ groesste Daten-Disk.
  • USV mit USB-Steuerung (NUT-faehig: APC Back-UPS RS 700+, Eaton 3S, CyberPower CP1500EPFCLCD). Direkter Shutdown bei Power-Loss.
  • Optional: zweiter alter Mini-PC oder NUC als Cold-Standby mit Tailscale, der den letzten Komodo-Bootstrap + Gitea-Mirror tragen kann.

Netzwerk

  • FritzBox (bestehend) als Router + NAT.
  • VLANs nur wenn IoT-WLAN dazukommt (FritzBox-Gast-WLAN reicht fuer Anfang).
  • DNS: AdGuard -> Unbound (bestehend). Admin-UI nur Tailscale.
  • Tailscale (bestehend): Operator-Pfad. Subnet-Router optional fuer LAN-Devices ueber Tailscale.

Storage

  • Cache only fuer appdata, system, domains (bestehend STORAGE_LAYOUT 4).
  • Disk1 (XFS) fuer services, documents, photos, backups, media, finance, projekte.
  • Externe Wechselplatte (XFS) fuer Cold-Off-Site mit fester monatlicher Rotation.

Ordnerstruktur (Repo)

  • Beibehalten. Nur Cleanup von Altstaenden (F-05). Naming kebab-case-Migration aus STORAGE_LAYOUT 6 schrittweise.

Docker

  • Compose-only via Komodo (bestehend).
  • Digest-Pin fuer alle Images (F-07).
  • Healthchecks fuer Tier-1 (F-15).
  • Mem-Limits fuer Tier-1 + Immich-ML (F-19).
  • App-interne Netze fuer Stack-Isolation (bestehend).

Reverse Proxy

  • Traefik v3 (bestehend), DNS-Challenge, Wildcard.
  • Dynamic Config nur fuer Middlewares, TLS, Dashboard (bestehend).
  • CrowdSec-Bouncer (F-14) fuer oeffentliche Apps.

Auth

  • Authelia als ForwardAuth und OIDC-Provider (F-13).
  • Nextcloud, Immich, Grafana via OIDC.
  • 2FA-Pflicht fuer alle Operator-Dienste (F-04).
  • Komodo bewusste Ausnahme (bestehend).

Backup

  • Borg lokal (/mnt/user/backups/borg/) + Borg Hetzner + Wechselplatte.
  • Pre-Dump-Hooks (bestehend).
  • Borg-Passphrase off-system analog (F-02).
  • Restore-Tests automatisiert (F-11 Immich, dann andere via CI).

Monitoring

  • monitoring/-Stack als alleinige Quelle. Altstaende raus (F-05).
  • Family-View-Dashboard in Grafana (alles gruen, Backup-Frische, Cert-Tage).
  • Alerts ausgebaut (F-08).
  • Posture-Check + Docker-Critical-Events -> ntfy homelab-alerts (bestehend).

Dokumentation

  • Aktuelle Doku-Tiefe halten.
  • SERVICES_RECOVERY.md und STORAGE_LAYOUT.md (Active) finalisieren.
  • Familien-/User-Onboarding-Doku als eigenes kleines Dokument.

GitOps

  • Gitea + Komodo (bestehend).
  • GitHub-Push-Mirror (umgesetzt, bestaetigt durch MASTER 7.1).
  • Renovate-Bot gegen Gitea (F-12).
  • Optional: Staging-Branch + zweites Komodo-Ziel in Tailscale-VM (Phase 3).

Restore

  • RESTORE_MATRIX bleibt fuehrend.
  • Restore-Lab unter /mnt/user/backups/restore-lab/ (bestehend).
  • Immich-Restore als Luecke schliessen (F-11).
  • Komodo-Self-Bootstrap raus aus Komodo (F-09).

F. Priorisierte Massnahmenliste

# Aufgabe Warum Kategorie Prio Aufwand Risiko (bei Nicht-Tun) Mehrwert Abhaengigkeiten Validierung
1 Borg-Passphrase analog sichern DR-SPOF schliessen Backup P0 S katastrophal DR-Sicherheit Wert ohne Host abrufbar
2 AdGuard-Admin auf Tailscale-IP binden LAN-Angriffsflaeche Security P0 S hoch LAN-IoT-Haertung ss -ltnp zeigt nur Tailscale
3 2FA-ACL erweitern (borg, code, files, traefik) Operator-Pwd-Leak Security P0 S hoch 2FA-Coverage Authelia-TOTP-Setup Login erzwingt 2FA
4 Altstaende ops/grafana-influxdb+ops/loki git rm Repo-Hygiene, kein Re-Deploy GitOps P0 S niedrig Klarheit Tag setzen Policy-Check clean
5 Hermes 60-Tage-Deadline Wartungsschuld App P1 S/L mittel Komplexitaet raus Operator-Entscheidung Entweder produktiv oder weg
6 Immich-Restore-Test einrichten Groesster Datentopf ungeprueft Backup P1 M hoch Restore-Vertrauen Restore-Lab-Pfad Smoke-Test-Report
7 Renovate-Bot in Gitea manuelle Digest-Pflege Wartung P1 M mittel Update-Hygiene Gitea-Runner erste PR offen
8 Alert-Regeln (Borg-Frische, Cert-Expiry) Blind-Spot Operations Monitoring P1 M mittel echte Alerts Pushgateway o. textfile Alert in Test
9 Family-View-Dashboard Grafana Morgens 30 s Check Monitoring P1 M niedrig Uebersicht Datasources stehen Dashboard funktioniert
10 Komodo-Self-Bootstrap als services/komodo-bootstrap/ Henne-Ei-Problem GitOps/DR P1 M mittel sauberer Recovery-Pfad Komodo-Stack-Doku Bootstrap aus Repo allein moeglich
11 Authelia-Drift-Diff-Check in posture-check Repo↔Host Drift GitOps P1 S mittel Drift-Detektion posture-check-Erweiterung neuer Check sichtbar
12 Healthchecks Tier-1 Soft-Failure-Erkennung Docker P1 M niedrig Self-Healing-Trigger docker ps zeigt healthy
13 CrowdSec-Bouncer vor Traefik oeffentliche Apps schuetzen Security P1 M mittel Brute-Force-Stop Traefik-Middleware Test-IP wird geblockt
14 Nextcloud-Haertung dokumentieren Public App + native Auth Security P1 S mittel App-Haertung Plugin-Install 2FA-erzwingt
15 Authelia OIDC-Provider + Nextcloud/Immich/Grafana SSO, Familien-Onboarding Security/UX P2 L niedrig hoher Mehrwert Authelia-OIDC-Setup SSO-Login funktioniert
16 Immich-Smartphone-Auto-Backup fuer Familie Killer-App fuer Familie App P2 S niedrig hoher Mehrwert Familien-Foto in Immich
17 Monitoring-Stack Digests + Renovate-Pin Reproduzierbarkeit GitOps P2 S niedrig konsistent Renovate optional @sha256 an allen Images
18 Mem-Limits Tier-1 + Immich-ML OOM-Schutz Hardware/Docker P2 M niedrig Schutz docker stats zeigt Limits
19 Off-Site-Zweitziel (rsync.net o. Wechselplatte) Single-Provider Backup P2 M mittel 3-2-1 echt Borg-Config beide Repos < 7d
20 Staging-Branch + 2. Komodo-Ziel Risiko-Aenderung testbar GitOps P3 L niedrig Reife 2. VM/Host Deploy auf staging klappt

G. Refactoring-Plan (Sprints)

Sprint 0 — Sicherheitsnetz und Ist-Zustand sichern (1 Tag)

  • Ziel: Du kannst danach im schlimmsten Fall alles, was du jetzt aenderst, sicher zurueckrollen.
  • Aufgaben:
    • Git-Tag audit-2026-05-25-baseline auf master setzen und nach Gitea + GitHub-Mirror pushen.
    • Borg-Lauf manuell ausloesen ("freshen up"), Erfolg im Log dokumentieren.
    • Aktuellen Komodo-Mongo-Dump verifizieren (mongorestore --dry-run).
    • docs/MIGRATION_LOG.md Eintrag "Audit-Sprint-Start".
  • Erfolgskriterium: Tag pushed, Borg-Lauf gruen, Mongo-Dump verifiziert.
  • Validierung: git fetch && git tag | grep audit-2026-05-25-baseline und ls /mnt/user/backups/borg/dumps/latest/ zeigt fresh.
  • Rollback: N/A (rein additiv).
  • Risiko bei Nichtumsetzung: Keine Notbremse fuer Sprint 1.

Sprint 1 — Offensichtliche Risiken entschaerfen (1 Woche)

  • Ziel: P0-Risiken weg, Repo-Hygiene wieder gruen.
  • Aufgaben (in dieser Reihenfolge):
    1. F-02 Borg-Passphrase analog sichern (off-system, kein Code-Change).
    2. F-01 AdGuard-Admin-Port auf Tailscale-IP — Edit host-services/Adguard/docker-compose.yml:16.
    3. F-04 Authelia ACL erweitern (two_factor fuer borg, code, files, traefik) — Edit security/authelia/configuration.yml + Host-Sync.
    4. F-05 Altstaende ops/grafana-influxdb/, ops/loki/ entfernen — git rm, MIGRATION_LOG.
    5. Policy-Check-Warnings SEC001 (ddns-updater, scrutiny) aufraeumen.
  • Erfolgskriterium: Policy-Check 0 Warnings fuer SEC001, AdGuard-Admin nur via Tailscale, 2FA-Login auf borg.kaleschke.info.
  • Validierung: Policy-Check-Report; Browser-Test mit/ohne 2FA-Cookie.
  • Rollback: Commit-Revert pro Block.

Sprint 2 — GitOps-Robustheit (12 Wochen)

  • Ziel: Self-Bootstrap-Problem entschaerft, Drift-Detektion automatisiert.
  • Aufgaben:
    1. F-09 Komodo-Bootstrap-Compose nach services/komodo-bootstrap/ extrahieren + dokumentierter Standalone-Restore-Pfad.
    2. F-10 Authelia-Drift-Diff in posture-check ergaenzen.
    3. F-11 Immich-Restore-Test einrichten (analog zu vaultwarden/gitea/paperless).
    4. F-06 Hermes-Entscheidung mit 60-Tage-Deadline schriftlich.
  • Erfolgskriterium: Komodo laesst sich aus Repo allein wiederherstellen. Posture-Check zeigt authelia_config_drift: false. Immich-Restore-Report unter /mnt/user/backups/restore-reports/.
  • Validierung: Trockenversuch (Komodo-Container stoppen, docker compose up -d aus services/komodo-bootstrap/).
  • Rollback: Bootstrap-Verzeichnis loeschen, Komodo-Self-Stack wie vorher.

Sprint 3 — Backup & Restore belastbar machen (23 Wochen)

  • Ziel: 3-2-1 echt, Restore-Tests breiter, Stack-ENV im DR-Pfad.
  • Aufgaben:
    1. F-03 Zweitziel: Wechselplatten-Rotation dokumentieren ODER zweites Borg-Repo (rsync.net / BorgBase EU2).
    2. F-20 Stack-ENV-Liste in DR-Doc explizit machen (Restore-Reihenfolge).
    3. Borg-Verifikation Cron fuer borg check --repository-only weekly (STORAGE_LAYOUT 8.4).
    4. Quartalsweise End-to-End-Restore-Drill in Schedule aufnehmen.
  • Erfolgskriterium: Beide Off-Site-Ziele < 7 Tage alt; DR-Doc enthaelt "ENV-Restore-Reihenfolge".
  • Validierung: borg list gegen beide Repos.

Sprint 4 — Monitoring & Alerting ausbauen (2 Wochen)

  • Ziel: Sichtbarkeit auf das, was wirklich weh tut.
  • Aufgaben:
    1. F-08 Alert-Regeln: BorgArchiveStale, TLSCertExpiryNear, ContainerDown, PostgresConnSaturation.
    2. F-15 Healthchecks fuer Traefik, Authelia, Postgres, Komodo, Gitea.
    3. F-07 Digest-Pin in monitoring/docker-compose.yml.
    4. Family-View-Dashboard in Grafana (1 Panel: Service-Up, 1 Panel: Backup-Frische, 1 Panel: Cert-Tage, 1 Panel: Disk-Fuellung).
  • Erfolgskriterium: Family-View zeigt alles gruen; Cert-Alert feuert in Test (Datum vorgespult).
  • Validierung: Dashboard sichtbar unter monitoring.kaleschke.info/d/family-view.

Sprint 5 — Auth-Konsolidierung & Frontdoor-Haertung (34 Wochen)

  • Ziel: SSO fuer die Familie, Brute-Force-Bouncer vor oeffentlichen Apps.
  • Aufgaben:
    1. F-13 Authelia OIDC-Provider aktivieren.
    2. Nextcloud OIDC-Plugin + Test-Login.
    3. Immich OIDC + Test-Login.
    4. Grafana OIDC + Test-Login.
    5. F-14 CrowdSec-Bouncer vor Traefik.
    6. F-18 Nextcloud-Haertung-Dokument + 2FA-Pflicht.
  • Erfolgskriterium: Familien-Konto loggt sich mit einem Login bei drei Apps ein; CrowdSec sperrt Test-IP nach N fehlerhaften Versuchen.
  • Validierung: OIDC-Sequenz im Browser ohne Eingabe-Wiederholung; CrowdSec-Dashboard zeigt Sperre.

Sprint 6 — Automatisierung und Nerd-Level (laufend)

  • Ziel: Image-Update-Pipeline, optional Staging.
  • Aufgaben:
    1. F-12 Renovate-Bot gegen Gitea.
    2. F-19 Mem-Limits Tier-1.
    3. Restore-Test-CI via Gitea Actions (P3).
    4. Optional: Staging-Branch + zweites Komodo-Ziel in Tailscale-VM (P3).
    5. Optional: Firefly III / Actual Budget fuer /mnt/user/finance.
  • Erfolgskriterium: Renovate-PRs erscheinen woechentlich; mindestens ein automatisches Patch-Update gemerged.

H. Fehlende Informationen

Nur, was den Audit konkret schaerfer machen wuerde.

Frage Warum Bereich Kommando / Datei
CPU-Modell, RAM-Groesse, Mainboard Hardware-Bewertung, OOM-Risiko, Immich-ML-Eignung, AVX-Verfuegbarkeit Hardware cat /proc/cpuinfo | grep -E 'model name|flags', free -h, dmidecode -t baseboard | head -20
USV vorhanden? Modell? DR-Beurteilung Power-Loss, Shutdown-Pfad Hardware/DR physische Sichtpruefung; apcaccess falls APC mit NUT
Stromverbrauch idle / Last Betriebskosten, Sizing Hardware Smartmeter / Tibber-API
NIC-Speed (1 GbE? 2.5 GbE?) Backup-Durchsatz, Plex-Streaming Netzwerk ip -br link, ethtool eth0
Disk-Inventar (Anzahl, Modelle, Alter) Storage-Health, Replacement-Plan Storage lsblk -o NAME,SIZE,MODEL,SERIAL, Scrutiny-UI
Aktueller Cache-Fuellstand Wann zweite NVMe? Storage df -h /mnt/cache
FritzBox-Modell + Firmware Net-Sicherheit, VLAN-Faehigkeit Netzwerk FritzBox-UI / fritzconnection
Tatsaechlich genutzte Plex- vs. ungenutzte App Konsolidierungs-Belege App-Landschaft Plex-Server-Logs, ggf. Glances-Container-CPU pro Stack
Existiert /mnt/user/finance/-Share schon? Ist Firefly-Vorbereitung trivial? Storage ls /mnt/user/finance/
Authelia Live-User-DB-Tiefe (Anzahl User, 2FA-Status) 2FA-Coverage-Bewertung Security cat /mnt/user/appdata/authelia/config/users_database.yml (nur Strukturansicht, keine Hashes hier zitieren)
Komodo-Mongo-Dump letzter Integrity-Check F-09-Vorbereitung Backup mongorestore --dry-run --archive=komodo-mongo.archive.gz --gzip
Aktuelle Cert-Restlaufzeit F-08-Test-Vorbereitung Operations openssl s_client -connect git.kaleschke.info:443 -servername git.kaleschke.info < /dev/null | openssl x509 -noout -dates

I. Pruefkommandos (Linux / Unraid / Docker / Windows)

Strukturiert nach Bereich. Sicher zum Ausfuehren am Host.

Hardware

# CPU + Flags (AVX fuer Immich-ML)
cat /proc/cpuinfo | awk '/model name|flags/ {print; if(/flags/) exit}'

# RAM
free -h
dmidecode -t memory | grep -E "Size|Speed" | head -20

# Mainboard
dmidecode -t baseboard | head -20

# PCI / SATA / NVMe
lspci
nvme list
lsblk -o NAME,SIZE,MODEL,SERIAL,FSTYPE,MOUNTPOINT,VENDOR

# SMART
smartctl -a /dev/nvme0n1 | head -40
smartctl -a /dev/sdb | head -40

# Stromverbrauch (Unraid Plugin oder ipmitool falls IPMI)
sensors | head -30

Filesystem / Storage / Mounts

# Filesystem-Typen (Hard Rule 12.1)
findmnt -no FSTYPE /mnt/cache /mnt/disk1 /boot
mount | grep -E "ntfs3|fuseblk"   # darf leer sein

# Share-Settings
ls -la /boot/config/shares/

# Cache-Fuellstand
df -h /mnt/cache /mnt/disk1 /mnt/user
du -sh /mnt/user/appdata/* | sort -hr | head -20

Docker

# Container-Inventur
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | sort
docker ps -a --filter "status=exited" --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"

# Netzwerke
docker network ls
docker network inspect frontend_net | jq '.[0].Containers | keys'
docker network inspect backend_net | jq '.[0].Internal'

# Volumes ohne Container (Waisen)
docker volume ls -qf dangling=true

# Effektive Ports
ss -ltnp | sort -k4

# Healthchecks
docker ps --format "{{.Names}}\t{{.Status}}" | grep -E "healthy|unhealthy|starting"

Security

# Privileged-Container und Docker-Socket-Mounts
for c in $(docker ps -q); do
  docker inspect "$c" --format '{{.Name}}: priv={{.HostConfig.Privileged}}; sock={{range .HostConfig.Binds}}{{println .}}{{end}}'
done | grep -E "priv=true|docker.sock"

# Direkte Host-Ports
docker ps --format "{{.Names}}: {{.Ports}}" | grep -v "^[^:]*: $"

# Secret-Datei-Rechte
ls -la /mnt/user/appdata/secrets/
stat -c "%a %n" /mnt/user/appdata/secrets/*.txt

Backup / Restore

# Borg-Frische
ls -lat /mnt/user/backups/borg/dumps/latest/ | head
find /mnt/user/backups/borg/dumps/latest -mmin +1440 -type f   # aelter 24h

# Borg-Repo (Passphrase per File)
export BORG_PASSPHRASE=$(cat /mnt/user/appdata/secrets/borg_repo_passphrase.txt)
borg list ssh://... --short | tail -5
borg info ssh://... ::Taegliche-Sicherung-2026-05-25T05:52:44.157

# Posture-Check
cat /mnt/user/services/posture-check/last.json | jq '.warning_count, .critical_count'

Netzwerk / DNS

# Tailscale
tailscale status

# DNS auf AdGuard testen
dig @127.0.0.1 git.kaleschke.info
dig @127.0.0.1 example.com   # Unbound-Recursion

# Cert-Restlaufzeit
for h in vault git immich cloud paperless mealie ntfy; do
  echo -n "$h.kaleschke.info: "
  openssl s_client -connect ${h}.kaleschke.info:443 -servername ${h}.kaleschke.info </dev/null 2>/dev/null \
    | openssl x509 -noout -dates 2>/dev/null
done

GitOps-Konsistenz

# Komodo Stack-Workspace vs. Repo
cd /mnt/user/services/stacks/<stackname>
git rev-parse HEAD
git status --short

# Webhook-Liveness
docker logs komodo-core 2>&1 | grep -i "webhook\|deploy" | tail -20

Windows (lokal)

# Repo-Status
git status --short
git fetch origin
git log origin/master..HEAD --oneline   # ungepushte Commits
git log HEAD..origin/master --oneline   # ungepullte Commits

# Policy-Check
.\ops\policy-checks\check_repo.ps1

# Restore-Freshness
.\ops\restore-tests\check-restore-freshness.ps1

J. Community- / Best-Practice-Abgleich

Nur fuer die Architekturentscheidungen, bei denen der Markt eindeutig ist oder Gegenpositionen relevant sind.

Entscheidung Markt-Best-Practice Stuetzende Quellen Bewertung
Traefik mit Docker-Labels statt File-Provider Standard in Selfhosted (siehe awesome-selfhosted-docker, Smarthome-Beginner Templates) Traefik-Doc v3 docs.traefik.io/providers/docker passt zu MASTER 13 (Wechsel 2026-03-28)
DNS-Challenge mit Cloudflare statt HTTP-01 Standard fuer Wildcard und reduzierte Angriffsflaeche acme.sh / lego docs passt, korrekt
Authelia ForwardAuth statt Authentik Authelia ist leichtgewichtiger, Authentik maechtiger; beide valide r/selfhosted-Konsens 2024-25 Authelia richtig fuer Single-Family-Setup
Authelia ohne Redis-Session-Backend Markt-Standard ist mit Redis; deine Vereinfachung ist begruendet (MASTER 13 2026-05-04) Authelia-Doc Trade-off klar; Bewertung: vertretbar fuer Homelab
Komodo statt Portainer/Dockge Komodo ist neuer (2024), Dockge etabliert, Portainer kommerziell Selfh.st 2025 Comparison Komodo legitim, mehr GitOps-nativ als Dockge
Borg statt Restic/Kopia Borg ist klassische Wahl fuer Linux-Backup mit Deduplikation; Kopia/Restic gewinnen mit Multi-Backend r/datahoarder, ServeTheHome 2024 Borg passt zu Unraid-Stack; bewusste Vereinfachung
Glance statt Homepage als Single-Dashboard beide auf Augenhoehe; Homepage etablierter, Glance moderner, schneller, mit Live-Widgets github.com/glanceapp/glance vs. github.com/gethomepage/homepage Glance legitim; Bewertung: deine Wahl ist verteidigbar
Immich nicht hinter Authelia ForwardAuth offizielle Immich-Doku raet bei nativer App-Auth davon ab, weil Sync-Clients OIDC oder direkte Auth brauchen immich.app/docs/administration/reverse-proxy korrekt; OIDC spaeter (F-13) ist der Weg
Nextcloud klassisch statt AIO NC-AIO ist offizielle Empfehlung fuer Neuaufbau, klassisch hat mehr Flexibilitaet fuer GitOps NC-Blog 2024 bewusste Ausnahme MASTER 13; vertretbar, da GitOps-Anbindung wichtiger
Single-Host + Borg statt Proxmox-Cluster + ZFS-Send fuer Familien-Homelab ist Cluster Overkill r/homelab, LTT-Forum Single-Host korrekt; Cold-Standby (Sprint 6) ist die richtige naechste Stufe
AdGuard + Unbound statt Pi-hole aequivalent; AdGuard hat moderne UI, Unbound recursion gowri/networkchuck Tutorials 2024 passt
Posture-Check als Skript statt Goss/InSpec fuer Single-Host pragmatisch Goss ist maechtiger, aber Overkill Skript-Loesung legitim
Renovate gegen Gitea mehrere Erfahrungsberichte in Gitea-Issues + Renovate-Docs docs.renovatebot.com/modules/platform/gitea/ Standard-Pfad
CrowdSec vor Traefik starker Trend 2024-25 in Selfhosted-Community crowdsec.net/blog, Marius-Hosting-Tutorials sinnvolle Haertung

Gegenpositionen, die du kennen solltest:

  • "Authelia OIDC ist kompliziert, lieber Authentik." Korrekt, wenn du auch B2B-SAML brauchst. Fuer reine Familien-OIDC ist Authelia leichter wartbar.
  • "CrowdSec laedt zentrale Reputation-Listen -> Privacy-Bedenken." Stimmt, du kannst Local-Only-Mode fahren. Fuer Homelab egal.
  • "Renovate-Bot erzeugt Laerm." Mit Group/Schedule-Rules zaehmbar. Wert > Laerm.
  • "Komodo ist zu jung." Gegenargument: du benutzt es seit Q1/2026 produktiv, Major-Inzidenz war beherrschbar. Der Wechsel zurueck zu Portainer/Dockge waere hoehere Kosten als der Reifegrad-Nachteil.

K. Endziel — "Nerd-Level Homelab"

So sieht dein Homelab aus, wenn es wirklich auf Senior-Level ist:

Betrieb im Alltag

  • Morgens 30 Sekunden auf monitoring.kaleschke.info: Family-View zeigt 7 Tier-1-Services gruen, Backup-Job in der Nacht hat 100 % Files erfasst, alle Certs > 30 Tage, Disk < 80 %.
  • Push-Benachrichtigung auf dem Handy nur, wenn wirklich etwas brennt (Posture-Check critical, Borg > 30 h, Endpoint down ≥ 8 Min, Cert < 14 Tage).
  • Familienmitglieder loggen sich mit einem Login bei Nextcloud, Immich, Mealie ein. 2FA per TOTP-App, kein App-by-App-Passwortzettel mehr.

Updates

  • Renovate oeffnet woechentlich 510 Pull-Requests in Gitea fuer Patch-Versionen. Du siehst sie im Web-UI, pruefst Release Notes, klickst Merge. Komodo deployt automatisch via Webhook. Smoke-Test in der naechsten Glance-Seite.
  • Major-Updates kommen separat mit Label major, behandelst du in einem geplanten Slot mit Restore-Snapshot davor.

Backups

  • Borg lokal alle 6 h, Borg Hetzner taeglich, Wechselplatte monatlich. Borg-Passphrase auf Papier im Bankschliessfach. Alle drei Ziele juenger als 36 h Alert-Schwelle.
  • Pre-Dump-Hooks erzeugen 15 konsistente Dump-Artefakte pro Lauf, automatische Posture-Check-Vor-Hook bricht Backup ab, wenn FS oder Mount sich veraendert haben.

Restore

  • Monatlicher Mini-Restore-Test fuer Vaultwarden/Gitea/Paperless/Immich nach /mnt/user/backups/restore-lab/<dienst>/ laeuft automatisiert per Gitea Actions, Erfolgs-Report landet als Datei + ntfy-Info.
  • Quartalsweise End-to-End-Drill: ein kompletter Stack restauriert, App startet, Smoke-Test passt, Doku validiert. Komodo-Bootstrap-Pfad ist getestet.
  • Im Ernstfall folgst du docs/DISASTER_RECOVERY.md Phase 05 und bist nach < 8 h wieder im Vollbetrieb. Repo-Bootstrap aus GitHub-Mirror, Stacks in Stufen 15, Verifikation pro Stufe.

Monitoring

  • Prometheus + Loki + Grafana + Alertmanager-ntfy-Bridge. ~15 Alert-Regeln, alle in alerts.yml versioniert.
  • Family-View, Host-Overview, Containers+Logs, Traefik-Standalone, Backup-Frische, Cert-Tage. Sechs Dashboards mehr braucht keine Familie.
  • Loki sammelt 30 Tage Logs aus allen Containern via Promtail. cAdvisor + node-exporter liefern Container- und Host-Metriken. Blackbox testet oeffentliche Endpoints alle 60 s.

Security

  • Authelia OIDC fuer Nextcloud, Immich, Grafana, Mealie. ForwardAuth fuer Operator-UIs mit 2FA-Pflicht ab Tier-2.
  • CrowdSec sperrt Brute-Force-IPs auf Traefik-Ebene bevor sie die Apps treffen.
  • AdGuard-Admin nur via Tailscale. Operator-Pfad ausschliesslich Tailscale.
  • Authelia-Repo-Baseline und Host-Config sind per Diff-Check im posture-check abgesichert.
  • Secrets-Mounts mode 600, Borg-Passphrase analog.

Dokumentation

  • SERVICE_CATALOG, RESTORE_MATRIX, DISASTER_RECOVERY, STORAGE_LAYOUT, SECRETS_MAP, WORKFLOW, GITOPS_DRIFT_RUNBOOK, ALERTING_MAP, HOMELAB_ARCHITECTURE_MASTER bleiben aktuelle Single-Source-of-Truth.
  • services/komodo-bootstrap/ loest das Henne-Ei. SERVICES_RECOVERY.md ist final, nicht Draft.
  • Familien-Onboarding-Doku als Markdown: "So nutzt du Nextcloud-Web", "So aktivierst du Immich-Foto-Backup auf dem Handy", "So loggst du dich neu per 2FA ein".

Taegliche Nutzung

  • Familie scannt Briefe per ASN-Barcode in scans_inbox/, Paperless tagged via paperless-gpt automatisch, alles durchsuchbar.
  • Immich erfasst Smartphone-Fotos aller Familienmitglieder automatisch, Familie blaettert per Web/App, Tagging per ML.
  • Nextcloud traegt Kalender, Kontakte, geteilte Familienordner per WebDAV/CardDAV — kein Google/Apple-Lock-In.
  • Mealie speichert Rezepte, Einkaufsliste auf dem Handy.
  • Vaultwarden ist der einzige Passwort-Tresor der Familie; Familien-Organisation aktiv.
  • Plex streamt Heim-Medien an alle Endgeraete.
  • ntfy schickt dir Vorfaelle aufs Handy — und sonst nichts.
  • Optional: Firefly III fuer die Familien-Finanzen, Ecowitt-Wetter-Dashboard, Home-Assistant-Automationen fuer Strom-Eigenverbrauch.

Was bewusst weggelassen ist

  • Kein Kubernetes. Komodo + Compose reicht.
  • Kein zweiter Medienserver neben Plex (Jellyfin-Entscheidung 2026-05-25).
  • Kein zweites Dashboard neben Glance (Homepage-Entscheidung 2026-05-25).
  • Kein Uptime-Kuma neben Blackbox (Entscheidung 2026-05-25).
  • Kein Hermes-Agent, wenn er bis 2026-07-25 keinen klaren Alltagsnutzen liefert.
  • Kein BentoPDF/paperless-gpt 24/7, wenn nicht aktiv genutzt.
  • Kein Self-Stack-Komodo (durch services/komodo-bootstrap/ ersetzt).

Schlussbemerkung

Das Setup ist naeher an Senior-Reife als an Bastel-Niveau. Der groesste Hebel der naechsten drei Monate ist Konsolidieren statt erweitern (Hermes-Entscheidung, Altstaende raus, Auth-SSO, Off-Site-Diversitaet), kombiniert mit der einen Aktivierung, die das Setup vom Operator-Tool zum Familien-Tool macht: Immich-Smartphone-Backup fuer alle.

Das vorhandene 2026-05-23-Audit hat die richtigen Sprintziele bereits identifiziert. Diese externe Audit-Sicht ergaenzt:

  • 2FA-Pflicht auf Tier-1-Operator-UIs (F-04) — fehlt in der Bewertung 2026-05-23 in dieser Klarheit.
  • Healthcheck-Luecke (F-15) und fehlende Mem-Limits (F-19) — operative Detail-Findings, die in der strategischen Bewertung nicht auftauchen.
  • Komodo-Self-Bootstrap als konkreter Code-Vorschlag (F-09) statt nur als Risiko-Erwaehnung.
  • Authelia-Drift-Detection automatisieren (F-10) statt nur "manuell merge".
  • Monitoring-Stack ohne Digest-Pin (F-07) — Inkonsistenz mit der eigenen Image-Pinning-Disziplin.
  • infra/redis ist faktisch nicht shared (F-16) — Etikett-Realitaet-Drift.
  • Alert-Regeln deutlich zu duenn (F-08) — Sichtbarkeitsluecken bei Cert/Borg/Container-Down.

Wenn Sprint 13 in 46 Wochen sitzen, bist du auf einer 1-Note. Wenn dann Sprint 45 in weiteren 68 Wochen kommen, hat die Familie ein echtes Self-Hosting-System, kein "Container-Sammlung im Keller". Das ist der Unterschied, den der Audit-Auftrag adressiert.