Files
homelab-infra/docs/MIGRATION_LOG.md
T

396 lines
39 KiB
Markdown

# 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-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.
- 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-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.