Files
homelab-infra/docs/MIGRATION_LOG.md
T

70 KiB

Migration Log - Homelab GitOps

Dieses Dokument ist nur noch ein historischer Verlauf. Der aktuelle operative Ablauf steht in docs/WORKFLOW.md, das Zielbild in HOMELAB_ARCHITECTURE_MASTER_V2.md.

Aktueller Endstand

  • Gitea Online ist der verbindliche Sollzustand.
  • Komodo ist der einzige produktive Stack-Manager.
  • Portainer CE ist entfernt.
  • Firefly, Firefly-Fints und Semaphore sind entfernt.
  • monitoring/ ist der einzige aktive Observability-Stack; alte Repo-Pfade ops/grafana-influxdb und ops/loki sind entfernt.
  • Borg UI ist produktiv, Dump-Automatisierung laeuft host-seitig und ein Restore-Smoke-Test wurde erfolgreich durchgefuehrt.
  • GitHub Desktop ist der bevorzugte lokale Workflow fuer Fetch, Pull, Commit und Push.
  • Mutable Image-Tags sind auf die aktuell laufenden Digests eingefroren.

Historische Meilensteine

2026-05-31 - Komodo 5xx-Spam eingegrenzt: LAN-Client statt Stack-Fehler

HomelabTraefik5xx feuerte fuer service="komodo@docker", weil wiederkehrende Komodo-UI-API-Requests ohne gueltige Session (GET /user, zeitweise POST /read/GetCoreInfo) von Traefik als 500 gezaehlt wurden. Komodo Core selbst loggte keine internen Fehler; die 500-Antwort ist ein Komodo-Auth-Pfad-Bug-on-top, aber nicht die primaere Betriebsstoerung.

  • Bestaetigt: Blackbox-Exporter erklaert nur GET / alle 15s. Waehrend monitoring-blackbox-exporter gestoppt war, verschwanden die /-200-Probes, /user-500 lief aber weiter.
  • Ausgeschlossen: cert-token-check.sh prueft keine Komodo-Domain; Komodo Periphery war nach 130s Stop nicht die Quelle; Glance war bereits vorab durch Stop-Test ausgeschlossen.
  • Core-Isolation: Bei gestopptem komodo-core liefen die Client-Requests weiter, aber Traefik loggte sie als 404 ohne komodo@docker-Service. Nach Core-Start wurden dieselben Requests wieder zu komodo@docker-500. Damit ist die Quelle ein LAN-/Client-Geraet, nicht Komodo Core als Self-Poll.
  • Lokale Client-Suche: Auf dem Windows-Operator-PC 192.168.178.103 bestanden HTTPS-Verbindungen zur WAN-IP 217.249.121.39. Brave war zunaechst plausibel, weil die Brave-Session alte Komodo-Tabs enthielt; ein Brave-Schluss beendete den 5xx-Takt jedoch nicht. Danach blieb als lokaler Kandidat nur Codex.exe mit Verbindung zur WAN-IP. Der in-app Browser zeigte keine offene Seite, daher ist der operative Fix: Codex-App/Thread nach Abschluss schliessen bzw. neu starten; falls der Takt danach wider Erwarten weiterlaeuft, naechster Schritt ist LAN-Geraetesuche am Router/Switch statt Repo-Aenderung.
  • Kein Repo-/Komodo-Fix umgesetzt: Monitoring-Regel und Komodo-Compose bleiben unveraendert. Ein Alert-Exclude fuer komodo@docker waere nur ein letzter Ausweg und wurde nicht gesetzt.
  • Smoke-Beleg waehrend der Eingrenzung: traefik, komodo-core, komodo-periphery, komodo-mongo und monitoring-blackbox-exporter liefen nach den Stop/Start-Tests wieder; komodo-mongo und traefik waren healthy.

2026-05-30 - Komodo-Bootstrap-Trockenlauf Erstlauf (F-09 Rest abgeschlossen)

Skript ist seit 2026-05-29 vorbereitet, heute erster echter Lauf auf dem Host.

  • Aufruf: bash /mnt/user/services/homelab-infra/ops/restore-tests/komodo-bootstrap-test.sh --keep-data
  • Vorlauf: --what-if zur Plan-Verifikation, danach echter Lauf, beides ohne Eingriff in den produktiven Komodo-Stack.
  • Ergebnis: SUCCESS, alle 5 Smoke-Checks gruen.
    • docker compose config valid: ok
    • Test-Mongo healthy: ok (Mongo healthy in ~6 s)
    • Mongo authenticated ping (Test-Creds): ok
    • Komodo Core HTTP status: 200 (Login-Seite ausgeliefert)
    • Test-Periphery container state: running
  • Report: /mnt/user/backups/restore-reports/komodo-bootstrap-2026-05-30.md
  • Isolation hielt wie geplant: produktive Container komodo-mongo, komodo-core, komodo-periphery unter Project komodo blieben unangetastet, ebenso /mnt/user/appdata/komodo/{mongo,core,periphery} und die produktiven KOMODO_*-Secrets. Test lief unter Project restoretest-komodo mit Wegwerf-Datadir /mnt/user/backups/restore-lab/komodo/, Wegwerf-Secrets im Test-Compose und Test-Port nur auf 127.0.0.1:19120.
  • Operator-Klick bewusst nicht von Claude uebernommen: ssh root@kallilabcore ist eine Aktionsklasse, die in CLAUDE.md ausdruecklich Operator-Anweisung verlangt. Der Auto-Mode-Classifier hat einen nicht-destruktiven SSH-Probe entsprechend blockiert. Der Operator hat den Befehl im Unraid-Webterminal selbst gestartet.
  • Bedeutung: ops/komodo/docker-compose.yml ist als Recovery-Anker fuer die Bootstrap-Stufen A-F in docs/SERVICES_RECOVERY.md jetzt belegt tauglich, nicht mehr nur angenommen tauglich. Image-Digests (mongo:7.0.32, komodo-core:2, komodo-periphery:2) und Mongo-Auth-Schema sind verifiziert.
  • Lab-Daten unter /mnt/user/backups/restore-lab/komodo/ bleiben mit --keep-data erhalten, Test-Container wurden im EXIT-Trap sauber abgeraeumt. Operator entscheidet, ob das Lab-Verzeichnis (~300 MB) entfernt wird.

Folgeschritt fuer docs/RESTORE_DRILL_ROUTINE.md: Komodo-Bootstrap-Trockenlauf passt zum quartalsweisen DR-Sanity-Check (Q4) oder als wiederholbarer Standalone-Drill. Aktuell kein Host-Schedule, Aufruf bleibt manuell.

2026-05-30 - F-10: Authelia Repo<->Host Drift-Check

Der dokumentierte "by-design"-Drift zwischen security/authelia/configuration.yml (Repo-Baseline) und /mnt/user/appdata/authelia/config/configuration.yml (Host) wird jetzt automatisch ueberwacht. Vorher: Manueller Merge auf den Host war Pflicht, aber keine Pruefung. Eine vergessene ACL-Synchronisation waere erst bei einem Login-Fehler aufgefallen.

  • Neues Skript services/authelia-diff.sh: extrahiert die access_control:-Sektion aus beiden YAMLs per awk-Block-Extractor (Top-Level-Key bis zum naechsten Top-Level-Key), normalisiert Kommentar- und Leerzeilen, vergleicht via diff -u. Default-Sektion ist access_control, weil das laut F-10 der primaere Drift-Vektor ist; per env AUTHELIA_DIFF_SECTIONS koennen weitere Top-Level-Sektionen (session, regulation, totp, ...) ergaenzt werden. OIDC-Clients, Identity-Provider und Secret-Werte bleiben bewusst aussen vor.
  • Exit-Code-Schema: 0 = ok, 1 = Drift (Diff auf stdout), 2 = Datei fehlt, 3 = Sektion fehlt, 4 = Werkzeug fehlt. Macht das Skript auch standalone nutzbar (ssh kallilab "bash /mnt/user/services/homelab-infra/services/authelia-diff.sh").
  • services/posture-check/posture-check.sh ruft das Skript am Ende des Checks-Blocks auf (check_authelia_config_drift). Drift wird als Warning gemeldet, nicht Critical, weil die produktive Authelia trotz Drift weiter laeuft und die ACL fuer schon angemeldete Sessions weiter wirkt. Skip-Mechanismus: SKIP_AUTHELIA_DRIFT=1. Pfad-Override: AUTHELIA_DIFF_SCRIPT.
  • Pflicht-Setup auf dem Host: Repo-Spiegel unter /mnt/user/services/homelab-infra/ als read-only-Clone von Gitea Micha/homelab-infra mit regelmaessigem git pull --ff-only. Default-Pfade des Skripts setzen das voraus. Ohne Repo-Spiegel meldet der Check Warning, weil die Baseline-Datei fehlt - keine stille Inaktivierung.
  • Lokaler Smoke-Test 2026-05-30 erfolgreich: identische Files -> rc=0; ACL-Drift im Domain-Eintrag scrutiny.kaleschke.info -> scrutiny-renamed.kaleschke.info -> rc=1 mit unified diff, ACL-Block korrekt extrahiert, Kommentar- und Leerzeilen rausgefiltert. False-Positive auf session.default_redirection_url-Aenderung korrekt vermieden (gehoert nicht zu access_control).
  • docs/WORKFLOW.md hat jetzt eine eigene Sektion "Ausnahme: Authelia configuration.yml" analog zur Traefik-Dynamic-Sektion. Pflicht-Workflow: 1. Repo-Aenderung + Commit + Push, 2. manueller Merge in die Host-Datei mit Erhalt der OIDC-Sektionen, 3. docker restart authelia + Login-Smoke-Test, 4. services/authelia-diff.sh muss exit 0 liefern.
  • docs/REPO_MAP.md und docs/SERVICE_CATALOG.md zeigen das Skript und den neuen Posture-Check-Eintrag.

Operator-Folgeschritt (klein, nicht heute): Repo-Spiegel /mnt/user/services/homelab-infra/ auf dem Host einrichten und in den vorhandenen gitea-bundle-mirror-6h-Plan oder einen eigenen 6h-Cron einbinden, damit das Skript einen aktuellen Vergleichsstand findet.

2026-05-29 - Stack-Hygiene Sprint: Healthchecks, Monitoring-Digests, Komodo-Bootstrap-Skript, Renovate-Vorbereitung

Vier Audit-Punkte am Stueck abgearbeitet. Pro Block: Live-Verifikation am Host, Doku im Repo.

F-15 Tier-1 Healthchecks

  • 6 Tier-1-Stacks bekommen Healthchecks: postgresql17 (pg_isready), Redis (redis-cli ping mit Auth aus dem mount), Vaultwarden (curl /alive), Gitea (wget /api/healthz), Traefik (traefik healthcheck --ping, vorher --ping=true in CLI aktiviert), Authelia (wget /api/health - Authelia v4.39 hat helper health-check entfernt, daher direkter Endpoint).
  • Erste Iteration in Vaultwarden + Authelia schlug fehl: Vaultwarden hat kein wget, Authelia kennt das helper-Subcommand nicht mehr. Probe per docker exec zeigte: Vaultwarden hat curl, Authelia hat wget. Compose entsprechend nachgezogen, zweiter Lauf gruen.
  • Komodo-Stack-Workspaces fuer postgresql17 (124 commits behind) und gitea (52 commits behind) wurden Komodo-seitig nicht automatisch gepullt. Manuell ueber git pull --ff-only plus cp der aktuellen Compose-Datei aus dem Host-Repo-Clone in den Stack-Workspace synchronisiert, dann docker compose up -d. Gitea-Workspace hatte zusaetzlich untracked Doku-Files; nur die im aktuellen Master tracked-en Files entfernt, nicht via git clean -fd. Workspace-Drift selbst ist nicht heute Auftrag, aber als Folge-Befund notiert.
  • Endstand Live: alle 6 Healthchecks healthy.

