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

18 KiB

Audit TODO 2026-05-25

Quelle: docs/archive/2026-05/AUDIT_2026-05-25.md

Status: Arbeitsliste fuer die Umsetzung. Authelia-2FA/OIDC, CrowdSec und Nextcloud-2FA-Haertung bleiben ganz hinten und werden bewusst nicht in diesem Audit-Zyklus angefasst.

Leitplanken

  • Authelia-2FA-ACL, Authelia-OIDC und CrowdSec werden in diesem Audit-Zyklus nicht umgesetzt (Operator-Vorgabe 2026-05-26).
  • Keine Live-riskanten Bind-/Port-Aenderungen ohne vorher erfasste Host-Werte, insbesondere Tailscale-IP.
  • Hermes-Agent ist geparkt, nicht entfernt; Review-Deadline 2026-07-25.
  • USV-Anschaffung ist verschoben; Power-Loss-Risiko ist als Operator-Entscheidung 2026-05-26 bewusst akzeptiert.
  • Borg-Passphrase ist offline gesichert (bestaetigt 2026-05-26).
  • H:/ ist evaluiert als zweite lokale Nearline-Kopie, nicht als Offsite-Ersatz (siehe docs/CAPACITY_AND_LIFECYCLE.md).
  • Familien-Einladung ist fuer das Wochenende nach Erreichen des finalen Stands geplant; Family-Onboarding muss familienverstaendlich werden, nicht technisch.
  • Jede produktive Aenderung bekommt Validierung und Rollback-Hinweis.

Naechster Startpunkt 2026-05-26

Kontext bewusst gesichert, bevor weitere Live-Aenderungen passieren:

  1. Host-Schedule fuer Gitea-Bundles und Restore-Freshness pruefen.
  2. FRITZ!Box-Portfreigaben (UI) gegen Repo-Soll abgleichen (443/tcp + 222/tcp).
  3. H:/ Pull-Workflow festlegen.
  4. Family-Onboarding-Doku familienverstaendlich umarbeiten, vor der Wochenend-Einladung.
  5. Authelia 2FA/OIDC und CrowdSec weiterhin nicht anfassen; bleibt bewusst der letzte Block.

Sprint 0 - Inventar und Baseline

Status Aufgabe Ergebnis
erledigt Hardware-Inventar ausfuellen CPU, RAM, Mainboard, BIOS, NIC, Controller, Disks, SMART und Capacity-Baseline erfasst; USV ist als nicht validiert dokumentiert
erledigt Netzwerk-Inventar ausfuellen Host-IP, Gateway, Tailscale-IP, AdGuard-Bind und FRITZ!Box-Baseline (7590, FRITZ!OS 8.21, Telekom DSL 87/36, 36 Geraete, Gast-WLAN inaktiv, Ausfallschutz inaktiv, 2 Portfreigaben aktiv) erfasst; IPv6 und FRITZ!OS-Update bleiben Operator-Folgeaufgaben
erledigt (Baseline) Externe Abhaengigkeiten dokumentieren docs/EXTERNAL_DEPENDENCIES.md enthaelt bekannte Provider, Kritikalitaet, Ausfallplaene; Account-Recovery-Codes/Zahlungswege bleiben Off-Repo-Operatorcheck
erledigt (Baseline) Services-Recovery-Pfade beschreiben docs/SERVICES_RECOVERY.md enthaelt Gitea-/Komodo-/Secrets-Sonderpfade; Gitea-Bundle-Mechanik ist umgesetzt und per Host-Erstlauf validiert
erledigt Baseline-Tag setzen audit-2026-05-25-baseline ist lokal und remote vorhanden
erledigt Policy-Check neu ausfuehren SEC001-Warnings aus altem Report sind nicht mehr aktuell

Sprint 1 - Nicht-kontroverse Sicherheits- und Repo-Hygiene

