# 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 Deploy-Drift strukturell abgesichert Nach dem Renovate-Block wurde die Ursache fuer den kurzzeitigen `nextcloud-postgres`-Drift nachgezogen: Komodo hatte den `nextcloud`-Stack beim Postgres-17.10-Deploy gestartet, aber `docker compose up -d` scheiterte zunaechst an einem Docker-Recreate-Namenskonflikt (`nextcloud-postgres` Ersatzcontainer). Der Workspace war dadurch bereits auf dem neuen Commit, waehrend der laufende DB-Container noch das alte Image nutzte. Der spaetere gezielte `docker compose up -d` aus dem aktualisierten Workspace hat den Zwischenzustand sauber aufgeloest; es blieben keine exited/dead Containerreste. - Komodo-Update-Historie bestaetigt: ein fehlgeschlagener `DeployStack` fuer `nextcloud` mit Compose-Up-Konflikt, danach ein erfolgreicher `DeployStack`. - Aktueller Runtime-Stand nach Pruefung: `nextcloud`, `nextcloud-postgres`, `nextcloud-redis`, `postgresql17`, `mealie-postgres`, `gitea`, `bentopdf`, `ddns-updater` und Komodo-Self-Stack laufen ohne `unhealthy`-Status; die erwarteten Images stimmen mit den Compose-Dateien ueberein. - `services/posture-check/export-prometheus-textfile.sh` exportiert jetzt `homelab_gitops_runtime_image_match{name,project,service}` fuer laufende Compose-Container. Die Metrik vergleicht das Image aus `docker compose config --format json` gegen `docker inspect .Config.Image` des laufenden Containers und faengt damit genau den Zustand "Workspace/Compose neu, Runtime alt" ab. - Neue Prometheus-Regel `HomelabGitOpsRuntimeImageDrift`: feuert als Warning, wenn ein laufender Compose-Container laenger als 10 Minuten nicht dem Compose-Image entspricht. - Smoke: Exporter-Test in `/tmp/kallilab-textfile-test/homelab.prom` lieferte fuer alle erkannten Compose-Container `homelab_gitops_runtime_image_match = 1`; `promtool check rules` meldete `SUCCESS: 17 rules found`. ### 2026-05-31 - Renovate PRs #1 bis #5 gemerged und deployed Die ersten fuenf Renovate-PRs wurden einzeln in `master` uebernommen, mit Policy-Check und Live-Smoke nach den Datenhalter-Aenderungen. Major-Branches wurden bewusst nicht gemerged. - #1 `renovate/mongo-7.0.32`: Mongo-Digest fuer Komodo uebernommen, Merge-Commit `b8b0af9`. - #2 `renovate/postgres-17.9`: Postgres-17.9-Digest fuer `postgresql17`, `mealie-postgres` und `nextcloud-postgres` uebernommen, Merge-Commit `db1fa7c`. - #3 `renovate/minor-patch-updates`: gruppierte Minor-/Patch-Updates uebernommen, Merge-Commit `dde4419`. Danach wurden die Komodo-Workspaces `gitea`, `bentopdf` und `ddns-updater` wegen Drift gezielt gesichert, auf `origin/master` synchronisiert und neu deployed. Backups liegen unter `/mnt/user/appdata/komodo/_workspace_backups/*-workspace-before-renovate-pr3-resync-*.tar.gz`. - #4 `renovate/mongo-7.x`: Komodo-Mongo von `7.0.32` auf `7.0.34` gehoben, Merge-Commit `076676d`. Da der Komodo-Self-Stack nicht ueber einen normalen Git-Webhook redeployed, wurde vorher ein Compose-Backup (`/mnt/user/appdata/komodo/_workspace_backups/komodo-compose-before-renovate-20260531-125102.yaml`) und ein frischer Mongo-Dump (`/mnt/user/backups/borg/dumps/latest/komodo-mongo-pre-renovate-20260531-125102.archive.gz`) erstellt, danach der Self-Stack kontrolliert aktualisiert. - #5 `renovate/postgres-17.x`: Postgres von `17.9` auf `17.10` fuer `postgresql17`, `mealie-postgres` und `nextcloud-postgres` gehoben, Merge-Commit `96fcacc`. `postgresql17` und `mealie-postgres` wurden durch Komodo recreated; `nextcloud-postgres` musste aus dem bereits aktualisierten Workspace `/mnt/user/services/stacks/nextcloud/apps/nextcloud` einmal gezielt mit `docker compose up -d` nachgezogen werden. - `ops/policy-checks/check_repo.ps1` blieb nach den Merge-Commits ohne Criticals; einzige Warning ist weiterhin die dokumentierte InfluxDB-root-Ausnahme. - Smoke-Beleg nach Settle: `postgresql17` healthy auf `postgres:17.10@sha256:0027bef...`, `mealie-postgres` und `nextcloud-postgres` laufen auf demselben `17.10`-Digest, `mealie.kaleschke.info` HTTP `200`, `cloud.kaleschke.info` HTTP `302`, `git.kaleschke.info` HTTP `200`, `komodo.kaleschke.info` HTTP `200`, keine `unhealthy` Container. - Gitea listete #1 bis #5 nach den lokalen Merge-Commits noch als offen. Jeder PR bekam per API einen Kommentar mit dem manuellen Merge-Commit und wurde geschlossen, damit Renovate keinen offenen Altstand behaelt. - Watchpoint: Renovate-Branches `mongo-8.x`, `postgres-18.x`, `redis-8.x` und `major-major-updates` bleiben bewusst ungemerged und brauchen separate Operator-Entscheidung. ### 2026-05-31 - Gitea Komodo-Workspace-Drift bereinigt Der Komodo-Workspace fuer den `gitea`-Stack unter `/mnt/user/services/stacks/gitea` war auf `1d0cba9` stehengeblieben, 70 Commits hinter `origin/master`, mit 23 untracked Pfaden. Dadurch war die von Docker genutzte Compose-Datei nicht identisch mit dem aktuellen Repo-Stand (`core/gitea/docker-compose.yml`), obwohl der Gitea-Komodo-Webhook aktiv war. - Vor der Bereinigung wurde der komplette Workspace gesichert: `/mnt/user/appdata/komodo/_workspace_backups/gitea-workspace-before-resync-20260531-122515.tar.gz`. - Die untracked Pfade wurden einzeln gegen `origin/master` geprueft. 18 Eintraege waren byte-identisch, vier Doku-Dateien waren aeltere Zwischenstaende, und `ops/h-drive-nearline/pull-critical-backups.ps1` war ebenfalls identisch. Es gab keinen nur-im-Workspace-gueltigen neueren Arbeitsstand. - Danach wurden nur die bekannten untracked Konfliktpfade aus dem Workspace entfernt und `git pull --ff-only origin master` ausgefuehrt. Ergebnis: `stacks/gitea` steht sauber auf `e6a0e9f`, `## master...origin/master`, ohne Dirty-State. - `docker compose up -d` aus `/mnt/user/services/stacks/gitea/core/gitea` lief ohne Recreate-Zwang; der laufende Container nutzt weiterhin den Stack-Workspace als Compose-Quelle und ist `healthy`. - Smoke-Test: `docker exec gitea wget -qO- http://localhost:3000/api/healthz` liefert `status: pass`, `https://git.kaleschke.info` liefert HTTP `200`, und die lokale Gitea-API fuer `Micha/homelab-infra` antwortet mit `default_branch: master`. - Watchpoint: Gitea ist ein Henne-Ei-Stack, weil der Dienst sein eigenes Git-Origin bereitstellt. Webhook und `auto_pull` sind aktiv, aber Workspace-Drift muss bei kuenftigen Gitea-Aenderungen besonders bewusst geprueft werden; kein pauschales `git clean -fd` ohne vorherige Sicherung und Vergleich. ### 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:root` → `node_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.