F-07 Monitoring-Stack Digest-Pinning

  • 9 Container in monitoring/docker-compose.yml per Tag@sha256 gepinnt (prometheus, alertmanager, alertmanager-ntfy-bridge, blackbox-exporter, loki, promtail, grafana, node-exporter, cadvisor; plus zweiter python:3.13-alpine im Bootstrap-Dashboard-Importer). InfluxDB war bereits gepinnt.
  • Digests aus den laufenden Containern per docker inspect ... .Config.Image + docker image inspect ... .RepoDigests ausgelesen, damit die Pins exakt dem Live-Stand entsprechen.
  • Kein Recreate ausgeloest, weil die Images identisch sind; nur die Compose-Datei ist jetzt reproduzierbar wie die Tier-1-Stateful-Stacks.

F-09 Rest - Komodo-Bootstrap-Trockenlauf-Skript

  • ops/restore-tests/komodo-bootstrap-{compose.test.yml,test.sh,plan.md,runbook.md} analog zum Immich-Restore-Test-Muster angelegt.
  • Test-Compose nutzt dieselben Image-Digests wie Produktion (mongo:7.0.32, komodo-core:2, komodo-periphery:2), isoliert unter Compose-Project restoretest-komodo, Test-Port nur 127.0.0.1:19120, Test-Periphery ohne docker.sock-Mount und ohne /mnt/user/services-Mount - kann produktive Container nicht managen.
  • Wegwerf-Secrets sind im Compose hardcodiert, produktive KOMODO_*-Werte werden nicht beruehrt.
  • Smoke-Test-Kriterien: docker compose config valid, Mongo healthy, Mongo Auth-Ping ok, Core HTTP 200/302/303/401, Periphery container running.
  • Erster Lauf bleibt manueller Operator-Schritt.

F-12 Renovate-Bot (live)

  • Repo-Config in renovate.json (Repo-Root): nur extends, packageRules, ignorePaths, manager file patterns, labels, rangeStrategy. Bot-Config separat in ops/renovate/bot-config.js: platform, endpoint, autodiscover=false, repositories=["Micha/homelab-infra"], gitAuthor, Concurrent-Limits. Trennung war noetig: Renovate liest die renovate.json im Repo als REPO-Config; Bot-Felder darin wurden als "this repo is disabled" fehlinterpretiert (Repository result: forbidden, status: disabled).
  • ops/renovate/run-renovate.sh als One-Shot-Container-Wrapper. Wichtige Haertungen waehrend des Setups:
    • --add-host git.kaleschke.info:192.168.178.58: Renovate-Container kann den Hostname sonst nicht aufloesen (EAI_AGAIN). Analog zur extra_hosts-Loesung in der Komodo-Compose.
    • --env-file statt -e RENOVATE_TOKEN=...: Token war sonst in ps und docker inspect sichtbar.
    • chmod 0777 auf /mnt/user/services/renovate/state: Renovate-Image laeuft als uid 12021 (ubuntu), kann root-owned Mount sonst nicht beschreiben.
  • Live-Setup am Host:
    • Service-Account renovate (uid 2, kein Admin) ueber gitea admin user create angelegt.
    • Collaborator-Status mit Write-Permission auf homelab-infra (initialer DB-Insert hat den Gitea-Permissions-Cache nicht aktualisiert; Renovate sah permissions.push=false und brach mit "Repository does not permit pull or push" ab; saubere Loesung war Operator-UI-Klick "Entfernen + neu hinzufuegen", was den Cache konsistent aktualisiert; Befund-Bestaetigung via Doku-Studium lib/modules/platform/gitea/index.ts: die Push-Check ist hardcoded, kein Bypass moeglich).
    • Personal-Access-Token mit Scopes read:user,write:repository,write:issue, in /mnt/user/appdata/secrets/renovate_token.txt (chmod 600). Token wurde einmal rotiert, weil der Wert beim ersten Erzeugen im SSH-Output sichtbar war.
    • User-Script renovate-six-hourly mit Cron 20 */6 * * * live in /etc/cron.d/root.
  • Erstlauf 2026-05-29 erfolgreich: 5 PRs (mongo digest, mongo 7.0.32->7.0.34, postgres digest, postgres 17.9->17.10, minor-and-patch-updates gruppiert), 1 Issue "Renovate Dependency Dashboard", 8 Branches (drei Major-Branches warten auf naechsten Lauf wegen prConcurrentLimit=5). Komodo-Major-Updates wurden korrekt durch packageRule unterdrueckt.
  • docs/RENOVATE.md zeigt die ursprueglichen 5 Operator-Schritte fuer Neuaufsetzen bzw. Disaster Recovery.

2026-05-29 - Borg-Source /local/appdata/homepage verspaetet entfernt + Removal-Checkliste in WORKFLOW

  • Befund aus den ersten Tagen scharfer Alert-Pipeline: HomelabBorgLastJobCompletedWithWarnings firing fuer die letzten vier Borg-Laeufe (26.05.-29.05.), jeweils Exit-Code 107.
  • Ursache im Borg-UI-Logfile backup_job_39_*.log: "/local/appdata/homepage: stat: [Errno 2] No such file or directory". Borg-UI-Source-Liste enthielt seit der Homepage-Entfernung am 25.05. weiterhin den Eintrag /local/appdata/homepage; der Appdata-Pfad war aber bereits nach _archive/homepage-removed-2026-05-25/ verschoben.
  • Operator hat den Eintrag in der Borg-UI manuell entfernt; Source-Liste jetzt 23 statt 24 Eintraege, homepage nicht mehr drin. Naechster Borg-Lauf 2026-05-30 04:30 sollte wieder completed ohne Warning sein.
  • Backups waren nicht gefaehrdet: trotz Exit-Code 107 wurden alle anderen 23 Quellen sauber archiviert (Stats Job 39: 100.895 Dateien, 26.72 GB Original, 317 MB deduplicated).
  • Erkenntnis: bei Stack-Removal wurde die Borg-Source-Liste damals nicht mit-aufgeraeumt. docs/WORKFLOW.md um neuen Abschnitt "Service-Removal-Checkliste" erweitert, der die Borg-UI-Source-Bereinigung explizit als Pflichtschritt 8 nennt (zusammen mit allen anderen Schritten wie Komodo-Destroy, Gitea-Webhook, Authelia-ACL, Blackbox-Target, Doku).
  • Positiv-Befund: die ntfy-Push-Pipeline (Cron */5 Textfile-Export -> node-exporter -> Prometheus -> Alertmanager -> ntfy-Bridge), die am 2026-05-27 scharfgeschaltet wurde, hat den Drift binnen 24 h sichtbar gemacht. Das ist der intendierte Mechanismus.

2026-05-28 - H:/-Pull als Windows Scheduled Task aktiviert

  • Task KalliLab H Drive Nearline Pull registriert auf dem Operator-Windows-PC: taeglich 05:30 (nach dem Borg-Dump-Fenster um ca. 04:00), RunLevel Limited, AllowStartIfOnBatteries, DontStopIfGoingOnBatteries, StartWhenAvailable, ExecutionTimeLimit 2 h. Naechster Lauf 2026-05-29 05:30.
  • Repo-Doku docs/H_DRIVE_NEARLINE_PULL.md Status auf "produktiv" gesetzt, Register-Snippet auf den tatsaechlich ausgefuehrten Befehl korrigiert (PowerShell-Enum LeastPrivilege -> Limited; alter Snippet haette beim ersten Aufruf einen Parameter-Binding-Fehler geworfen).
  • Verifikation am Windows-PC: Get-ScheduledTask zeigt State Ready, Trigger-Start 2026-05-28T05:30, RunLevel Limited.
  • Kein Eingriff am Host noetig; SMB-Quelle und H:/-Ziel waren bereits vorbereitet.

2026-05-28 - Zweites Off-site bewusst nicht umgesetzt

  • Operator-Bewertung: 3-2-1-Regel ist mit aktueller Topologie erfuellt (Live + lokales Borg-Repo + Hetzner-Borg + H:/-Nearline = 4 Kopien / 3 Medien / 1 Off-site).
  • Ein zweites Off-site wuerde ausschliesslich das Szenario "Hetzner-Account verloren" zusaetzlich abdecken. Eintrittswahrscheinlichkeit niedrig (etablierter deutscher Anbieter, dokumentierter Zahlungsweg). Aufwand und Kosten unverhaeltnismaessig fuer Familien-Homelab.
  • Beschluss in docs/OFFSITE_BACKUP_OPTIONS.md mit Review-Triggern dokumentiert; F-03 in docs/AUDIT_2026-05-25_TODO.md von "offen" auf "erledigt (bewusst nicht umgesetzt)".
  • Stattdessen drei Folge-TODOs zur Haertung der bestehenden Topologie:
    • Hetzner-Account-Hygiene: starkes Passwort + Backup-Zahlungsweg + Login-Benachrichtigungen. Bewusst keine 2FA (Operator-Entscheidung analog USV-Risiko-Akzeptanz).
    • Borg --append-only auf Hetzner pruefen. Befund: Repo appdata-critical laeuft aktuell im Mode full, custom_flags leer. Setup waere server-seitig in Hetzner-authorized_keys.
    • H:/-Pull als Windows Scheduled Task aktivieren (Skript und Doku ready, Erstlauf 2026-05-27 erfolgreich, Task selbst noch nicht angelegt).
  • Bewusst NICHT angefasst: laufende Backup-Pipeline (kein Test-Restore, kein Modus-Wechsel ohne Folge-Sprint).

2026-05-28 - paperless-gpt und BentoPDF bewusst behalten

  • Befund: Beide Container laufen Up 3 days, aber 0 Traefik-Zugriffe in den letzten 7 Tagen und kein User-LLM-Event in den paperless-gpt-Logs. BentoPDF-Logs zeigen ausschliesslich Docker-Healthchecks.
  • Resource-Footprint vernachlaessigbar: paperless-gpt 34 MB RAM, bentopdf 4 MB RAM, beide 0 % CPU.
  • Operator-Entscheidung 2026-05-28 (gegen die Nicht-Nutzung): beide behalten.
    • paperless-gpt: bleibt aktiv bis Paperless-NGX 3.0 verfuegbar ist. Paperless 3.0 wird native KI-Features mitbringen; danach neu entscheiden, ob paperless-gpt noch noetig ist oder abgeloest werden kann.
    • bentopdf: bleibt aktiv als situatives PDF-Werkzeug; Footprint zu klein, um eine harte Entfernung zu rechtfertigen.
  • Doku-Anker in docs/SERVICE_CATALOG.md ergaenzt, damit die Frage in 6 Monaten nicht erneut als "warum laeuft das?" auftaucht.