Status Aufgabe Ergebnis
erledigt Borg-Passphrase analog sichern Operator bestaetigt am 2026-05-26: Passphrase ist offline gesichert und ohne Host/Vaultwarden wiederherstellbar
erledigt (repo) AdGuard Admin-Bind vorbereiten Tailscale-IP 100.80.98.33 erfasst, Compose-Soll geaendert
erledigt AdGuard Admin-Port auf Tailscale-IP binden Live validiert: ss -ltnp zeigt 100.80.98.33:8082, DNS auf Port 53 funktioniert, LAN-Zugriff auf 192.168.178.58:8082 schlaegt fehl
erledigt Alte Monitoring-Verzeichnisse entfernen ops/grafana-influxdb/ und ops/loki/ sind aus dem aktiven Repo entfernt; Rollback erfolgt ueber Git-Historie
erledigt Komodo/Gitea-Restdrift bereinigen alter Komodo-Stack grafana ist inert und ohne Repo-Pfad/Webhook; Gitea-Hook 35 und komodo-Self-Hook 11 sind inaktiv; aktive Gitea-Hooks haben keine Fehlstatus
erledigt Policy-Warnings triagieren Plex Host-Netz und digest-gepinnte mutable Tags sind dokumentierte Info-Ausnahmen; monitoring-influxdb3-core als Root-Ausnahme bleibt bewusst als Warning sichtbar

Sprint 2 - Storage und Recovery verbindlich machen

Status Aufgabe Ergebnis
erledigt docs/STORAGE_LAYOUT.draft.md finalisieren Datei als docs/STORAGE_LAYOUT.md Active v1.4 gefuehrt; Draft-Blocker entfernt
erledigt (Baseline) Disk- und Share-TBDs eintragen Disk-Modelle, Seriennummern, Groessen, Filesysteme und Share-Cache-Settings aus docs/HARDWARE_INVENTORY.md und Host-Readout 2026-05-27 uebernommen; Retention-/Schwellen-Kalibrierung bleibt Folgeaufgabe
erledigt Gitea-Repo-Mirror-Mechanik definieren ops/borg-ui/scripts/gitea-bundle-mirror.sh erzeugt verifizierte Bundles unter /mnt/user/backups/git-bundles/gitea; Host-Erstlauf 2026-05-26: 4 Bundles, Checksums OK, homelab-infra.bundle klonbar und git fsck sauber. Schedule live seit 2026-05-27 ueber User-Script gitea-bundle-mirror-6h (10 */6 * * *); Bundles werden mit chmod 644 geschrieben damit der Nearline-Pull sie greift.
erledigt (Doku + Skript + Erstlauf) Komodo-Bootstrap-Pfad beschreiben docs/SERVICES_RECOVERY.md enthaelt linearen Bootstrap in Stufen A-F mit Recovery-Anker ops/komodo/docker-compose.yml, expliziter Abgrenzung zum Self-Stack, Secret-Reihenfolge und Validierungs-Kommandos; docs/DISASTER_RECOVERY.md Stufe 3 verlinkt auf Bootstrap-Pfad. Trockenlauf-Skript unter ops/restore-tests/komodo-bootstrap-* seit 2026-05-29 vorhanden, Erstlauf 2026-05-30 erfolgreich (siehe Sprint 8 Eintrag).
erledigt Immich-Restore-Test planen Testumfang, Datenpfade und Smoke-Test-Kriterium sind in docs/IMMICH_RESTORE_TEST.md, ops/restore-tests/immich-plan.md und ops/restore-tests/immich-runbook.md festgehalten; erster Host-Lauf am 2026-05-27 erfolgreich

Sprint 3 - Restore und Monitoring