2026-05-28 - Plex Server Reclaim und Remote Access deaktiviert

  • Befund beim Versuch, Remote Access in der Plex-UI zu deaktivieren: Plex-Server war seit 18.05.2026 13:18 nicht mehr mit einem Plex.tv-Account geclaimt. Preferences.xml 391 Bytes, ohne PlexOnlineMail/PlexOnlineUsername/PlexOnlineToken. Login als Xeridos lieferte "Keine Berechtigung" auf den lokalen Server. Zusaetzlich waren die library_sections leer (Backups vom 19./22./28.05. ebenfalls ~370 KB statt MBs); die Bibliotheks-Konfiguration war seit dem 18.05. weg. Filmdateien unter /mnt/user/media/* blieben unangetastet (833 Verzeichnisse, ~1.7 TB).
  • Reclaim als Xeridos durchgefuehrt: Operator-Token via plex.tv/claim erzeugt, am Host als Shell-Inline-ENV beim docker compose up -d --force-recreate plex mitgegeben. Token wurde nicht in .env, nicht in Compose, nicht in Komodo-Stack-ENV geschrieben. Nach Erfolg sauberer zweiter Recreate ohne Token, damit docker inspect-Snapshot keinen Token mehr enthaelt. Bash-History defensiv geleert.
  • Endstand laut Preferences.xml: PlexOnlineUsername="Xeridos", PlexOnlineMail="michideheld@gmx.de", PlexOnlineHome="1", PublishServerOnPlexOnlineKey="0" (Remote Access aus).
  • Operator hat im Anschluss die Bibliotheken neu angelegt (/data/movies, /data/Heimatfilme) und Remote Access in der Plex-UI auf "deaktiviert" gesetzt; Metadata-Cache wuchs in den ersten 18 Minuten auf 630 MB.
  • Plex bleibt damit strikt LAN/Tailscale-only, konsistent zur FRITZ!Box-Bereinigung vom selben Tag. Smart-TVs (Schlaf-/Wohnzimmer) finden den Server ueber WLAN-LAN per mDNS/Plex-GDM unveraendert.
  • HOMELAB_ARCHITECTURE_MASTER_V2.md Sektion 13 enthaelt die ausfuehrliche Recovery-Geschichte. docs/SERVICE_CATALOG.md und Sektion 7.4 auf "LAN/Tailscale-only, Remote Access aus" praezisiert.

2026-05-28 - FRITZ!Box-Portfreigaben bereinigt

  • WAN-Soll auf eine einzige Freigabe reduziert: 443/tcp -> 192.168.178.58:443 (Traefik HTTPS).
  • 80/tcp aus FRITZ!Box-UI entfernt. Validierung: Mobilfunk-Test ergibt Timeout auf http://vault.kaleschke.info, https://vault.kaleschke.info weiter erreichbar; lokal greift Traefik-Redirect 80->443 nach wie vor. Cloudflare-DNS-Challenge braucht kein Port 80.
  • 222/tcp bleibt bewusst nicht eingerichtet. Begruendung: Tailscale ist Operator-Pfad, GitHub-Push-Mirror michaelkaleschke-spec/homelab-infra deckt Repo-Bootstrap-Pfad ab, Gitea-Bundles unter /mnt/user/backups/git-bundles/gitea decken Offline-Restore ab. HOMELAB_ARCHITECTURE_MASTER_V2.md Sektion 10 entsprechend mit "Tailscale-only, bewusst nicht WAN-freigegeben" praezisiert.
  • UPnP-Selbstfreigabe-Recht fuer PC-192-168-178-71 (Hostname VONETS.COM, MAC 00:17:13:2F:61:96) deaktiviert. Identifiziert als VONETS-WiFi-Bridge, vermutlich Bridge-Anbindung zum SolarEdge-Wechselrichter. SolarEdge-Cloud-Sync ist outbound und benoetigt keine UPnP. Aktuell waren 0 Selbstfreigaben aktiv; die Aenderung ist praeventiv gegen kuenftige Anforderungen.
  • docs/NETWORK_INVENTORY.md, docs/FRITZBOX_PORT_CORRECTION_PLAN.md und docs/AUDIT_2026-05-25_TODO.md Sprint 4 entsprechend nachgezogen.
  • Bewusst NICHT angefasst: FRITZ!OS 8.21 Update (Service-Fenster), IPv6-Exposure (separater Folgeschritt), WAN-Ausfallschutz (bewusst aus).

2026-05-27 - Monitoring-Alerts live, Gitea-Bundle-Cron live, H:/-Pull live

Drei Audit-TODOs gleichzeitig auf "erledigt" gezogen; alle Aenderungen mit Host-Smoke verifiziert.

Monitoring-Alerts (Borg-Stale / Cert-Expiry / Container-Down)

  • Auf dem Host neuer User-Script export-prometheus-textfile-5min mit Cron */5 * * * * angelegt. Schreibt /mnt/user/services/posture-check/textfile/homelab.prom.
  • Repo: services/posture-check/export-prometheus-textfile.sh setzt jetzt vor dem mv per chmod 644, damit node-exporter (nobody:65534) lesen kann. Vorher 0600 root:rootnode_textfile_scrape_error 1.
  • monitoring-prometheus wurde einzeln per docker restart neu gestartet, um den stale file handle auf der gebundenen alerts.yml zu loesen. Kein Stack-Down. promtool check rules SUCCESS 14 rules, lastConfigTime 2026-05-27T18:33:06Z. Aktive Alerts: 1 firing (HomelabTraefik5xx aus dem 2026-05-20-Befund), 1 pending (HomelabBorgLastJobCompletedWithWarnings durch completed_with_warnings-Status des letzten Borg-Laufs).
  • Pipeline end-to-end: Textfile-Skript ⇒ node-exporter Textfile-Collector ⇒ Prometheus ⇒ alerts.yml-Regeln.

Gitea-Bundle-Schedule

  • User-Script gitea-bundle-mirror-6h mit Cron 10 */6 * * * (00:10/06:10/12:10/18:10).
  • Repo: ops/borg-ui/scripts/gitea-bundle-mirror.sh schreibt Bundles und Sidecars jetzt chmod 644 statt 600. Begruendung: Bundle-Inhalt ist Git-Historie ohne Secrets (durch .gitignore abgedeckt), nicht sensibler als die uebrigen 0644-Dumps. Damit funktioniert der Nearline-Pull ueber SMB.
  • Existierende Bundles wurden manuell auf 0644 angehoben. Erster Cron-Lauf 2026-05-27 18:41 UTC erfolgreich: 4 Bundles, Checksums OK.

H:/ Nearline-Pull

  • Erster scharfer Lauf 2026-05-27 20:25 zeigte vier Permission-Befunde: unraid-flash-config.* (4 Files, by-design 0600), filebrowser.bolt.dump (0640, Source erbt), und alle 10 Gitea-Bundle-Files (0600).
  • Repo: ops/h-drive-nearline/pull-critical-backups.ps1 excluded jetzt die unraid-flash-config.*-Familie ueber /XF (Restore-Quelle bleibt Hetzner-Borg). ops/borg-ui/scripts/pre-backup-dumps.sh setzt alle Dumps via atomic_write per Default auf 0644, Flash-Config-Familie explizit mit atomic_write target tmp 600.
  • Existierende Files am Host nachtraeglich auf 0644 angehoben.
  • Zweiter Lauf 2026-05-27 20:45: beide Robocopy-Jobs Exit 1, 19 Borg-Dumps + 10 Gitea-Bundle-Files unter H:\kallilab-nearline-backups. Report-Tabellen-Quirk in PowerShell durch & robocopy @args | Out-Null behoben (Live-Output landete vorher in $results).
  • docs/H_DRIVE_NEARLINE_PULL.md mit Erstlauf-Befund, gefixter Erwartungs-Liste und expliziter Out-of-Scope-Anmerkung fuer Flash-Config aktualisiert.
  • Windows Scheduled Task taeglich 05:30 bleibt bewusst offen bis zur Operator-Bestaetigung.

Was bewusst NICHT angefasst wurde

  • Authelia/OIDC/CrowdSec/Nextcloud-Haertung (geparkt).
  • Hermes (Review 2026-07-25).
  • USV (Risiko bewusst akzeptiert).
  • FRITZ!Box-/Plex-/UI-Punkte (Punkt 5 fuer morgen frueh).
  • unraid-flash-config.tar.gz bleibt bewusst 0600 und ausserhalb des Nearline-Scopes.

2026-05-27 - Vorbereitungsdokumente FRITZ!Box-Korrektur und Off-site-Optionen

  • Reine Doku-Aenderung; kein Router-, Provider- oder Host-Eingriff.
  • docs/FRITZBOX_PORT_CORRECTION_PLAN.md neu angelegt: Korrektur-Plan fuer drei Punkte (80/tcp entfernen, 222/tcp nicht ergaenzen solange Tailscale stabil, UPnP-Selbstfreigabe PC-192-168-178-71 deaktivieren). Operator-Go ausstehend; jede UI-Aenderung wird gesondert dokumentiert.
  • docs/OFFSITE_BACKUP_OPTIONS.md neu angelegt: Entscheidungsvorlage fuer zweites Off-site-Ziel mit drei Optionen (rsync.net Borg-Plan, BorgBase EU2, rotierende Cold-Platte). Bewertung gegen Provider-Trennung, Standort, Preis und Konto-Risiko; Empfehlung rsync.net oder Cold-Platte; BorgBase EU2 explizit nicht empfohlen wegen gleichem Anbieter. Kein Provider gebucht, keine Kosten ausgeloest.
  • docs/REPO_MAP.md um beide neuen Dokumente ergaenzt.
  • docs/AUDIT_2026-05-25_TODO.md Sprint 4 (FRITZ!Box) und Sprint 7 (Off-site) mit Verweis auf die neuen Vorbereitungsdokumente nachgezogen.

2026-05-27 - Doku-Sprint Bootstrap / Family-View / Onboarding / Drill-Routine

  • Reine Doku-Aenderung; kein Compose-, Secret-, Host- oder Router-Eingriff.
  • docs/SERVICES_RECOVERY.md "Komodo Bootstrap" auf linearen Stufenpfad A-F ausgebaut: Recovery-Anker bleibt ops/komodo/docker-compose.yml, Self-Stack ist explizit kein Anker, Secret-Restore-Reihenfolge verweist auf docs/SECRETS_MAP.md Stack-ENV-only-Sektion, Validierungs-Kommandos ergaenzt. Trockenlauf-Idee als Folgeaufgabe eingetragen, kein Repo-Skript dafuer.
  • docs/DISASTER_RECOVERY.md Phase 4 Stufe 3 verweist explizit auf den Bootstrap-Pfad in docs/SERVICES_RECOVERY.md und auf die Stack-ENV-only-Sektion in docs/SECRETS_MAP.md.
  • docs/FAMILY_VIEW_DASHBOARD.md neu angelegt: Spezifikation fuer homelab-family-view-Dashboard, 8 Panels (Endpoints up, Borg-Frische, Cert-Tage, Kritische Container, Disk-Fuellung, Endpoint-Tabelle, Cert-Tabelle, Container-Tabelle), PromQL-Queries, Thresholds, Build-Reihenfolge. Bewusst noch kein monitoring/grafana/dashboards/family-view.json angelegt, weil Borg-Stale-/Cert-Expiry-/Container-Down-Metriken laut Sprint 3 noch "in Arbeit" sind.
  • docs/FAMILY_ONBOARDING.md final redigiert: Status auf "Final-Stand vor Wochenend-Einladung", 2FA-Beschreibung auf App-eigene 2FA praezisiert (kein SSO-Versprechen, weil Authelia-OIDC weiter geparkt ist), neuer "Bewusst nicht versprochen"-Block (kein Einheits-Login, kein 24/7-SLA, kein Hotline-Support, keine Datenweitergabe).
  • docs/RESTORE_DRILL_ROUTINE.md neu angelegt: Drei-Stufen-Modell (Freshness woechentlich / Mini-Restore monatlich-bimonatlich / DR-Sanity quartalsweise), Quartals-Kadenz Q1-Q4 mit Dienst-Rotation, bestaetigte Mini-Restores (Vaultwarden, Gitea, Paperless 2026-05-07; Immich 2026-05-27), 10-Punkte-Sanity-Check, Abbruch-Regel mit Verweis auf docs/GITOPS_DRIFT_RUNBOOK.md. Kein Host-Schedule angelegt, nur Doku.
  • ops/restore-tests/schedule.md verweist jetzt auf docs/RESTORE_DRILL_ROUTINE.md als Quelle der Quartals-Belegung.
  • docs/REPO_MAP.md um docs/FAMILY_VIEW_DASHBOARD.md, docs/RESTORE_DRILL_ROUTINE.md und docs/IMMICH_RESTORE_TEST.md ergaenzt.
  • docs/AUDIT_2026-05-25_TODO.md aktualisiert: Sprint 2 "Komodo-Bootstrap-Pfad beschreiben", Sprint 3 "Family-View Dashboard definieren", Sprint 4 "Familien-Onboarding schreiben" und Sprint 7 "Restore-Lab-Drill quartalsweise dokumentieren" jeweils auf "erledigt".
  • Geparkte Punkte bleiben unveraendert: Authelia-2FA/OIDC/CrowdSec, Nextcloud-Haertung, Hermes (Review 2026-07-25), USV-Anschaffung.

2026-05-27 - Immich Restore-Smoke-Test praktisch verifiziert (F-11)

  • Erster echter Immich-Restore-Smoke-Test gegen das produktive Borg-Archiv erfolgreich: Tägliche-Sicherung-2026-05-27T04:30:06.778, Report /mnt/user/backups/restore-reports/immich-2026-05-27.md.
  • Validiert wurden Borg-Extract von local/borg-dumps/latest/immich.dump, Import in isolierten tensorchord/pgvecto-rs:pg14-v0.2.0 Test-Postgres, Start des Immich-Servers ohne ML und ohne Traefik, HTTP 200 auf 127.0.0.1:12283, Login-Marker, 11977 Assets und 1 User im Test-DB-Check.
  • Produktive Container und produktive Foto-Pfade wurden nicht angefasst; Testdaten und Testcontainer wurden nach Erfolg bereinigt.
  • Im Lauf wurden Restore-Test-Haertungen umgesetzt: Borg-known_hosts aus /data/known_hosts wird fuer SSH-Trust genutzt, completed_with_warnings-Archive gelten als verwendbare Restore-Quelle, Postgres-Startfenster werden retry-faehig behandelt, Immich-v2-Upload-Marker werden im leeren Test-Mount erzeugt und Smoke-Checks schlagen bei HTTP-/Marker-Fehlern hart fehl.
  • docs/IMMICH_RESTORE_TEST.md, docs/RESTORE_MATRIX.md, ops/restore-tests/schedule.md und docs/AUDIT_2026-05-25_TODO.md nachgezogen; F-11 ist damit abgeschlossen. Voll-Restore inklusive Foto-Dateien bleibt ein separater DR-Drill.

2026-05-27 - FRITZ!Box-Portfreigaben gegen Repo-Soll abgeglichen

  • FRITZ!Box-UI Internet -> Freigaben -> Kallilabcore geprueft: aktiv sind HTTP-Server TCP 80/tcp und HTTPS-Server TCP 443/tcp auf 192.168.178.58.
  • Repo-Soll aus docs/NETWORK_INVENTORY.md ist nur 443/tcp plus optional gewolltes Gitea-SSH 222/tcp. Der aktuelle Zustand weicht ab: 80/tcp ist offen, 222/tcp fehlt.
  • Kallilabcore ist nicht als Exposed Host markiert und erlaubt keine selbststaendige Portfreigabe. PC-192-168-178-71 erlaubt selbststaendige Portfreigabe, hat aber 0 aktiv.
  • Keine FRITZ!Box-Aenderung vorgenommen. Router-Korrektur bleibt ein produktiver Operator-Schritt nach ausdruecklicher Freigabe.

2026-05-26 - Immich Restore-Smoke-Test vorbereitet (F-11)

  • docs/IMMICH_RESTORE_TEST.md und ops/restore-tests/immich-plan.md/immich-runbook.md beschreiben den geplanten Immich-Mini-Restore: immich.dump aus Borg, isolierter pgvecto-rs-Test-Postgres, Test-Redis, Immich-Server ohne ML, lokaler Port 127.0.0.1:12283, keine produktiven Foto-Mounts.
  • ops/restore-tests/immich-restore-test.sh, immich-restore-test.ps1 und immich-compose.test.yml wurden vorbereitet; der Dispatcher kennt immich --what-if.
  • Lokal verifiziert: Bash-Syntax, run-restore-checks.sh immich --what-if, PowerShell-Dispatcher -Mode immich -WhatIf, Docker-Compose-Render und Policy-Check. Kein echter Host-Restore, kein Borg-Extract, kein Produktiv-Container-Eingriff.
  • Host-Preflight 2026-05-27: Host-Clone per Fast-forward auf c5d231a, immich.dump 66M, /mnt/user/backups ca. 3.7T frei, run-restore-checks.sh immich --what-if erfolgreich. Kein echter Restore-Lauf.
  • F-11 bleibt fachlich offen bis zum ersten Host-Lauf mit Report unter /mnt/user/backups/restore-reports/immich-YYYY-MM-DD.md.

2026-05-27 - H:/ Nearline-Pull vorbereitet

  • docs/H_DRIVE_NEARLINE_PULL.md und ops/h-drive-nearline/pull-critical-backups.ps1 definieren den Windows-seitigen Pull von \\192.168.178.58\backups\borg\dumps\latest und \\192.168.178.58\backups\git-bundles\gitea nach H:\kallilab-nearline-backups.
  • SMB-Quelle \\192.168.178.58\backups und H:/ sind erreichbar; -WhatIf prueft den Plan ohne Kopie.
  • Kein Scheduled Task angelegt und kein echter Kopierlauf gestartet. Empfohlen ist taeglich 05:30 nach dem Borg-Dump-Fenster, Aktivierung erst nach Operator-Sichtpruefung.

2026-05-27 - Storage Layout als Active v1.4 gefuehrt

  • docs/STORAGE_LAYOUT.draft.md wurde zu docs/STORAGE_LAYOUT.md umbenannt. Das Dokument war inhaltlich bereits als Active markiert; Version 1.4 entfernt den formalen Draft-Blocker.
  • Physikalische Disk-Werte aus docs/HARDWARE_INVENTORY.md und Host-Readout uebernommen: Cache Samsung 970 EVO Plus 1.8T XFS, Disk1 WDC WD60EFAX 5.5T XFS auf md1p1, Parity TOSHIBA HDWG480 7.3T, Boot Samsung Flash Drive 59.8G FAT32, H:/ als Nearline-Ziel.
  • docs/AUDIT_2026-05-25_TODO.md Sprint 2 fuer Storage-Layout und Disk-/Share-Baseline auf erledigt gesetzt. Retention-Kalibrierung, Monitoring-Schwellen und RESTORE_MATRIX-Detailklassifikation bleiben normale Folgeaufgaben.

2026-05-27 - F-08 Alert-Regeln vorbereitet

  • services/posture-check/export-prometheus-textfile.sh erzeugt Textfile-Metriken fuer Borg-Backup-Frische und kritische Container unter /mnt/user/services/posture-check/textfile/homelab.prom.
  • monitoring/docker-compose.yml aktiviert den Node-Exporter-Textfile-Collector. monitoring/prometheus/alerts.yml enthaelt vorbereitete Alerts fuer Borg-Stale, Borg-Fehlerstatus, Borg-Warnstatus, Textfile-Stale, Critical-Container-Down und TLS-Cert-Expiry 21/7 Tage.
  • Host-Smoke 2026-05-27: Skript erzeugt homelab.prom, alle gelisteten kritischen Container melden 1, Borg-Status ist completed_with_warnings und wird als Warning statt Critical modelliert.
  • Kein Monitoring-Redeploy und kein Scheduled Task in diesem Schritt. Abschluss erfolgt nach Host-Schedule, Prometheus-Reload und Testalert.

2026-05-26 - Audit F-16 und F-20 abgeschlossen (Doku-only)

  • F-16: infra/redis-Etikett auf die Realitaet abgeglichen. docs/SERVICE_CATALOG.md, docs/REPO_MAP.md, HOMELAB_ARCHITECTURE_MASTER_V2.md Sektion 13 und docs/DISASTER_RECOVERY.md Bootstrap-Stufe 2 beschreiben Redis jetzt als "primaer Paperless-Redis (App-Cache); historisch als shared angelegt, faktisch nur von Paperless genutzt". Immich, Nextcloud, Mealie eigene Redis-Instanzen; Authelia bewusst ohne Redis. Keine Compose-Aenderung.
  • F-20: Restore-Wege fuer Stack-ENV-only Secrets explizit gemacht. Neuer Abschnitt 6.2.1 Restore-Quellen fuer Stack-ENV-Werte in docs/DISASTER_RECOVERY.md (Reihenfolge Komodo-Mongo-Dump -> Vaultwarden -> externe Notiz, Komodo-Sonderfall, Paperless als Hauptanwendung). Neuer Abschnitt Stack-ENV-only Secrets - Restore-Wege in docs/SECRETS_MAP.md mit Tabelle je Stack (Paperless, Immich, Mail-Archiver, Speedtest, Komodo, Hermes, Glance). Glance-Widget-Tokens explizit als rebuildbar markiert. Konkrete Werte werden nirgendwo dokumentiert.
  • docs/AUDIT_2026-05-25_TODO.md Sprint 6 entsprechend auf "erledigt" gestellt.
  • Kein Eingriff in ops/borg-ui/scripts/gitea-bundle-mirror.sh, kein Gitea-Bundle-Trockenlauf, keine SSH-/Host-Pruefung.