Status Aufgabe Ergebnis
erledigt Immich-Restore-Test implementieren Echter Host-Lauf 2026-05-27 erfolgreich: Borg-Archiv Tägliche-Sicherung-2026-05-27T04:30:06.778, immich.dump extrahiert, isolierter pgvecto-rs-Postgres importiert, Immich-Server ohne ML gestartet, HTTP 200, Login-Marker ok, 11977 Assets und 1 User im Test-DB-Check; Report /mnt/user/backups/restore-reports/immich-2026-05-27.md
erledigt Borg-Stale-Alert bauen Cron */5 * * * * (export-prometheus-textfile-5min User-Script) schreibt homelab.prom; node-exporter scraped, Prometheus laedt Regel HomelabBorgBackupStale aktiv. Live 2026-05-27 20:33 reloaded; lastConfigTime: 2026-05-27T18:33:06Z; Smoke-Query (time() - homelab_borg_last_completed_timestamp_seconds)/3600 = 16h. Borg-Job-Warning ist aktuell pending (Letzter Lauf completed_with_warnings).
erledigt TLS-Cert-Expiry-Alert bauen Regeln HomelabCertificateExpiresSoon (21d) und HomelabCertificateExpiresCritical (7d) sind in alerts.yml aktiv und nach Prometheus-Reload geladen. Smoke inactive (keine Cert <21d).
erledigt Container-Down-Alert bauen HomelabCriticalContainerDown aktiv; Live-Smoke 2026-05-27 sum(homelab_critical_container_running) = 30, alle aktuellen Critical-Container 1. Aktualisierung alle 5 Min ueber Cron.
erledigt (Spezifikation) Family-View Dashboard definieren docs/FAMILY_VIEW_DASHBOARD.md enthaelt Layout, PromQL-Queries, Thresholds und Build-Reihenfolge fuer ein homelab-family-view-Dashboard. JSON wird bewusst erst angelegt, sobald Borg-Stale-/Cert-Expiry-/Container-Down-Metriken stabil live sind und ein manueller Build im Grafana-UI das Layout bestaetigt hat.

Sprint 4 - Familien- und Betriebsdoku

Status Aufgabe Ergebnis
erledigt (final vor Einladung) Familien-Onboarding schreiben docs/FAMILY_ONBOARDING.md ist final redigiert: familienverstaendliche Sprache, App-eigene 2FA statt SSO-Versprechen, neuer "Bewusst nicht versprochen"-Block (kein Einheits-Login, kein 24/7-SLA, kein Hotline-Support, keine Datenweitergabe), konkrete Was-tun-Anleitungen. Einladungstermin bleibt Operator-Aufgabe.
erledigt (Baseline) Capacity-/Lifecycle-Review erstellen Cache 6 %, Array/User-Shares 33 %, lokale Backups 2.2G; H:/-Nearline-Bewertung ergaenzt; zweites Off-site/Cold-Storage bewusst nicht umgesetzt
erledigt USV-Test oder USV-Entscheidung Operator-Entscheidung 2026-05-26: aktuell keine USV-Anschaffung; Power-Loss-Risiko wird bewusst akzeptiert und dokumentiert
erledigt (Baseline) H:/ als zusaetzliches lokales Backupziel bewerten Als zweite Nearline-Kopie und Freeze-Sicherung sinnvoll; kein Offsite-Ersatz, kein CIFS-Hard-Mount am Unraid; Pull-Modell vom Windows-PC ist der getestete Weg (siehe docs/CAPACITY_AND_LIFECYCLE.md)
erledigt 2026-05-28 H:/ Groesse und Pull-Schedule festschreiben Groesse erfasst: 8.0T NTFS, 3.91T belegt, 4.10T frei, Healthy. Erster echter Pull 2026-05-27 20:45 erfolgreich: 19 Borg-Dumps + 10 Gitea-Bundle-Files unter H:\kallilab-nearline-backups. unraid-flash-config.* bewusst ausserhalb Scope (/XF-Exclude, Restore aus Hetzner-Borg). Windows Scheduled Task KalliLab H Drive Nearline Pull laeuft seit 2026-05-28 taeglich 05:30.
erledigt 2026-05-28 FRITZ!Box-Portfreigaben gegen Repo-Soll abgleichen Bereinigt: 80/tcp entfernt (Mobilfunk-validiert: HTTP timeout, HTTPS weiter erreichbar). 222/tcp bleibt bewusst nicht eingerichtet (Tailscale-only-Linie). UPnP-Selbstfreigabe-Recht fuer PC-192-168-178-71 (VONETS-Bridge, vermutlich SolarEdge-Wechselrichter) deaktiviert. Aktiver Endstand: ausschliesslich 443/tcp -> 192.168.178.58. Details in docs/archive/2026-05/FRITZBOX_PORT_CORRECTION_PLAN.md.