2026-05-26 - FRITZ!Box-/H:/-/Family-Onboarding-Doku-Update

  • docs/NETWORK_INVENTORY.md mit FRITZ!Box-Baseline gefuellt: FRITZ!Box 7590, FRITZ!OS 8.21 (Update gemeldet, nicht eingespielt), Telekom DSL ~87/36 Mbit/s, 36 aktive Heimnetz-Geraete, LAN 1-4 verbunden, WLAN Fritzi, Gast-WLAN inaktiv, Telefonie/DECT aktiv, Ausfallschutz nicht eingerichtet, USB nicht verbunden, 2 Portfreigaben aktiv. Soll fuer Portfreigaben: nur 443/tcp und 222/tcp auf 192.168.178.58.
  • docs/EXTERNAL_DEPENDENCIES.md um Telekom-DSL und FRITZ!Box 7590 als WAN-/Router-Abhaengigkeit erweitert; Ausfall-Szenario "Telekom-DSL / FRITZ!Box gestoert" ergaenzt.
  • docs/CAPACITY_AND_LIFECYCLE.md um Abschnitt "H:/ als zusaetzliches lokales Backup-Ziel" ergaenzt. Bewertung: H:/ ist als zweite lokale Nearline-Kopie und Freeze-Sicherung sinnvoll, aber bewusst kein Offsite-Ersatz und kein CIFS-Hard-Mount am Unraid (STORAGE_LAYOUT §12.6). Pull-Modell vom Windows-PC bleibt der getestete Weg (vgl. Disk1 Phase 2 Freeze 2026-05-25).
  • docs/FAMILY_ONBOARDING.md von Tabellen-Entwurf auf familienverstaendlichen Begruessungstext umgestellt: kurze App-Erklaerungen, konkrete Was-tun-Wenn-Anleitungen (Webseite weg, Passwort vergessen, 2FA verloren, Foto-Backup haengt, Browser-Warnung), "Was du nicht musst"-Block, Hinweis fuer geplante Wochenend-Einladung.
  • docs/AUDIT_2026-05-25_TODO.md Leitplanken aktualisiert: Authelia 2FA/OIDC/CrowdSec und Nextcloud-2FA-Haertung werden in diesem Zyklus nicht angefasst (Operator-Vorgabe). Hermes-Agent geparkt mit Review-Deadline 2026-07-25. USV-Risiko bewusst akzeptiert. Sprint 4 um H:/-Bewertung und FRITZ!Box-Portfreigaben-Abgleich erweitert. Neue Sprints 6 (geparkte Apps) und 7 (Off-site) ergaenzt.
  • Keine Live-/Compose-Aenderung in diesem Commit; nur Doku.

2026-05-26 - USV-Risiko bewusst akzeptiert

  • Operator-Entscheidung: aktuell wird keine USV angeschafft.
  • Der Befund bleibt technisch unveraendert: keine funktionierende USV-Abschaltung nachgewiesen. Power-Loss-Risiko fuer Docker-/DB-State und laufende Writes wird bewusst akzeptiert und bei spaeteren Reviews neu bewertet.

2026-05-26 - Borg-Passphrase offline gesichert

  • Operator bestaetigt: Die Borg-Passphrase ist offline/off-system gesichert und kann ohne Host oder Vaultwarden wiederhergestellt werden.
  • Doku aktualisiert nur den Sicherungsstatus; Secret-Wert und Ablageort bleiben bewusst ausserhalb des Repos.

2026-05-26 - Gitea-Bundle-Mechanik definiert

  • ops/borg-ui/scripts/gitea-bundle-mirror.sh ergaenzt: erstellt verifizierte git bundle-Artefakte fuer alle bare Gitea-Repositories, schreibt Checksums und einen Markdown-Report.
  • Zielpfad ist /mnt/user/backups/git-bundles/gitea; dieser Pfad muss in den Borg/off-site Scope aufgenommen und hostseitig geplant werden.
  • docs/SERVICES_RECOVERY.md und docs/RESTORE_MATRIX.md dokumentieren Bundles jetzt als zweite Repo-Bootstrap-Schicht neben dem GitHub-Mirror.
  • Host-Erstlauf nach Skript-Fix erfolgreich: 4 Bundles erzeugt (homelab-infra, homelab, homepage, smart-home-kalli), Checksums OK, homelab-infra.bundle in Restore-Lab geklont und git fsck sauber. Offen bleibt die dauerhafte Schedule-Einbindung.

2026-05-26 - Audit-Baseline-Tag gesetzt

  • Der Stand nach Hardware-/Capacity-Baseline, Policy-Triage und Recovery-Doku wurde als audit-2026-05-25-baseline markiert und nach Gitea gepusht.

2026-05-26 - Externe Abhaengigkeiten und Services-Recovery baseline dokumentiert

  • docs/EXTERNAL_DEPENDENCIES.md von Template auf Betreiber-Baseline angehoben: Domain, Cloudflare, Hetzner, GitHub-Mirror, Tailscale, GMX, Let's Encrypt, Registries, Plex und mobile Push-Pfade sind mit Ausfallwirkung und Notfallplan dokumentiert.
  • docs/SERVICES_RECOVERY.md finalisiert den Komodo-Bootstrap-Anker: ops/komodo/docker-compose.yml bleibt verbindlich; der komodo-Self-Stack hat keinen aktiven Gitea-Webhook und ist nicht der Recovery-Anker.
  • Offene Off-Repo-Betreiberchecks bleiben Account-Besitz, 2FA-Recovery-Codes, Zahlungswege, Borg-Passphrase-Hinterlegung und Gitea-Bundle-/Mirror-Mechanik.

2026-05-26 - Policy-Warnings triagiert

  • Plex network_mode: host wurde in den Policy-Ausnahmen als dokumentierte Discovery-Ausnahme erfasst.
  • Mutable Tags bei ddns-updater, glances und scrutiny bleiben wegen vorhandener SHA256-Digests reproduzierbar gepinnt und werden im Policy-Report als Info-Ausnahmen sichtbar gehalten.
  • monitoring-influxdb3-core bleibt als dokumentierte user: "0"-Ausnahme bewusst eine Warning, damit der Hardening-Punkt nicht aus dem Blick faellt.

2026-05-26 - Hardware-/Capacity-Baseline abgeschlossen

  • Hardware-Inventar auf Host-Befund aktualisiert: BIOS AMI F21 vom 2025-06-19, Intel Raptor Lake SATA AHCI, Samsung NVMe Controller und Realtek RTL8125 2.5GbE mit aktuellem 1G-Link.
  • RAM-Baseline dokumentiert: 4x 8 GB DDR4 ohne ECC, gemischte Module, aktuell 2133 MT/s konfiguriert.
  • Capacity-Baseline dokumentiert: Cache 1.9T mit 97G genutzt (6 %), Disk1/User-Shares 5.5T mit 1.8T genutzt (33 %), lokale Backups 2.2G unter /mnt/user/backups.
  • USV-Befund dokumentiert: apcupsd ist vorhanden und auf USB vorkonfiguriert, laeuft aber nicht; apcaccess status liefert Connection refused und lsusb zeigt keine erkannte USV. Power-Loss bleibt damit eine offene Betreiberentscheidung.

2026-05-26 - Komodo/Gitea-Restdrift bereinigt

  • Der alte Komodo-Stack grafana wurde als historischer Altstand inert gemacht: keine Repo-Dateipfade, kein Webhook, keine alte Stack-ENV, keine missing_files/remote_errors. Rollback bleibt Git-Historie, nicht der alte Komodo-Stack.
  • Der Gitea-Hook 35 fuer den alten grafana-Stack bleibt inaktiv. Der nicht sinnvolle komodo-Self-Hook 11 wurde deaktiviert, weil Komodo selbst nicht per Gitea-Webhook auf master deployed wird.
  • Ein kurz sichtbarer Komodo-DB-Typfehler durch updated_at als Float wurde im selben Kontrollfenster auf nativen Mongo Long korrigiert; danach traten keine neuen invalid type-Fehler mehr auf.
  • Nach der Bereinigung: aktive Gitea-Komodo-Hooks haben 0 Fehlstatus; komodo-core, komodo-periphery, komodo-mongo, nextcloud und die aktuellen monitoring-* Container laufen weiter.

2026-05-26 - Monitoring-Altstaende aus aktivem Repo entfernt

  • Die abgeloesten Pfade ops/grafana-influxdb und ops/loki wurden per git rm aus dem aktiven Repo entfernt. monitoring/ bleibt der einzige Observability-Zielstack.
  • Live-Check vor dem Cleanup: nur monitoring-grafana, monitoring-promtail, monitoring-influxdb3-core und monitoring-loki laufen; alte Container grafana, influxdb3-core, loki und alloy sind nicht vorhanden.
  • Rollback erfolgt bei Bedarf ueber Git-Historie, nicht ueber parallel gepflegte Compose-Verzeichnisse.
  • Im selben GitOps-Kontrollfenster wurde Gitea-Webhook 35 fuer den alten grafana-Rollback-Stack als inaktiv bestaetigt. Der aktive Nextcloud-Hook 36 hatte einen Signaturfehler; sein Secret wurde ohne Ausgabe des Werts aus der Komodo-Stack-Konfiguration zurueck nach Gitea synchronisiert.

2026-05-26 - AdGuard Admin-Port auf Tailscale-Soll begrenzt

  • Host-Audit per SSH gegen Kallilabcore durchgefuehrt: Tailscale IPv4 ist 100.80.98.33, LAN-IP ist 192.168.178.58/24, Gateway 192.168.178.1.
  • Repo-Soll fuer host-services/Adguard/docker-compose.yml geaendert: DNS 53/tcp+udp bleibt unveraendert, die Admin-UI bindet nun auf 100.80.98.33:8082:80.
  • Architektur, Service-Katalog, Repo-Map, Netzwerk-Inventar und AI-Kontext wurden an das neue Modell angepasst: keine Traefik-/Authelia-2FA-Umstellung, aber keine LAN-weite Admin-Bindung mehr.
  • Live-Deploy wurde nach Fast-Forward des AdGuard-Workspaces auf 5cb4017 mit docker compose -p adguard ... up -d ausgefuehrt. Validierung erfolgreich: ss -ltnp zeigt 100.80.98.33:8082, DNS via @127.0.0.1 und @192.168.178.58 funktioniert, http://100.80.98.33:8082/ liefert HTTP 302, http://192.168.178.58:8082/ ist nicht mehr erreichbar.
  • Nachpruefung des GitOps-Pfads: Gitea-Hook 1 zeigt auf Komodo-Stack 69c7b9e26b77cd827811b9d0 und lieferte HTTP 200. Komodo-Deploys fuer AdGuard scheiterten zunaechst im Git pull einmal an .git/index.lock und danach an fatal: Cannot rebase onto multiple branches; der Workspace wurde aufgeraeumt und steht sauber auf origin/master.

2026-05-26 - Audit-Umsetzung vorbereitet

  • Aus docs/AUDIT_2026-05-25.md wurde docs/AUDIT_2026-05-25_TODO.md als operative Arbeitsliste abgeleitet. Authelia-2FA/OIDC bleibt bewusst geparkt und wird erst nach finaler Policy-Entscheidung umgesetzt.
  • Neue Inventar- und Betriebsdokumente angelegt: docs/HARDWARE_INVENTORY.md, docs/NETWORK_INVENTORY.md, docs/EXTERNAL_DEPENDENCIES.md, docs/CAPACITY_AND_LIFECYCLE.md und docs/FAMILY_ONBOARDING.md.
  • docs/SERVICES_RECOVERY.md beschreibt initial die recovery-kritischen /mnt/user/services-Pfade, Gitea-Repo-Mirror-Optionen, Komodo-Bootstrap und Secret-Recovery-Reihenfolge.
  • Policy-Check lokal erneut ausgefuehrt: die alten SEC001-Warnings fuer ddns-updater und scrutiny sind nicht mehr aktuell; verbleibende Warnings betreffen Host-Netz-/User-/Image-Tag-Themen und Altstaende.