Sprint 5 - Auth und Frontdoor, bewusst zuletzt

In diesem Audit-Zyklus werden diese Punkte nicht umgesetzt. Sie sind dokumentiert, damit sie bei einer kuenftigen Policy-Entscheidung sofort priorisiert werden koennen.

Status Aufgabe Begruendung der Parkung
geparkt Authelia 2FA fuer Operator-UIs erweitern (F-04) Operator-Vorgabe 2026-05-26: keine Auth-Aenderungen in diesem Zyklus
geparkt Authelia OIDC fuer Apps pruefen (F-13) Operator-Vorgabe 2026-05-26: keine Auth-Aenderungen in diesem Zyklus
geparkt CrowdSec vor Traefik pruefen (F-14) Operator-Vorgabe 2026-05-26: erst nach finaler Auth-Policy
geparkt Nextcloud-2FA-/Brute-Force-Haertung dokumentieren (F-18) beruehrt Auth-Policy fuer Familien-Konten; gemeinsam mit OIDC-Entscheidung

Sprint 6 - Geparkte Apps und Folgeentscheidungen

Status Aufgabe Naechster Pruefschritt
geparkt Hermes-Agent (F-06) — Operator-Entscheidung produktiv vs. entfernen Review-Deadline 2026-07-25; bis dahin bleibt der NAS-Stack deaktiviert, das Repo-Verzeichnis erhalten, Dashboard-Domain und ACL-Eintrag unveraendert
erledigt 2026-05-28 paperless-gpt / BentoPDF Nutzungsentscheidung Operator behaelt beide. paperless-gpt bleibt bis Paperless-NGX 3.0 (erwartete native KI-Features); danach neu bewerten. BentoPDF bleibt als situatives Tool (Resource-Footprint ~4 MB). Beide ohne aktive Traefik-Zugriffe in der letzten Woche, aber bewusste Behalten-Entscheidung mit Begruendungs-Anker im SERVICE_CATALOG.
erledigt 2026-05-28 Plex Remote Access in UI deaktivieren falls nur LAN/Tailscale (F-17) Beim Versuch entdeckt: Server war seit 18.05. unclaimed und Bibliotheken leer. Reclaim als Xeridos via inline PLEX_CLAIM-Token, danach Bibliotheken (/data/movies 1.4 TB, /data/Heimatfilme 300 GB) neu angelegt und Remote Access deaktiviert (PublishServerOnPlexOnlineKey=0, Plex-Relay aus). Details in HOMELAB_ARCHITECTURE_MASTER_V2.md Sektion 13.
erledigt infra/redis Doku-Etikett korrigieren (F-16) SERVICE_CATALOG, REPO_MAP, MASTER (Sektion 13) und DISASTER_RECOVERY Bootstrap-Stufe 2 auf "primaer Paperless-Redis" praezisiert; keine Compose-Aenderung
erledigt Paperless-DBPass DR-Restore-Reihenfolge in DR-Doc (F-20) DISASTER_RECOVERY 6.2.1 (Restore-Quellen fuer Stack-ENV-Werte) ergaenzt; SECRETS_MAP um Abschnitt "Stack-ENV-only Secrets - Restore-Wege" mit Reihenfolge Komodo-Mongo-Dump -> Vaultwarden -> externe Notiz erweitert; Paperless, Immich, Mail-Archiver, Speedtest, Komodo, Hermes und Glance je mit Restore-Quelle dokumentiert

Sprint 8 - Reife der Stack-Hygiene (2026-05-29)

Status Aufgabe Ergebnis
erledigt 2026-05-29 Healthchecks fuer Tier-1 (F-15) postgresql17 (pg_isready), Redis (redis-cli ping mit Auth), Vaultwarden (curl /alive), Gitea (wget /api/healthz), Traefik (traefik healthcheck --ping, --ping=true in CLI), Authelia (wget /api/health, weil v4.39 helper health-check entfernt hat); komodo-mongo war bereits gepinnt healthy. Live-Smoke: alle 6 healthy nach Recreate. Postgres- und Gitea-Stack-Workspace waren Komodo-seitig zurueckgeblieben (124 bzw. 52 commits behind); manuell per cp + docker compose up -d synchronisiert.
erledigt 2026-05-29 Monitoring-Stack Digest-Pinning (F-07) 9 Container in monitoring/docker-compose.yml per Tag@sha256 gepinnt: prometheus, alertmanager, alertmanager-ntfy-bridge (python:3.13-alpine), blackbox-exporter, loki, promtail, grafana, node-exporter, cadvisor. Digests aus dem aktuell laufenden Container ausgelesen, damit der Pin den Live-Stand reflektiert. influxdb3-core war bereits gepinnt.
erledigt 2026-05-29 (Skript) / 2026-05-30 (Erstlauf) Komodo-Bootstrap-Trockenlauf-Skript (F-09 Rest) ops/restore-tests/komodo-bootstrap-{compose.test.yml,test.sh,plan.md,runbook.md} analog zum Immich-Restore-Test angelegt. Test-Compose nutzt dieselben Image-Digests wie Produktion, isoliert unter Project restoretest-komodo, Test-Periphery ohne docker.sock-Mount, Test-Port nur 127.0.0.1:19120. Wegwerf-Secrets im Compose. Erstlauf 2026-05-30 erfolgreich: Result SUCCESS, alle 5 Checks gruen — compose config valid, Test-Mongo healthy (6s), Mongo authenticated ping ok, Komodo Core HTTP 200, Test-Periphery container state running. Report unter /mnt/user/backups/restore-reports/komodo-bootstrap-2026-05-30.md. Produktive Komodo-Container, Mongo-Datadir und Secrets nicht beruehrt. Damit ist ops/komodo/docker-compose.yml als Recovery-Anker belegt tauglich (nicht mehr nur angenommen).
erledigt 2026-05-29 Renovate-Bot gegen Gitea (F-12) Live: Service-Account renovate (uid 2, kein Admin) angelegt, Collaborator Write auf Micha/homelab-infra, PAT in /mnt/user/appdata/secrets/renovate_token.txt (chmod 600). Cron renovate-six-hourly (20 */6 * * *) live in /etc/cron.d/root. Erstlauf 2026-05-29 erfolgreich: 5 PRs (mongo digest+minor, postgres digest+minor, minor-and-patch-updates gruppiert), 1 Dependency-Dashboard-Issue, 8 Branches. Komodo-Major durch packageRule deaktiviert wie erwartet. Architektur-Detail: Repo-Config in renovate.json, Bot-Config in ops/renovate/bot-config.js (Renovate liest die im Repo nur als Repo-Config, Bot-Settings dort triggern "forbidden/disabled").
erledigt 2026-05-30 Authelia Repo<->Host Drift-Check (F-10) services/authelia-diff.sh vergleicht die access_control:-Sektion zwischen Repo-Baseline und Host-Datei (Default; per env AUTHELIA_DIFF_SECTIONS erweiterbar). OIDC-Clients/Identity-Provider und Secret-Werte bleiben bewusst aussen vor. Exit-Codes: 0 = ok, 1 = Drift, 2 = Datei fehlt, 3 = Sektion fehlt, 4 = Werkzeug fehlt. Posture-Check ruft das Skript als Check authelia_config_drift auf (SKIP_AUTHELIA_DRIFT=1 skippt, AUTHELIA_DIFF_SCRIPT ueberschreibt den Pfad); Drift wird als Warning gemeldet, nicht Critical. Smoke-Test lokal: identische Files -> rc=0, ACL-Drift im Domain-Eintrag -> rc=1 mit unified diff. WORKFLOW.md hat jetzt eine eigene Pflicht-Sektion "Ausnahme: Authelia configuration.yml" analog zur Traefik-Dynamic-Sektion. Pflicht-Setup auf dem Host: Repo-Spiegel unter /mnt/user/services/homelab-infra/.