2026-05-25 - Unraid Flash-Backup in Borg-Scope aufgenommen

  • pre-backup-dumps.sh erzeugt zusaetzlich zu den DB-Dumps ein sensibles unraid-flash-config.tar.gz aus /boot/config inklusive SHA256 und Manifest unter /mnt/user/backups/borg/dumps/latest.
  • Da /local/borg-dumps bereits Teil des Borg-Scopes ist, wird das Flash-Konfigurationsartefakt mit dem bestehenden Hetzner/Borg-Backup historisiert. Downloadbare Plugin-Paketarchive unter /boot/config/plugins/*/ werden aus dem Artefakt ausgeschlossen; Restore-relevante Konfiguration bleibt enthalten.
  • Live-Erstlauf erfolgreich: pre-borg.sh lieferte critical_count=0, Freshness Critical: 0, unraid-flash-config.tar.gz ist 297 KiB gross, 0600 root:root, SHA256-Pruefung OK, 356 Archiv-Eintraege, Manifest fuer Unraid 7.2.4. Der Borg-UI-Job Taegliche Sicherung ist aktiv und umfasst /local/borg-dumps; der naechste planmaessige Hetzner-Lauf nimmt das neue Flash-Artefakt mit. Der Host-Repo-Clone unter /mnt/user/services/homelab-infra wurde wegen eines fehlgeschlagenen Fast-Forward-Checkouts frisch geklont; der vorherige Stand liegt archiviert unter /mnt/user/services/_archive/homelab-infra-pre-refresh-20260525-194209.

2026-05-25 - Monitoring-Zielstack finalisiert und Uptime Kuma entfernt

  • monitoring und glance wurden auf Commit b6bbca4 deployed; Komodo zeigt fuer beide latest_hash = deployed_hash = b6bbca4 ohne remote_errors. Die zehn monitoring-* Container laufen, monitoring.kaleschke.info und glance.kaleschke.info leiten anonym zu Authelia, Prometheus ist ready und Loki /ready liefert ready.
  • Alte Monitoring-Altcontainer grafana, influxdb3-core, loki und alloy sind in Docker nicht vorhanden; ops/grafana-influxdb und ops/loki bleiben nur als Rollback-/Migrationsreferenz im Repo. Der noch aktive Gitea-Hook 35 des alten grafana-Rollback-Stacks wurde deaktiviert, damit zukuenftige Pushes den Altstand nicht reaktivieren.
  • Uptime Kuma wurde durch Blackbox/Prometheus/Grafana ersetzt: aktive Blackbox-Zielliste enthaelt 19 HTTPS-Ziele, uptime.kaleschke.info ist dort nicht mehr enthalten und liefert nach Stack-Removal 404. Der Komodo-Stack uptime-kuma wurde gestoppt/destroyed/geloescht, Gitea-Webhook 23 deaktiviert, Appdata nach /mnt/user/appdata/_archive/uptime-kuma-removed-2026-05-25 und der alte Stack-Workspace nach /mnt/user/services/stacks/_archive/uptime-kuma-removed-2026-05-25 verschoben.
  • Authelia-Hostconfig wurde mit Backup configuration.yml.pre-uptime-removal-20260525-164343.bak um den toten uptime.kaleschke.info-Eintrag bereinigt, validiert und neu gestartet. Prometheus wurde wegen eines Stale NFS file handle auf der gebundenen Konfigurationsdatei per Komodo-Restart neu gemountet.

2026-05-25 - AdGuard Admin-Port bewusst LAN-direkt belassen

  • Strategische Option adguard.kaleschke.info hinter Traefik/Authelia-2FA wurde bewertet, aber vom Operator bewusst verworfen, weil der Betriebsweg einfach bleiben soll. AdGuard bleibt als dokumentierte Ausnahme mit DNS 53/tcp+udp und Admin 8082:80 LAN-direkt; keine Live-Aenderung an AdGuard, Authelia oder Traefik wurde vorgenommen.

2026-05-25 - Borg-Passphrase Host-Secret verifiziert

  • Erwartete Host-Secret-Datei /mnt/user/appdata/secrets/borg_repo_passphrase.txt aus der bestehenden Borg-UI-Repo-Konfiguration erzeugt, mit root:root und Modus 600 gesichert und per borg info gegen das Hetzner-Borg-Repo verifiziert. Analoge Offline-Hinterlegung bleibt bewusste Operator-Aufgabe; Secret-Wert wurde nicht ausgegeben oder dokumentiert.

2026-05-25 - Dashboard auf Glance konsolidiert

  • Glance bleibt das einzige Homelab-Dashboard; Homepage wurde aus dem Zielbild entfernt. Authelia-Default-Redirect, Monitoring-Blackbox-Ziele, Cert-Check-Domains und Glance-Konfiguration zeigen nicht mehr auf home.kaleschke.info; Homepage wurde via Komodo-API gestoppt/destroyed, der Komodo-Stack geloescht, der alte Gitea-Webhook deaktiviert und Appdata nach /mnt/user/appdata/_archive/homepage-removed-2026-05-25 verschoben.

2026-05-25 - Jellyfin aus Zielbild entfernt

  • Plex-Smoke-Test erfolgreich (/identity HTTP 200, Container healthy, /data/movies und /photos sichtbar). Jellyfin wurde repo-seitig entfernt, aus Authelia-Baseline und Zielbild-Doku ausgetragen, via Komodo-API gestoppt/destroyed, der Komodo-Stack geloescht und Appdata nach /mnt/user/appdata/_archive/jellyfin-removed-2026-05-25 verschoben; Plex bleibt einziger Medienserver.

2026-05-25 - Externer Repo-Mirror eingerichtet

  • Gitea erlaubt fuer Repo-Migrationen und Mirror-Targets gezielt github.com und nutzt explizite externe DNS-Resolver. Micha/homelab-infra spiegelt nun als privater GitHub-Push-Mirror nach michaelkaleschke-spec/homelab-infra; erster manueller Sync erfolgreich, Gitea push_mirror.last_error leer. Token-Werte bleiben ausschliesslich in Gitea/GitHub und werden nicht dokumentiert.

2026-05-25 - Audit-Final nachgemessen

  • Audit-Restliste erneut live geprueft: runtime-relevanter Stack-Inhalt fuer gitea, borg-ui und monitoring seit 66ee10c unveraendert; abschliessende Audit-Doku-Commits liegen in Gitea; Monitoring inklusive Loki /ready gruen; Borg-Job und 15 kanonische Dump-Artefakte frisch; docs/AUDIT_2026-05-23_FINAL.md auf den Live-Stand aktualisiert.

2026-05-25 - Disk1 Phase 2 abgeschlossen

  • Disk1 wurde nach H:-Freeze-Backup und finalem Service-Freeze von NTFS/ntfs3 auf XFS migriert.
  • Restore verifiziert: media final 2722 Dateien und 1,800,782,188,226 Bytes mit 0 missing/extra/size mismatch; Tar-Shares und Disk1-Extras aus den H:-Freeze-Archiven wiederhergestellt.
  • Docker/Services nach XDG-Runtime-Fix wieder stabil: 49 Container laufend, 0 stopped, 0 unhealthy, 0 starting; Gitea, Komodo, Borg, Jellyfin und Monitoring per Smoke-Test erreichbar.
  • Borg-UI meldet den letzten Backup-Job completed; pre-backup-dumps.sh wurde nach Wiederanlauf erneut ausgefuehrt und 15 kanonische Dump-Artefakte sind juenger als 24 h.
  • posture-check erwartet Disk1 nun standardmaessig als XFS (ALLOW_DISK1_NTFS=0).

2026-05-23 - Audit-Endstufe verifiziert

  • Lokalen Hardening-Commit cd650b1 nach Gitea gepusht; Komodo-Workspaces fuer gitea, borg-ui und monitoring stehen auf cd650b1.
  • Live-Audit in docs/AUDIT_2026-05-23_LIVE.md dokumentiert: Gitea-Registration geschlossen, Borg-Dumps frisch, Monitoring-Stack aktiv, alte Grafana/Loki-Altcontainer nicht mehr vorhanden.
  • Jellyfin und Plex in Architektur, Service-Katalog und Repo-Map nachgetragen; Plex ist jetzt als Repo-Compose-Stack mit dokumentierter Host-Netz-Ausnahme gefuehrt.
  • Repo-Hygiene abgeschlossen: .serena/ ignoriert, leere Verzeichnisse entfernt, Windows-Reinstall-Helfer unter ops/windows-reinstall/ bewusst versioniert.

2026-05-20 - Gitea 5xx-Bursts untersucht und Signup geschlossen

  • Live-Befund zu HomelabTraefik5xx: kurze externe POST /-Bursts auf gitea@docker von 103.153.183.69 und 103.153.183.73, jeweils HTTP 500 in unter 10 ms; normale Gitea-Checks und Git-Reads liefen parallel mit HTTP 200.
  • Keine Hinweise auf erfolgreichen Zugriff: Gitea-Container ohne Restart/OOM, nur User micha, keine neuen User der letzten 30 Tage, keine neuen Repos, SSH-Keys oder Access-Tokens im Untersuchungsfenster.
  • Live-Prometheus lief noch mit der alten Regel rate(...[5m]) > 0; die bereits im Repo vorbereitete Regel increase(...[5m]) >= 5 wurde auf den Live-Mount kopiert und per Prometheus-Reload aktiviert.
  • Gitea-Registrierung und OpenID-Signup wurden geschlossen: DISABLE_REGISTRATION=true, REGISTER_EMAIL_CONFIRM=true, ENABLE_OPENID_SIGNIN=false, ENABLE_OPENID_SIGNUP=false; Signup-Seite zeigt danach "Registration is disabled", OpenID-Login liefert 403.

2026-05-18 - Komodo Webhooks vollstaendig abgeglichen

  • Live-Befund auf Kallilabcore: Komodo hatte fuer mehrere aktuelle Stacks webhook_enabled: true, aber Gitea enthielt noch nicht fuer alle aktuellen Stack-IDs aktive Webhooks.
  • In der Gitea-Datenbank wurden aktive Webhooks fuer monitoring (6a08d5297707b0930ab95c72), glance (6a09d7347707b0930ab96eae), grafana (69f31ecdf65eb72b757c497d) und nextcloud (69e519085fd5e8bc51f121f0) nach dem bestehenden Komodo-Hook-Muster angelegt.
  • Stale aktive Gitea-Hooks auf nicht mehr vorhandene bzw. alte Komodo-Stack-IDs wurden deaktiviert.
  • Abgleich danach: 30 aktive Gitea-Komodo-Hooks fuer 30 Komodo-Stacks mit aktiviertem Webhook; hermes bleibt in Komodo bewusst webhook_enabled: false.
  • Netzwerkpfad aus dem gitea-Container zu komodo-core:9120 wurde erfolgreich verifiziert; last_status=0 fuer neue Hooks bleibt bis zum ersten Push erwartbar.

2026-05-19 - Posture-Check Host-Version verifiziert

  • Ursache fuer wiederholte ntfy-Warnings war nicht mehr die Repo-Logik allein, sondern dass auf dem Unraid-Host noch die alte Skriptversion unter /mnt/user/services/homelab-infra/services/posture-check/posture-check.sh ausgefuehrt wurde.
  • Host-Skript wurde mit Backup ersetzt und mit SEND_NTFY=0 direkt auf dem Host verifiziert.
  • Ergebnis des echten Host-Laufs: status: ok, critical_count: 0, warning_count: 0.
  • Betriebsregel daraus: Bei Host-User-Scripts nach Repo-Aenderungen immer den tatsaechlich ausgefuehrten Host-Pfad und den Live-Output pruefen.

2026-05-19 - Borg-Scope fuer GitOps Host Automation erweitert

  • Nach den Gitea-/Komodo-Webhook- und Posture-Check-Aenderungen wurde der Backup-Scope um Host-GitOps-Pfade erweitert.
  • Borg UI mountet kuenftig /mnt/user/services read-only als /local/services.
  • In all-important-sources.txt wurden /local/services/homelab-infra, /local/services/stacks und /local/services/posture-check aufgenommen.
  • pre-backup-dumps.sh wurde auf dem Host ausgefuehrt; frische Dumps fuer gitea.sqlite.dump und komodo-mongo.archive.gz liegen unter /mnt/user/backups/borg/dumps/latest.
  • Wirksam wird der neue /local/services-Mount nach Redeploy/Recreate des borg-ui-Stacks.

2026-05-19 - Traefik-5xx Alert entstoert

  • HomelabTraefik5xx hatte auf einzelne 5xx-Antworten reagiert, weil die Regel rate(...[5m]) > 0 nutzte.
  • Live-Befund fuer gitea@docker: zwei kurze POST / mit HTTP 500 von einer externen IP, danach durchgehend erfolgreiche Gitea-Checks; kein Container-Restart.
  • Prometheus-Regel auf increase(...[5m]) >= 5 geaendert, damit einzelne externe Fehlrequests keinen ntfy-Alarm ausloesen.

2026-05-17 - Glance Homelab-Dashboard vorbereitet

  • ops/glance als geschuetztes Homelab-Dashboard unter glance.kaleschke.info vorbereitet.
  • Glance zeigt HTTP-Monitore fuer Core, Apps und Ops, Docker-Containergruppen, Host-Snapshot und Bookmarks.
  • Docker-Status laeuft nicht ueber einen direkten Socket-Mount in Glance, sondern ueber glance-docker-socket-proxy auf einem internen glance_socket_net.
  • Die HTTP-Monitore nutzen oeffentliche URLs als Klickziel und interne check-url-Endpunkte auf frontend_net, damit Glance nicht vom externen Hairpin-/Auth-Pfad abhaengt.
  • Das Immich Community-Widget wurde ergaenzt. Der API-Zugriff nutzt eine interne Service-URL und ein Stack-ENV-Token. Paperless, Scrutiny und Speedtest bleiben Kandidaten fuer einen spaeteren Widget-Pass, sobald die konkrete API-Ausgabe im Glance-Kontext sauber verifiziert ist.
  • Das Dashboard-Layout wurde an ginesjunior11/glance-dashboard-config angelehnt: dunkleres blaues Theme, Zeitfortschrittsgruppe, farbige Dashboard-Icons, dichter Homelab Status, Server-Stats im Hauptbereich und eine zweite Seite Infrastructure and Media. Die rechte Home-Spalte zeigt WAN-Infos aus Speedtest Tracker, Speedtest-Livewerte, AdGuard-DNS-Stats, DNS/Ingress-Monitore und eine separate Netzwerk-Containergruppe.

2026-05-17 - Monitoring-Zielstack konsolidiert

  • monitoring/ als zentraler Observability-Zielstack fuer Prometheus, Loki, Promtail, Grafana, node-exporter, cAdvisor und InfluxDB 3 Core vorbereitet.
  • monitoring-grafana nutzt den Repo-Standard authelia@file,secure-headers@file und Secrets per Datei statt Klartext-Stack-ENV.
  • monitoring-influxdb3-core uebernimmt den LAN-only Writer-Endpunkt fuer Home Assistant (8181 via INFLUXDB_BIND_IP).
  • ops/loki und ops/grafana-influxdb sind abgeloeste Altstaende und bleiben nur als Rollback-/Migrationsreferenz im Repo.

2026-05-07 - Vaultwarden Restore-Test praktisch verifiziert

  • Erster echter Vaultwarden-Mini-Restore gegen das produktive Borg-Repo hetzner_borg_appdata_critical erfolgreich durchgefuehrt.
  • Restore lief isoliert nach /mnt/user/backups/restore-lab/vaultwarden, nicht gegen produktive Pfade.
  • Testinstanz restoretest-vaultwarden wurde lokal auf 127.0.0.1:18080 gestartet; HTTP 200 und Login-Seite wurden erfolgreich bestaetigt.
  • Report wurde unter /mnt/user/backups/restore-reports/vaultwarden-2026-05-07.md geschrieben.
  • Fuer den praktischen Restore-Pfad wurden zwei hostseitige Voraussetzungen sichtbar und umgesetzt:
    • known_hosts fuer das Hetzner-Ziel im borg-ui-Container
    • Host-Secret-Datei /mnt/user/appdata/secrets/borg_repo_passphrase.txt fuer kuenftige Restore-Tests
  • Testdaten unter /mnt/user/backups/restore-lab/vaultwarden/data wurden nach erfolgreichem Lauf wieder bereinigt.

2026-05-07 - Gitea Restore-Test praktisch verifiziert

  • Erster echter Gitea-Mini-Restore gegen das produktive Borg-Repo hetzner_borg_appdata_critical erfolgreich durchgefuehrt.
  • Restore lief isoliert nach /mnt/user/backups/restore-lab/gitea, nicht gegen produktive Pfade.
  • Testinstanz restoretest-gitea wurde lokal auf 127.0.0.1:13000 und 127.0.0.1:12222 gestartet.
  • HTTP 200, HTML-Titel und lokaler SSH-Port wurden erfolgreich bestaetigt.
  • Report wurde unter /mnt/user/backups/restore-reports/gitea-2026-05-07.md geschrieben.
  • Testdaten unter /mnt/user/backups/restore-lab/gitea/data wurden nach erfolgreichem Lauf wieder bereinigt.

2026-05-07 - Paperless Restore-Test praktisch verifiziert

  • Erster echter Paperless-Mini-Restore gegen das produktive Borg-Repo hetzner_borg_appdata_critical erfolgreich durchgefuehrt.
  • Restore umfasste sowohl die Dateipfade als auch postgresql17-paperless.dump aus dem Borg-Archiv.
  • Testinstanzen restoretest-paperless, restoretest-paperless-postgres und restoretest-paperless-redis liefen isoliert ohne Traefik.
  • Login-Seite war lokal auf 127.0.0.1:18120 erreichbar.
  • Der Dump-Import in Test-Postgres war erfolgreich; die Test-Datenbank enthielt 25 Dokumente.
  • Report wurde unter /mnt/user/backups/restore-reports/paperless-2026-05-07.md geschrieben.
  • Testdaten unter /mnt/user/backups/restore-lab/paperless wurden nach erfolgreichem Lauf wieder bereinigt.

2026-05-06 - Komodo Webhook Secret getrennt

  • KOMODO_WEBHOOK_SECRET von KOMODO_SECRET_KEY getrennt und als eigene Stack-ENV-Variable dokumentiert.
  • Gitea-Komodo-Webhooks mit bisherigem Core-Secret wurden auf den neuen KOMODO_WEBHOOK_SECRET umgestellt; bereits individuelle per-Stack-Webhook-Secrets wurden beibehalten.
  • Host-.env, persistente Komodo-Compose und Gitea-Webhooks wurden als ein gemeinsamer Runtime-Schritt behandelt, damit Auto-Deploys nicht auseinanderlaufen.
  • Ein stale Gitea-Webhook auf eine nicht mehr vorhandene Komodo-Stack-ID wurde deaktiviert, nicht geloescht.

2026-05-06 - Authelia GMX SMTP Notifier

  • Authelia-Notifier von Filesystem-Log auf GMX SMTP (submission://mail.gmx.net:587) umgestellt.
  • SMTP-Passwort bleibt ausserhalb des Repos unter /mnt/user/appdata/secrets/authelia_smtp_password.txt.
  • Authelia-Compose erhaelt explizite DNS-Server, weil der SMTP-Startup-Check externe Namen wie mail.gmx.net aufloesen muss.
  • Repo-Baseline und Host-Config muessen bei Auth-Aenderungen weiter bewusst gemerged und vor Restart validiert werden.

2026-05-06 - Hermes DR und Mail-Archiver Authelia

  • Hermes Agent in docs/RESTORE_MATRIX.md und docs/DISASTER_RECOVERY.md mit Restore-Pfaden, Secret-/ENV-Hinweisen und Smoke-Test ergaenzt.
  • Mail-Archiver Web-UI hinter authelia@file,secure-headers@file gelegt; App-eigene Auth bleibt als zweite Schutzschicht bestehen.
  • M10/Komodo blieb unveraendert.

2026-05-05 - N-Aufraeum-Sprint

  • Obsolete Compose-Top-Level-Felder version: "3.9" aus Immich, Mail Archiver und Paperless entfernt.
  • Leere env/domains.env.example und env/global.env.example mit nicht geheimen Beispielwerten gefuellt.
  • Veraltete .keep-Platzhalter aus Verzeichnissen mit echten Compose-/Repo-Inhalten sowie zwei reine Geister-Verzeichnisse (host-services/plex, infra/dns) entfernt.

2026-05-16 - Backup-Konsistenz und erster Hardening-Schnitt

  • SQLite-Dumps fuer Gitea, Vaultwarden, Speedtest Tracker und Filebrowser werden containerseitig als *.sqlite.dump erzeugt und per Freshness-Check geprueft; Uptime Kuma wurde am 2026-05-25 aus dem aktiven Dump-Scope entfernt.
  • nextcloud.dump und die Nextcloud-Userdaten sind als Option A im Borg-Scope dokumentiert.
  • Filebrowser mountet keine breite /mnt/user/appdata-Flaeche mehr, sondern nur noch Documents, Photos, Projekte sowie eigenen App-State.
  • Authelia Argon2id-Parameter in der Repo-Baseline auf iterations: 3, memory: 65536, parallelism: 4 gesetzt; produktive Host-Config muss kontrolliert gemerged und mit Test-User validiert werden.
  • Redis-Caches wurden auf redis:7.4-alpine@sha256:... vereinheitlicht; Nextcloud wurde mit Registry-validiertem Digest gepinnt.
  • Eindeutig aufloesbare latest@sha256-Images wurden auf konkrete Tags umgestellt: Homepage v1.12.3, code-server 4.116.0, Filebrowser v2.63.2, Speedtest Tracker 1.13.12.

2026-05-05 - M3b versionierte App-Images digest-gepinnt

  • Versionierte Nicht-Komodo-Images fuer BentoPDF, Mealie, Paperless, Paperless-GPT, AdGuard Home, Grafana, InfluxDB 3 Core und Traefik auf die am Host laufenden, manifest-validierten Digests gepinnt.
  • nextcloud:33.0.2-apache wurde bewusst nicht in diesem Schritt gepinnt, weil der lokal gelistete Digest nicht als Registry-Manifest fuer tag@sha256 validierbar war.
  • Redis-Caches und Komodo/M10 blieben unveraendert.

2026-05-05 - M6/M7/M8 Doku-Konsolidierung

  • hermes.kaleschke.info als produktive Hermes-Dashboard-Route hinter Traefik + Authelia in Architektur, Repo-Map und Service-Katalog ergaenzt.
  • grafana und influxdb3-core laufen weiterhin als user: "0"; das wurde als Host-Appdata-Permissions-Ausnahme dokumentiert und nicht nebenbei geaendert.
  • Tailscale-Ausnahme um NET_ADMIN, NET_RAW und /dev/net/tun ergaenzt.
  • Komodo-Secret-/Webhook-Themen wurden bewusst nicht geaendert; Komodo-Aenderungen erfolgen nur gemeinsam mit dem Betreiber.

2026-05-05 - M3a stateful Digest-Pinning

  • PostgreSQL 17 Datenhalter auf postgres:17.9@sha256:5b96f1a16bd9768b060dd2ffe55cb6225c4d9ef4d214a8b21eb08134869a97e4 gepinnt (postgresql17, mealie-postgres, nextcloud-postgres).
  • Immich pgvector-Postgres auf tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52 gepinnt.
  • Komodo Mongo auf mongo:7.0.32@sha256:32979a1189dfdc44da3f5ed40d910495f5ad8f6f7f77556646f890a30b2d3f56 sowie Komodo Core/Periphery und Gitea auf die am Host laufenden Digests gepinnt.
  • Redis-Caches wurden am 2026-05-16 auf redis:7.4-alpine@sha256:... vereinheitlicht; Redeploys erfolgen stackweise mit Smoke-Test, nicht parallel.

2026-05-04 - Komodo Self-Stack Drift auf persistenten Pfad zurueckgefuehrt

  • Drift-Befund: komodo-core und komodo-periphery liefen aus /tmp/komodo-core-repair.yml bzw. /tmp/komodo-periphery-repair.yml; komodo-mongo verwies auf /mnt/user/services/stacks/komodo/compose.yaml, obwohl dieser Pfad fehlte.
  • Vor Eingriff wurden die Repair-Dateien und zugehoerigen /tmp/*.env-Dateien unter /mnt/user/appdata/komodo/_drift_backup_2026-05-04/ gesichert.
  • Zusaetzlich wurde eine geschuetzte Recovery-ENV unter /mnt/user/appdata/secrets/_komodo_stack_env_recovery_2026-05-04.env abgelegt; diese Datei enthaelt Tier-1-Secret-Material und ist kein Dauerzustand.
  • Vor dem Reconcile wurde das host-seitige Dump-Skript ausgefuehrt; komodo-mongo.archive.gz wurde frisch unter /mnt/user/backups/borg/dumps/latest/ erzeugt.
  • Persistenter Self-Stack wurde unter /mnt/user/services/stacks/komodo/compose.yaml aus ops/komodo/docker-compose.yml wiederhergestellt; .env wurde hostseitig aus der bestehenden Runtime-ENV abgeleitet.
  • Der vollstaendige Dry-run haette auch komodo-mongo recreated und wurde daher nicht ausgefuehrt. Stattdessen wurden nur komodo-core und komodo-periphery gezielt mit --no-deps --force-recreate aus dem persistenten Pfad neu erstellt; komodo-mongo blieb unveraendert healthy.
  • Smoke-Tests: docker compose ls zeigt fuer komodo nur noch /mnt/user/services/stacks/komodo/compose.yaml, Mongo pingt { ok: 1 }, https://komodo.kaleschke.info liefert HTTP 200, und Periphery meldet sich am Core an.
  • Die /tmp/*repair.yml-Dateien bleiben vorerst als Altlast erhalten und duerfen erst nach stabiler Laufzeit bewusst entfernt oder ins Drift-Backup verschoben werden.

2026-05-04 - Authelia ACL-Drift hostseitig gemerged

  • Die produktive Authelia-Config ist groesser als die Repo-Datei, weil sie hostseitige OIDC-/Secret-Konfiguration enthaelt. Die Repo-Datei wurde daher als nicht geheime Baseline eingeordnet und nicht blind auf den Host kopiert.
  • Host-Backup vor Aenderung: /mnt/user/appdata/authelia/config/configuration.yml.bak-20260504-acl-sync.
  • Minimaler Host-Merge: homepage.kaleschke.info wurde aus der bypass-Liste entfernt, komodo.kaleschke.info aus der 2FA-Liste entfernt, und default_redirection_url wurde auf https://home.kaleschke.info gesetzt.
  • authelia validate-config war erfolgreich; Authelia wurde neu gestartet und war danach healthy.
  • Smoke-Tests: home.kaleschke.info liefert fuer anonyme Requests eine Authelia-Weiterleitung, komodo.kaleschke.info bleibt ueber native Komodo-Auth erreichbar.

2026-05-04 - Home Assistant InfluxDB LAN-Port und Drift-Runbook

  • influxdb3-core fuer Home-Assistant-Writer auf LAN-Port 8181 vorbereitet und deployed.
  • InfluxDB bleibt ohne Traefik-/Public-Route und haengt nicht im frontend_net.
  • Fuer aktives Docker Host-Port-Publishing wurde zusaetzlich zum internen grafana_influx_internal das Compose-Netz grafana_influx_lan ergaenzt.
  • Komodo Periphery dauerhaft um /mnt/user/services:/mnt/user/services und frontend_net ergaenzt, damit Stack-Workspaces und Gitea-Zugriff reproduzierbar funktionieren.
  • docs/GITOPS_DRIFT_RUNBOOK.md angelegt, um lokale Git-Kopie, Gitea, Komodo Workspace, Docker Runtime und Host-Listener getrennt zu pruefen.

2026-03-28 - GitOps-Konsolidierung

  • Komodo als primaeren Stack-Manager eingefuehrt.
  • Portainer aus dem Zielbild herausgenommen.
  • Traefik auf 100% Docker-Labels konsolidiert.
  • diun entfernt; Update-Monitoring wird ueber Komodo abgedeckt.

2026-03-29 - Portainer abgeschaltet

  • Portainer CE aus dem produktiven Betrieb entfernt.
  • Komodo als alleinigen Stack-Manager festgezogen.

2026-04-13 bis 2026-04-15 - Borg-Rollout abgeschlossen

  • critical_infra erfolgreich nach Borg gesichert.
  • Pre-Backup-Dumps host-seitig ueber Unraid User Scripts etabliert.
  • Dump-Zielpfad auf /mnt/user/backups/borg/dumps umgestellt.
  • Restore-Smoke-Test fuer postgresql17-globals.sql und gitea.db erfolgreich nachgewiesen.
  • Monitoring fuer Borg war historisch ueber ntfy und Uptime Kuma eingerichtet; seit 2026-05-25 ersetzt durch ntfy, Blackbox/Prometheus und Monitoring Grafana.

2026-04-15 - Repo- und Betriebsbereinigung

  • Firefly, Firefly-Fints und Semaphore aus Repo und Homelab entfernt.
  • GitHub Desktop als Standard-Workflow fuer den lokalen Sync festgelegt.

2026-04-17 - Sicherheits- und Doku-Abgleich

  • code-server hinter authelia@file,secure-headers@file abgesichert.
  • Traefik-Dashboard von dashboard-auth@file auf authelia@file,secure-headers@file umgestellt; BasicAuth-Hash aus dem Repo entfernt.
  • Redis von Klartext in der Compose auf Secret-Datei unter /mnt/user/appdata/secrets/redis_password.txt umgestellt.
  • Redis-Passwort bewusst nicht rotiert; Live-Passwort bleibt vorerst unveraendert.
  • mail-archiver in der Architektur-Doku an den realen Traefik-Betrieb angepasst.
  • paperless-gpt von LOG_LEVEL=debug auf info umgestellt.
  • speedtest-tracker von APP_DEBUG=true auf false umgestellt.
  • Mutable Image-Tags fuer produktive Stacks auf die aktuell laufenden Digests eingefroren, um Deployments reproduzierbar zu machen.
  • paperless-ngx bleibt fuer PAPERLESS_DBPASS und PAPERLESS_REDIS vorerst bewusst bei Stack Environment Variables; keine Live-Migration auf _FILE, solange der aktuelle Stand stabil laeuft.
  • Disaster-Recovery-Runbook und Restore-Matrix fuer den Totalausfall-/Wiederanlauf-Fall neu dokumentiert.

2026-04-19 - paperless-gpt Digest-Pin zurueckgenommen

  • Der fuer paperless-gpt eingetragene Digest war syntaktisch ungueltig (63 statt 64 Hex-Zeichen) und wurde daher wieder auf icereed/paperless-gpt:latest zurueckgesetzt.
  • Diese Ruecknahme ist bewusst eng auf einen einzelnen defekten Pin begrenzt und aendert keine anderen Digest-Festschreibungen.
  • Die zwischenzeitlichen OCR-/Versions-Experimente fuer paperless-gpt wurden wieder auf den einfachen vorherigen Stand zurueckgenommen (icereed/paperless-gpt:latest, VISION_LLM_MODEL=cnshenyang/qwen3-nothink:14b), um den letzten bekannten Alltagszustand wiederherzustellen.

2026-04-19 - Nextcloud und Stirling-PDF vorbereitet

  • apps/nextcloud/docker-compose.yml als offizieller Docker-Microservice-Stack mit nextcloud:apache, eigener PostgreSQL-Datenbank und eigenem Redis vorbereitet.
  • Nextcloud folgt dem Repo-Standard frontend_net + app-internes Netz, nutzt _FILE-Secrets fuer Admin- und DB-Passwort und ist bewusst nicht hinter zentraler ForwardAuth, damit WebDAV/CardDAV und native Clients sauber funktionieren.
  • apps/stirling-pdf/docker-compose.yml als geschuetzter Tool-Stack hinter authelia@file,secure-headers@file vorbereitet.
  • Stirling-PDF nutzt persistente Pfade fuer /configs, /logs, /pipeline, /customFiles und /usr/share/tessdata; interne Stirling-Login-Funktion bleibt zugunsten des zentralen Traefik-/Authelia-Zugangs deaktiviert.

2026-04-30 - BentoPDF und Grafana/InfluxDB vorbereitet

  • stirling-pdf repo-seitig durch bentopdf ersetzt; Domain pdf.kaleschke.info bleibt erhalten.
  • BentoPDF laeuft als geschuetztes browserseitiges PDF-Tool hinter authelia@file,secure-headers@file und setzt zusaetzlich COOP/COEP-Header fuer SharedArrayBuffer-basierte Office-Konvertierung.
  • ops/grafana-influxdb als neuer Monitoring-Stack vorbereitet und spaeter in Betrieb genommen.
  • Grafana laeuft hinter Traefik + Authelia unter grafana.kaleschke.info.
  • InfluxDB 3 Core bleibt ohne Public Route und wird ueber eine provisionierte Grafana-Datenquelle angebunden.
  • Secrets fuer Grafana-Admin-Passwort, InfluxDB-Admin-Token und Grafana-Datasource-Token sind als Host-Dateien unter /mnt/user/appdata/secrets/ dokumentiert.

Dauerhafte Learnings

  • Kein Live-Editing in Komodo; Git gewinnt immer gegen manuelle Drift.
  • Webhooks koennen nach einem Push sofort einen Deploy ausloesen.
  • Rollback soll bevorzugt ueber saubere Git-Commits und bekannte Good States erfolgen, nicht ueber History-Rewrites auf master.
  • Doku soll Endzustaende beschreiben, nicht veraltete Zwischenstaende konservieren.