Sprint 7 - Off-site und 3-2-1

Status Aufgabe Bemerkung
erledigt 2026-05-28 (bewusst nicht umgesetzt) Zweites echtes Off-site (F-03) Operator-Entscheidung 2026-05-28: kein zweites Off-site. 3-2-1 ist mit Live + lokalem Borg + Hetzner + H:/-Nearline erfuellt; ein zweites Off-site wuerde nur den Fall "Hetzner-Account verloren" zusaetzlich abdecken, Aufwand/Kosten unverhaeltnismaessig fuer Familien-Homelab. Statt dessen drei Hetzner-Haertungen als Folge-TODOs (siehe docs/OFFSITE_BACKUP_OPTIONS.md Beschluss-Block). Review-Trigger sind dort definiert.
offen (Operator-Aufgabe) Hetzner-Account-Hygiene ohne 2FA Starkes, einzigartiges Passwort in Vaultwarden + Backup-Zahlungsweg + Login-Benachrichtigungen per E-Mail. 2FA bewusst nicht (analog USV: Risiko bewusst akzeptiert, Aufwand ueberwiegt Risiko-Reduktion fuer Familien-Homelab).
offen (Folge-Sprint) Borg --append-only auf Hetzner setzen Aktuell laeuft Repo appdata-critical im Mode full, custom_flags leer. Setup server-seitig in Hetzner ~/.ssh/authorized_keys mit command="borg serve --append-only". Schuetzt gegen Ransomware, die client-seitig Borg-Credentials abgreifen koennte.
erledigt 2026-05-28 H:/-Pull als Windows Scheduled Task Task KalliLab H Drive Nearline Pull registriert: taeglich 05:30, RunLevel Limited, AllowStartIfOnBatteries, StartWhenAvailable, ExecutionTimeLimit 2h. Naechster Lauf 2026-05-29 05:30. Erstlauf manuell 2026-05-27 20:45 erfolgreich, Task-Setup in docs/H_DRIVE_NEARLINE_PULL.md aktualisiert (RunLevel-Enum-Fix LeastPrivilege -> Limited).
erledigt (Routine dokumentiert) Restore-Lab-Drill quartalsweise dokumentieren docs/RESTORE_DRILL_ROUTINE.md definiert Drei-Stufen-Modell (Freshness woechentlich / Mini-Restore monatlich-bimonatlich / DR-Sanity quartalsweise), Quartals-Belegung Q1-Q4 mit Dienst-Rotation, Immich 2026-05-27 als bestaetigter Erstlauf gefuehrt, 10-Punkte-Sanity-Check, kein Host-Schedule angelegt. ops/restore-tests/schedule.md verweist jetzt auf Drill-Routine.

Offene Host-Werte

Diese Werte muessen am Unraid-Host erhoben werden, bevor die entsprechenden Aenderungen sauber umgesetzt werden:

hostname
cat /proc/cpuinfo | awk '/model name|flags/ {print; if(/flags/) exit}'
free -h
dmidecode -t baseboard | head -30
ip -br link
tailscale ip -4
lsblk -o NAME,SIZE,MODEL,SERIAL,FSTYPE,MOUNTPOINT,VENDOR
df -h /mnt/cache /mnt/disk1 /mnt/user
smartctl -a /dev/nvme0n1 | head -80
smartctl -a /dev/sdb | head -80