docs: introduce DECISIONS.md decision register, slim architecture master
- new docs/DECISIONS.md (ADR-light): decisions migrated from master section 13, MASTER_TODO parked items, hardware inventory and audit restliste into one chronological register - HOMELAB_ARCHITECTURE_MASTER_V2.md: section 13 replaced by pointer, section 9 condensed (502 -> 372 lines, target picture only) - ROLLBACK.md: drop rollback recipes for already removed services (uptime-kuma, grafana/influx legacy, stirling/glance bootstrap notes) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
> **Single Source of Truth** für Docker-Netzwerkarchitektur, Sicherheitsregeln, Zielbild und Migration des Kallilabcore-Homelabs.
|
||||
> **Arbeitsregel für KI-Assistenten:** Dieses Dokument immer zuerst lesen, bevor Fragen zu Containern, Netzwerken, Traefik, Tailscale, Migration oder Security beantwortet werden.
|
||||
|
||||
**Stand:** 2026-06-02 | **Aktueller Schwerpunkt:** GitOps / Doku-Synchronisierung / Reproduzierbare Deployments
|
||||
**Stand:** 2026-06-11 | **Aktueller Schwerpunkt:** GitOps / Doku-Synchronisierung / Reproduzierbare Deployments
|
||||
|
||||
---
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
10. [Bekannte Ausnahmen und Begründungen](#10-bekannte-ausnahmen-und-begründungen)
|
||||
11. [Projektorganisation und Arbeitsmodus](#11-projektorganisation-und-arbeitsmodus)
|
||||
12. [Nutzung mit KI / Kontext-Regel](#12-nutzung-mit-ki--kontext-regel)
|
||||
13. [Betriebserfahrungen und Entscheidungs-Log](#13-betriebserfahrungen-und-entscheidungs-log)
|
||||
13. [Betriebserfahrungen und Entscheidungs-Log (ausgelagert)](#13-betriebserfahrungen-und-entscheidungs-log-ausgelagert)
|
||||
|
||||
---
|
||||
|
||||
@@ -371,23 +371,7 @@ labels:
|
||||
|
||||
## 9. Historische Migration (abgeschlossen)
|
||||
|
||||
Die frühere Blockmigration aus der Portainer-/Dockerman-Phase ist fachlich abgeschlossen.
|
||||
|
||||
Dieser Abschnitt dient nur noch als **historischer Vermerk**:
|
||||
|
||||
- Traefik läuft labelbasiert ohne Service-Routen im File-Provider.
|
||||
- Komodo ist der einzige aktive Stack-Manager.
|
||||
- Portainer CE ist entfernt.
|
||||
- Borg/Borg UI, Dump-Automatisierung und Restore-Test sind produktiv eingeführt.
|
||||
- Frühere Sprint-/Block-Checklisten werden hier **nicht mehr operativ gepflegt**.
|
||||
|
||||
Für den laufenden Betrieb gilt stattdessen:
|
||||
|
||||
- Zielbild und Architektur in diesem Dokument
|
||||
- Git-/Komodo-Ablauf in `docs/WORKFLOW.md`
|
||||
- fachliche Änderungen in der jeweils betroffenen Stack-Doku
|
||||
- Entscheidungen und besondere Umstellungen im Entscheidungs-Log unten
|
||||
|
||||
Die Blockmigration aus der Portainer-/Dockerman-Phase ist abgeschlossen: Traefik laeuft labelbasiert ohne File-Provider-Service-Routen, Komodo ist alleiniger Stack-Manager, Portainer CE ist entfernt, Borg/Dumps/Restore-Tests sind produktiv. Entscheidungen und Hintergruende stehen in `docs/DECISIONS.md`; die Sprint-Historie liegt in Git.
|
||||
## 10. Bekannte Ausnahmen und Begründungen
|
||||
|
||||
| Container | Ausnahme | Begründung |
|
||||
@@ -464,176 +448,15 @@ Damit ist sofort klar:
|
||||
|
||||
---
|
||||
|
||||
## 13. Betriebserfahrungen und Entscheidungs-Log
|
||||
## 13. Betriebserfahrungen und Entscheidungs-Log (ausgelagert)
|
||||
|
||||
### Fix Common Problems Plugin entfernt (2026-06-03)
|
||||
|
||||
Befund: Drei `grep -R ... /usr/local/emhttp`-Prozesse liefen seit ~7 Tagen durchgehend mit je 100 % CPU (TIME+ 177-179 h). Status `R`, von PID 1 adoptierte Zombies einer laengst beendeten Fix-Common-Problems-(FCP)-Scan-Session. Folge: konstante Load 14.6 auf 12 Cores, IOWAIT-Peaks bis 55 %, USB-Flash unter Dauer-IO.
|
||||
|
||||
Ursache: Unraids `/usr/local/emhttp` enthaelt Symlinks `mnt -> /mnt` (mehrere TB Array) und `boot -> /boot` (USB-Flash). GNU `grep -R` dereferenziert Symlinks rekursiv. Ein FCP-Scan-Schritt (`/etc/cron.daily/fix.common.problems.sh -> scripts/scan.php`) hat dadurch effektiv die gesamte Array-Struktur gegrept und ist beim ersten Treffer-Loop haengen geblieben. Der Lock `/tmp/fix.common.problems/scanRunning` war vom 2026-06-03 04:40 - jeder weitere Daily-Cron-Run wuerde dasselbe Verhalten reproduzieren.
|
||||
|
||||
Massnahme: FCP-Plugin per `plugin remove fix.common.problems.plg` deinstalliert. Cron-Eintrag, Plugin-Verzeichnis und `/tmp`-Reste sauber. Load fiel innerhalb Minuten auf 1.08 (1-min).
|
||||
|
||||
Entscheidung: FCP wird bewusst **nicht** wieder installiert. Begruendung:
|
||||
|
||||
- Restliche Risiken werden bereits ueber andere Wege abgedeckt: Scrutiny (Laufwerks-SMART), Monitoring-Stack (Container-Health, Prometheus-Alerts, Blackbox), Posture-Check (Filesystem-/Drift-/Authelia-Audit), Critical-Events-Watcher (`services/posture-check/docker-critical-events.sh`).
|
||||
- FCP ist ein externes Community-Plugin und nicht Teil der Repo-managed GitOps-Welt; Verhalten haengt von einer Online-Templates-Datei ab.
|
||||
- Ein einmaliges Hang-up reicht, um die Flash-Drive 7 Tage lang zu thrashen - das Verhaeltnis Nutzen/Risiko ist negativ.
|
||||
|
||||
Folgen fuer Doku: Eintrag in `docs/AUDIT_2026-05-25_TODO.md` unter "Zuletzt geschlossen"; FCP taucht nicht mehr als Voraussetzung in DR/Monitoring-Pfaden auf, da es nie produktiv referenziert war.
|
||||
|
||||
### Plex Server Reclaim und LAN-only-Profil (2026-05-28)
|
||||
|
||||
Befund: Die `Preferences.xml` des Plex-Servers war seit dem 18.05.2026 13:18 jungfraeulich (391 Bytes, ohne `PlexOnlineMail`/`PlexOnlineUsername`/`PlexOnlineToken`). Der Server war damit nicht mit einem Plex.tv-Account geclaimt, obwohl die Smart-TVs ueber LAN-Discovery (mDNS/Plex-GDM) weiter funktionierten. Beim Login als `Xeridos` ueber `app.plex.tv` meldete der Server "Keine Berechtigung", weil kein Owner registriert war. Zusaetzlich war die `library_sections`-Konfiguration leer (Backups vom 19./22./28.05. ebenfalls ~370 KB statt MBs/GBs); die Bibliotheks-Konfiguration war seit dem 18.05. weg, die Filmdateien unter `/mnt/user/media/*` blieben aber intakt (~833 Verzeichnisse, davon `movies/` 1.4 TB und `Heimatfilme/` 300 GB).
|
||||
|
||||
Reclaim:
|
||||
|
||||
- Operator-Claim-Token via `https://www.plex.tv/claim` als `Xeridos` erzeugt.
|
||||
- Plex-Container per `PLEX_CLAIM=claim-... docker compose up -d --force-recreate plex` am Host-Pfad `/mnt/user/services/stacks/plex/host-services/plex` neu erstellt. Token wurde **nur** als Shell-Inline-ENV mitgegeben, **nicht** in eine `.env`-Datei, **nicht** in die Compose, **nicht** in die Komodo-Stack-ENV geschrieben.
|
||||
- Nach Erfolg: zweiter `docker compose up -d --force-recreate plex` ohne `PLEX_CLAIM`, damit der verbrauchte Token nicht im `docker inspect`-ENV-Snapshot persistiert.
|
||||
- Bash-History defensiv geleert.
|
||||
|
||||
Endstand:
|
||||
|
||||
- `PlexOnlineUsername="Xeridos"`, `PlexOnlineMail="michideheld@gmx.de"`, `PlexOnlineHome="1"`.
|
||||
- Bibliotheken neu angelegt via Plex-Web → Verwalte Mediatheken → `/data/movies`, `/data/Heimatfilme` etc.
|
||||
- `PublishServerOnPlexOnlineKey="0"` (Remote Access deaktiviert), Plex-Relay aus.
|
||||
- 2026-06-06: Externer Komfortzugriff ueber `https://plex.kaleschke.info` via Traefik ergaenzt. Das ist **kein** Plex-Remote-Access und keine direkte FRITZ!Box-Freigabe auf `32400`; Plex bleibt hinter Traefik/443 und nutzt native Plex-Auth.
|
||||
|
||||
Konsequenzen fuer Doku/Betrieb:
|
||||
|
||||
- Plex-Home-Familien-Profil ("Familie") muss bei Bedarf neu eingeladen werden; war ohnehin nicht aktiv genutzt.
|
||||
- Watch-State aus der Zeit vor dem 18.05. ist nicht recoverbar; Filme/Serien laufen bei Wiederaufruf bei 00:00 los.
|
||||
- `host-services/plex/docker-compose.yml` enthaelt weiter `PLEX_CLAIM: ${PLEX_CLAIM:-}`, damit ein zukuenftiger Reclaim ohne Repo-Aenderung moeglich ist.
|
||||
|
||||
### Traefik — Wechsel zu reinen Docker-Labels (2026-03-28)
|
||||
Die statischen File-Provider-Konfigurationen in `/mnt/user/appdata/traefik/dynamic/` wurden vollständig bereinigt:
|
||||
- **Gelöscht:** `immich.yml`, `gitea.yml`, `mealie.yml`, `scrutiny.yml`, `vaultwarden.yml.bak`
|
||||
- **Verbleibend (notwendig):** `middlewares.yml`, `tls.yml`, `dashboards.yml`
|
||||
|
||||
**Hintergrund:** Die alten File-Provider-Configs haben `@file`-Routen mit `@docker`-Routen konkurrieren lassen. In Traefik v3 gewinnt der File-Provider und hat z.B. Immich auf die falsche IP geroutet (Bad Gateway). Nach Löschung läuft Traefik ausschließlich auf Docker-Labels.
|
||||
|
||||
**Regel:** Neue Dienste ausschließlich via Docker Compose Labels konfigurieren. Keine neuen `.yml`-Dateien im `dynamic/`-Verzeichnis für Service-Routen anlegen.
|
||||
|
||||
### Komodo — Ablösung von Portainer als Stack-Manager (2026-03-28)
|
||||
Komodo ist nun der primäre GitOps-Stack-Manager:
|
||||
- **Komodo Core** läuft als Docker-Stack (`ops/komodo/docker-compose.yml`)
|
||||
- **Komodo Periphery** läuft auf dem Unraid-Host für direktes Server-Management
|
||||
- Stacks werden via Gitea synchronisiert und über Komodo deployed
|
||||
- Portainer CE ist abgeschaltet; Komodo ist der alleinige aktive Stack-Manager
|
||||
|
||||
**Betriebsregel:** Alle Stack-Änderungen laufen über Git; Komodo konsumiert nur den Stand aus Gitea.
|
||||
|
||||
**Zugangsregel:** Komodo bleibt bewusst bei nativer Authentifizierung ohne pauschal vorgeschaltete ForwardAuth-Middleware vor dem gesamten Router. Hintergrund sind die gemischten UI-, API-, Webhook- und Periphery-Endpunkte unter derselben Domain.
|
||||
|
||||
### Komodo Self-Stack Drift-Recovery (2026-05-04)
|
||||
- Befund: `komodo-core` und `komodo-periphery` liefen aus temporaeren `/tmp/*repair.yml`-Dateien, waehrend `komodo-mongo` auf den fehlenden persistenten Pfad `/mnt/user/services/stacks/komodo/compose.yaml` verwies.
|
||||
- Recovery: Repair-YAMLs und Runtime-ENV wurden unter `/mnt/user/appdata/komodo/_drift_backup_2026-05-04/` gesichert; eine zusaetzliche Recovery-ENV liegt unter `/mnt/user/appdata/secrets/_komodo_stack_env_recovery_2026-05-04.env` und ist als temporaeres Tier-1-Secret-Material zu behandeln.
|
||||
- Der persistente Self-Stack wurde unter `/mnt/user/services/stacks/komodo/compose.yaml` aus `ops/komodo/docker-compose.yml` wiederhergestellt. Die hostseitige `.env` bleibt ausserhalb von Git.
|
||||
- Reconcile-Regel: Bei Self-Stack-Drift keinen pauschalen `docker compose up -d` ausfuehren, wenn der Dry-run `komodo-mongo` recreaten wuerde. Core und Periphery koennen gezielt mit `--no-deps` neu erstellt werden, Mongo bleibt dabei unangetastet.
|
||||
- Ergebnis: Alle drei Komodo-Container zeigen wieder auf `/mnt/user/services/stacks/komodo/compose.yaml`; Mongo blieb waehrend der Rueckfuehrung healthy.
|
||||
|
||||
### AdGuard Home — Ablösung von Pi-hole (2026-03-28)
|
||||
`binhex-official-pihole` wurde entfernt und durch `AdGuard Home` + `unbound` ersetzt:
|
||||
- AdGuard läuft als Git-Stack (`host-services/Adguard/docker-compose.yml`)
|
||||
- Netzwerke: `dns_net` (feste IP 172.23.0.3) + `frontend_net`
|
||||
- Port 53 (DNS) direkt gebunden — dokumentierte Ausnahme
|
||||
- Admin-UI direkt gebunden via Tailscale-IP `100.80.98.33:8082` auf Container-Port 80 — 2026-05-26 bewusst als einfache Operator-Entscheidung ohne Traefik-/2FA-Umstellung
|
||||
- `unbound` läuft weiterhin als Upstream-Resolver in `dns_net`
|
||||
|
||||
### diun — Entfernung (2026-03-28)
|
||||
`diun` (Docker Image Update Notifier) wurde deinstalliert:
|
||||
- Stack gelöscht
|
||||
- Orphan-Netzwerk `diun_diun_default` bereinigt
|
||||
- Repo-Eintrag `infra/diun/` aus Git entfernt
|
||||
|
||||
Update-Monitoring kann über Komodo's eingebaute Update-Notifications abgedeckt werden.
|
||||
|
||||
### ntfy — Push-Notifications (Git-Stack)
|
||||
`ntfy` läuft als Git-Stack (`apps/ntfy/docker-compose.yml`):
|
||||
- `ntfy.kaleschke.info` via Traefik
|
||||
- `NTFY_UPSTREAM_BASE_URL: https://ntfy.sh` für mobile Push-Notifications
|
||||
- `NTFY_BEHIND_PROXY: true` korrekt gesetzt
|
||||
|
||||
### immich_default — internal: true gesetzt (2026-03-29)
|
||||
`immich_default` wurde von `external: true` auf ein Compose-verwaltetes internes Netz umgestellt:
|
||||
- **Vorher:** `external: true` (manuell erstellt, falsche Labels `com.docker.compose.network=default`)
|
||||
- **Nachher:** Compose-managed, `internal: true`, `driver: bridge`, korrekte Labels
|
||||
- Durchgeführt via: manuelles `docker stop` der Containers → `docker network rm immich_default` → Komodo Redeploy
|
||||
- Ergebnis: alle Immich-Container (`immich_postgres`, `immich_redis`, `immich_machine_learning`) sind jetzt vom Internet isoliert; nur `immich_server` hat zusätzlich `frontend_net` für Traefik
|
||||
|
||||
### Secrets in Komodo Stacks
|
||||
Host-Pfade in `env_file` (z.B. `/mnt/...`) sind in Git-Stacks nicht verfügbar. Standardlösung: Stack Environment Variables + `${VARIABLE_NAME}` in der Compose.
|
||||
|
||||
**Regel:** Wenn `_FILE` nicht unterstützt wird → Stack Environment Variable. Kein Secret im Git.
|
||||
|
||||
**Bewusste Ausnahme:** `paperless-ngx` bleibt fuer `PAPERLESS_DBPASS` und `PAPERLESS_REDIS` vorerst bei Stack Environment Variables. Eine Umstellung auf `_FILE` ist fachlich denkbar, wird aber nicht gegen den aktuell stabilen Produktionsstand erzwungen.
|
||||
|
||||
### Borg UI / BorgBase (2026-04-12)
|
||||
- `borg-ui` läuft als Admin-Dienst in `ops/borg-ui/docker-compose.yml`
|
||||
- nur `frontend_net`, weil Web-UI + externer SSH-Zugang zu BorgBase benötigt werden
|
||||
- keine direkten Host-Ports; Zugriff ausschließlich via Traefik + Middleware über `borg.kaleschke.info`
|
||||
- breite Restore-/Backup-Mounts bewusst gesetzt; inklusive `/local/secrets` fuer Disaster Recovery, separates Restore-Ziel unter `/mnt/user/appdata/borg-ui/restore`
|
||||
- kein separater Borg-CLI-Container nötig, da Borg UI die Borg-CLI bereits im Container mitbringt
|
||||
|
||||
| Container | `_FILE` Support |
|
||||
|---|---|
|
||||
| Vaultwarden | ✅ ja |
|
||||
| PostgreSQL | ✅ ja |
|
||||
| code-server | ✅ ja (`PASSWORD_FILE`) |
|
||||
| Immich Postgres | ✅ ja (`POSTGRES_PASSWORD_FILE`) |
|
||||
| Mealie | ✅ ja (`POSTGRES_PASSWORD_FILE`) |
|
||||
| paperless-ngx | ❌ nein für DB-Pass → Stack ENV |
|
||||
|
||||
### Reproduzierbare Deployments (2026-04-17)
|
||||
Mutable Tags wie `latest`, `stable`, `release` oder reine Major-Tags wurden auf die **aktuell laufenden Digests** eingefroren. Das ist bewusst **kein Upgrade-Mechanismus**, sondern dient dazu, den heute funktionierenden Laufzeitstand exakt im Repo festzuhalten. Echte Versions-Upgrades bleiben ein eigener, geplanter Schritt.
|
||||
|
||||
### Stateful Digest-Pinning (2026-05-05, ergaenzt 2026-05-16)
|
||||
- Tier-1/stateful Basisdienste werden bevorzugt mit sprechendem Minor-/Patch-Tag plus Digest gepinnt, z. B. `postgres:17.9@sha256:...` oder `mongo:7.0.32@sha256:...`.
|
||||
- Redis-Caches sind seit dem Hardening-Sprint 2026-05-16 auf `redis:7.4-alpine@sha256:...` vereinheitlicht. Updates erfolgen bewusst stackweise mit Smoke-Test.
|
||||
- Bereits versionierte Apps koennen optional spaeter ebenfalls Digests erhalten; dieser Schritt ist getrennt vom Datenhalter-Pinning.
|
||||
|
||||
### Nextcloud und Stirling-PDF (2026-04-19)
|
||||
- `nextcloud` wird bewusst **nicht** als AIO-Stack gebaut, sondern als klassischer Docker-Microservice-Stack mit eigenem PostgreSQL und eigenem Redis. Das passt besser zum bestehenden GitOps-/Compose-Modell des Repos.
|
||||
- `nextcloud` bleibt bei nativer App-Authentifizierung ohne zentrale ForwardAuth-Middleware vor dem Router, damit Browser-Login, Desktop-/Mobile-Clients sowie WebDAV/CardDAV sauber funktionieren.
|
||||
- `stirling-pdf` wird als geschuetzter Tool-Stack hinter `authelia@file,secure-headers@file` betrieben; die interne Stirling-Login-Funktion bleibt deaktiviert, um Doppel-Login zu vermeiden.
|
||||
|
||||
### BentoPDF und Monitoring-Zielstack (2026-04-30, aktualisiert 2026-05-17)
|
||||
- `bentopdf` ersetzt repo-seitig `stirling-pdf` auf der bestehenden Domain `pdf.kaleschke.info`, bleibt aber bis zum bewussten Komodo-Deploy nur vorbereitet.
|
||||
- BentoPDF benoetigt fuer Office-Konvertierung die Cross-Origin-Isolation-Header `Cross-Origin-Opener-Policy: same-origin` und `Cross-Origin-Embedder-Policy: require-corp`; diese werden per Traefik-Docker-Middleware gesetzt.
|
||||
- `monitoring/` ist der zentrale Zielstack fuer Prometheus, Loki, Promtail, Grafana, node-exporter, cAdvisor und InfluxDB 3 Core.
|
||||
- `monitoring-grafana` wird als geschuetztes Monitoring-UI unter `monitoring.kaleschke.info` betrieben.
|
||||
- `monitoring-influxdb3-core` bleibt ohne Traefik-/Public-Route; fuer interne Writer wie Home Assistant kann Port `8181` per `INFLUXDB_BIND_IP` auf eine LAN-Adresse gebunden werden.
|
||||
- Fuer dieses Port-Publishing nutzt `monitoring-influxdb3-core` zusaetzlich `monitoring_influx_lan`. Das ist keine Public-App-Freigabe und ersetzt nicht die Token-Authentifizierung.
|
||||
- InfluxDB 3 Core nutzt einen festen Versionstag statt `latest`, weil der InfluxDB-`latest`-Tag versionsstrategisch im Umbruch ist.
|
||||
- Die alten Pfade `ops/grafana-influxdb` und `ops/loki` wurden am 2026-05-26 aus dem aktiven Repo entfernt; `monitoring/` ist der einzige Observability-Zielstack.
|
||||
- Uptime Kuma wurde nach erfolgreichem Blackbox-/Grafana-Smoke-Test entfernt; `monitoring/` ist die Quelle fuer HTTP-Erreichbarkeit und Alerts.
|
||||
|
||||
### Monitoring-Logging-Baseline (2026-05-17)
|
||||
- `monitoring-loki` laeuft intern auf `monitoring_net`, ohne Traefik-Route und ohne Host-Port.
|
||||
- `monitoring-promtail` sammelt Docker-Logs ueber `/var/run/docker.sock:ro` und `/var/lib/docker/containers:ro` und schreibt sie an Loki.
|
||||
- `monitoring-grafana` bekommt provisionierte Datasources fuer Prometheus, Loki und InfluxDB 3 Core.
|
||||
- Loki-Logdaten sind Diagnosematerial mit begrenzter Retention, keine primaere Restore-Quelle.
|
||||
|
||||
### Authelia ohne Redis-Session-Backend (2026-05-04)
|
||||
- Authelia nutzt PostgreSQL fuer persistente Storage-Daten, aber bewusst kein Redis-Session-Backend.
|
||||
- Das haelt den Tier-1-Auth-Pfad einfacher; nach einem Authelia-Restart muessen aktive Sessions neu aufgebaut werden.
|
||||
- `infra/redis` ist historisch als "shared Cache" angelegt, wird aber faktisch nur von Paperless als App-Cache genutzt. Immich, Nextcloud und Mealie betreiben jeweils eigene Redis-Instanzen in ihren App-internen Netzen; Authelia laeuft bewusst ohne Redis. Eine spaetere Konsolidierung in `apps/paperless/` (analog zu Mealie/Immich/Nextcloud) bleibt fachlich denkbar, ist aber kein priorisierter Schritt.
|
||||
|
||||
### ddns-updater — Netz-Ausnahme
|
||||
Bleibt bewusst in `frontend_net` statt `backend_net`, weil `backend_net` `internal: true` ist und ddns-updater die Cloudflare-API erreichen muss.
|
||||
|
||||
### mail-archiver — Hybrid-Dienst
|
||||
Benötigt `backend_net` (PostgreSQL) + `frontend_net` (IMAP-Abruf von GMX/Gmail). Kein reiner Backend-Dienst. Die Web-UI ist via Traefik unter `mail.kaleschke.info` erreichbar und wird durch `authelia@file,secure-headers@file` plus App-eigene Auth geschuetzt.
|
||||
|
||||
### Netzwerk-Standard für Apps mit Datenbanken
|
||||
- App → `frontend_net` + internes Netzwerk
|
||||
- Datenbank → nur internes Netzwerk (`internal: true`)
|
||||
|
||||
Beispiel (Mealie): `mealie` → `frontend_net` + `mealie_internal`, `mealie-postgres` → nur `mealie_internal`.
|
||||
Architektur- und Betriebsentscheidungen werden seit 2026-06-11 zentral in
|
||||
`docs/DECISIONS.md` gefuehrt (ADR-light: Entscheidung, Kontext, Review-Trigger).
|
||||
Dieses Dokument haelt nur noch das Zielbild. Neue Entscheidungen werden dort
|
||||
eingetragen; hier aendert sich nur etwas, wenn das Zielbild selbst betroffen
|
||||
ist (Netze, Zugangsmodell, Ausnahmen in Sektion 10).
|
||||
|
||||
---
|
||||
|
||||
## Schlussformel
|
||||
|
||||
Dieses Dokument ist keine lose Notiz, sondern das **operative Masterdokument** für die Docker- und Zugriffsarchitektur des Homelabs.
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
# Entscheidungs-Register (ADR-light)
|
||||
|
||||
Typ: Entscheidung · Stand: 2026-06-11 · Status: aktiv
|
||||
|
||||
Zentrales Register fuer Architektur- und Betriebsentscheidungen. Neueste oben.
|
||||
Jeder Eintrag: Entscheidung, Kontext, ggf. Alternativen und Review-Trigger.
|
||||
Lange Incident-Erzaehlungen gehoeren nicht hierher, sondern in den Commit bzw.
|
||||
Host-Report; hier steht das Destillat. Vorher lebten diese Eintraege verstreut
|
||||
in `HOMELAB_ARCHITECTURE_MASTER_V2.md` §13, `docs/MASTER_TODO.md` (Geparkt),
|
||||
`docs/HARDWARE_INVENTORY.md` und der Audit-Restliste.
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-11 — Doku-Konsolidierung: ein Fakt, ein Zuhause
|
||||
|
||||
**Entscheidung:** Die Dokumentation wird nach `docs/homelab-doku-optimierung.md` (archiviert) konsolidiert: `MASTER_TODO.md` ist die einzige Statusliste, dieses Register die einzige Entscheidungssammlung, `docs/archive/` nimmt abgeschlossene Snapshots auf, Erledigtes verlaesst die Arbeitskopie. Keine Ordner-Restruktur des Bestands.
|
||||
**Kontext:** 74 Markdown-Dateien / ~9.400 Zeilen; einzelne Sachverhalte waren an 6–9 Stellen dokumentiert; vier parallele Statuslisten.
|
||||
**Review-Trigger:** Quartals-Gaertnern (siehe `docs/REPO_MAP.md` Doku-Regeln).
|
||||
|
||||
## 2026-06-06 — baerchen: BitLocker und Veeam Storage Encryption bewusst aus
|
||||
|
||||
**Entscheidung:** BitLocker bleibt auf allen Laufwerken deaktiviert; Veeam Storage Encryption bleibt aus (`StorageEncryptionEnabled=False`).
|
||||
**Kontext:** Recovery laeuft ueber das Veeam-Image auf dem lokalen SMB-Share; kein Key-Management-Aufwand, Restrisiko physischer Diebstahl akzeptiert.
|
||||
**Review-Trigger:** Off-host-Auslagerung des Windows-Images oder geaendertes Risikoprofil. Runbook: `ops/windows-reinstall/docs/windows-image-backup-baseline.md`.
|
||||
|
||||
## 2026-06-06 — Tailscale: natives Unraid-Plugin kanonisch, restriktive ACL
|
||||
|
||||
**Entscheidung:** Tailscale laeuft ausschliesslich als natives Unraid-Plugin (`tailscale.plg`, Subnet-Router, State im Flash-Backup); der redundante userspace-Docker-Stack `host-services/tailscale/` wurde entfernt. Tailnet-ACL ist tag-basiert restriktiv (`tag:server`/`tag:operator`, `tag:family` schlafend), Default-Allow entfernt.
|
||||
**Kontext:** Zwei parallele `tailscaled`-Instanzen; nur die Plugin-Instanz routet. Details: `docs/NETWORK_INVENTORY.md`.
|
||||
**Review-Trigger:** Erstes reales Familiengeraet (Familien-Dienste in ACL konkretisieren).
|
||||
|
||||
## 2026-06-06 — Authelia: 2FA-Catch-all aktiv, OIDC-Rollout gestaffelt
|
||||
|
||||
**Entscheidung:** Catch-all `*.kaleschke.info` -> `two_factor` in Repo- und Host-Config. OIDC-SSO wird app-weise ausgerollt (live: Grafana, Mealie; deployed: Paperless). Immich- und Nextcloud-OIDC sowie Nextcloud-Operator-TOTP sind geparkt, bis Familien-Accounts existieren.
|
||||
**Kontext:** Nur der Operator hat aktuell einen Authelia-Account; Familien-SSO-Nutzen entsteht erst mit dem Onboarding. Runbook: `docs/AUTHELIA_OIDC_PLAN.md`.
|
||||
**Review-Trigger:** Family-Onboarding erreicht die App-Login-Ebene.
|
||||
|
||||
## 2026-06-05 — USV geparkt, Cold-Backup Hetzner-only, kein Strom-Monitoring
|
||||
|
||||
**Entscheidung:** Keine USV-Anschaffung dieses Quartal (Power-Loss bewusst akzeptiert). Off-site bleibt allein Hetzner-Borg, keine zweite rotierende Cold-Kopie. Stromverbrauch wird nicht gemessen (kein Messgeraet, kein Beschaffungs-Todo).
|
||||
**Review-Trigger:** USV: Q3-Review ab 2026-07-01, Hardware-Upgrade oder realer Stromausfall mit Datenfolge. Cold-Backup: Hetzner-Probleme oder stark wachsender Datenwert. Strom: nur bei Anschaffung eines Messgeraets.
|
||||
|
||||
## 2026-06-03 — Fix Common Problems Plugin entfernt, keine Neuinstallation
|
||||
|
||||
**Entscheidung:** FCP wurde deinstalliert und wird bewusst nicht wieder installiert.
|
||||
**Kontext:** Ein FCP-Scan hing 7 Tage in einem `grep -R`-Symlink-Loop ueber das gesamte Array (3 Cores 100 %, IOWAIT bis 55 %, Load 14.6 -> 1.08 nach Entfernung). Die abgedeckten Risiken uebernehmen Scrutiny, Monitoring-Stack, Posture-Check und Critical-Events-Watcher.
|
||||
**Review-Trigger:** keiner; Entscheidung ist final.
|
||||
|
||||
## 2026-06-01 — Borg append-only auf Hetzner nicht umgesetzt
|
||||
|
||||
**Entscheidung:** Kein append-only/forced-command auf der Storage Box.
|
||||
**Kontext:** Der forced-command-Test brach die Key-Auth und musste per Passwort-Recovery zurueckgesetzt werden; Nutzen/Betriebsrisiko-Verhaeltnis unguenstig. Kompensation (Storage-Box-Snapshots) siehe `docs/homelab-optimierung.md` Empfehlung 2.
|
||||
**Review-Trigger:** Hetzner bietet robusteren Mechanismus, oder Ransomware-Risikoprofil aendert sich.
|
||||
|
||||
## 2026-05-28 — Plex: Reclaim, Traefik-Route ohne ForwardAuth, kein Remote Access
|
||||
|
||||
**Entscheidung:** Plex-Server ist als Operator-Konto geclaimt; externer Zugriff laeuft ausschliesslich ueber Traefik/443 (`plex.kaleschke.info`, File-Provider-Ausnahme wegen Host-Netz), Plex Remote Access und WAN-Port 32400 bleiben aus, keine Authelia-ForwardAuth (native Plex-Auth).
|
||||
**Kontext:** Preferences waren nach dem Mai-Crash jungfraeulich; Claim-Token wurde nur als Shell-Inline-ENV genutzt, nie persistiert. Details: `docs/SERVICE_CATALOG.md`, `HOMELAB_ARCHITECTURE_MASTER_V2.md` §10.
|
||||
|
||||
## 2026-05-28 — Gitea-SSH (222) bleibt ohne WAN-Freigabe
|
||||
|
||||
**Entscheidung:** Port 222 wird nicht in der FRITZ!Box freigegeben.
|
||||
**Kontext:** Tailscale ist der Operator-Pfad, der GitHub-Mirror deckt DR-Bootstrap ab, SSH-Brute-Force-Vektor extern vermeiden.
|
||||
|
||||
## 2026-05-28 — paperless-gpt und BentoPDF bleiben aktiv
|
||||
|
||||
**Entscheidung:** Beide Container bleiben trotz geringer Nutzung. paperless-gpt-Abloese wird erst mit Paperless-NGX 3.0 (eigene KI-Features) neu bewertet; BentoPDF ist situatives Tool mit vernachlaessigbarem Footprint und ersetzt Stirling-PDF.
|
||||
**Review-Trigger:** Paperless-NGX-3.0-Release.
|
||||
|
||||
## 2026-05-26 — AdGuard-Admin nur auf Tailscale-IP, ohne Traefik/2FA
|
||||
|
||||
**Entscheidung:** Admin-UI bleibt auf `100.80.98.33:8082` (Tailscale-only) gebunden; bewusst keine Traefik-/2FA-Umstellung. DNS-Port 53 bleibt direkte Host-Port-Ausnahme.
|
||||
**Review-Trigger:** Aenderung des Tailnet-Zugangsmodells.
|
||||
|
||||
## 2026-05-25 — Ein Dienst pro Funktion: Jellyfin, Homepage, Uptime-Kuma entfernt
|
||||
|
||||
**Entscheidung:** Plex ist der einzige Medienserver, Glance das einzige Dashboard, Blackbox-Exporter + Prometheus-Alerts + Grafana ersetzen Uptime-Kuma.
|
||||
**Kontext:** Doppelte Dienste = doppelte Pflege/Attack-Surface. Removal-Checkliste: `docs/WORKFLOW.md`.
|
||||
|
||||
## 2026-05-17 — Monitoring-/Logging-Baseline
|
||||
|
||||
**Entscheidung:** `monitoring/` ist der einzige Observability-Stack (Prometheus, Loki, Promtail, Grafana, Exporter, InfluxDB 3 Core). Loki intern ohne Route, Promtail mit read-only Docker-Socket, Loki-Daten sind Diagnosematerial mit Retention, keine Restore-Quelle. Alte Pfade `ops/loki`/`ops/grafana-influxdb` sind entfernt (Rollback nur via Git-Historie).
|
||||
|
||||
## 2026-05-05 — Stateful Digest-Pinning und Versionspolitik
|
||||
|
||||
**Entscheidung:** Tier-1-/stateful Dienste laufen mit sprechendem Versions-Tag plus Digest (z. B. `postgres:17.x@sha256:...`); mutable Tags wurden 2026-04-17 auf laufende Digests eingefroren. Digest-Pinning ist Reproduzierbarkeit, kein Upgrade-Mechanismus; echte Upgrades sind eigene Aenderungsbloecke. Renovate (live seit 2026-05-29) liefert PRs, kein Auto-Merge.
|
||||
**Review-Trigger:** Mutable-Tag-Restbestand siehe `docs/homelab-optimierung.md` Empfehlung 1.
|
||||
|
||||
## 2026-05-04 — Authelia ohne Redis-Session-Backend
|
||||
|
||||
**Entscheidung:** Authelia nutzt PostgreSQL fuer Storage, aber kein Redis-Session-Backend; nach Restart werden Sessions neu aufgebaut.
|
||||
**Kontext:** Haelt den Tier-1-Auth-Pfad einfach. `infra/redis` ist faktisch nur Paperless-Cache; Konsolidierung nach `apps/paperless/` bleibt denkbar, unpriorisiert.
|
||||
|
||||
## 2026-05-04 — Komodo-Self-Stack: Reconcile-Regel nach Drift
|
||||
|
||||
**Entscheidung:** Der Komodo-Self-Stack laeuft aus `/mnt/user/services/stacks/komodo/compose.yaml` (Quelle: `ops/komodo/docker-compose.yml`). Bei Self-Stack-Drift kein pauschales `docker compose up -d`, wenn der Dry-run `komodo-mongo` recreaten wuerde; Core/Periphery gezielt mit `--no-deps` neu erstellen, Mongo unangetastet lassen.
|
||||
**Kontext:** Drift-Recovery 2026-05-04 (Repair-YAMLs aus `/tmp`); Sicherungen unter `/mnt/user/appdata/komodo/_drift_backup_2026-05-04/`.
|
||||
|
||||
## 2026-04-19 — Nextcloud als klassischer Stack, nicht AIO; native Auth
|
||||
|
||||
**Entscheidung:** Nextcloud laeuft als App + eigene PostgreSQL + eigene Redis (kein AIO), ohne zentrale ForwardAuth (Browser-/Client-/WebDAV-Flows brauchen native Auth).
|
||||
|
||||
## 2026-04-12 — Borg-Scope enthaelt bewusst /local/secrets
|
||||
|
||||
**Entscheidung:** Borg sichert ausgewaehltes Secret-Material (`/local/secrets`) als Teil der DR-Strategie; `borg-ui` hat dafuer breite, bewusste Mounts. Dumps statt Raw-DB-Pfade sind der primaere Restore-Weg.
|
||||
**Kontext:** `ops/borg-ui/BACKUP_SCOPE.md`.
|
||||
|
||||
## 2026-03-28/29 — GitOps-Fundament
|
||||
|
||||
**Entscheidung:** Komodo ersetzt Portainer als alleiniger Stack-Manager (Docker-Socket-Ausnahme, native Auth ohne pauschale ForwardAuth wegen Webhooks/`/ws/periphery`). Traefik routet ausschliesslich ueber Docker-Labels; File-Provider nur fuer `middlewares.yml`, `tls.yml`, `dashboards.yml` (+ dokumentierte `plex.yml`-Ausnahme). AdGuard Home + Unbound ersetzen Pi-hole.
|
||||
**Kontext:** Konkurrierende `@file`-/`@docker`-Router hatten Fehlrouting verursacht; Regel: keine neuen Service-Routen im File-Provider.
|
||||
|
||||
## Aelteres / Sonderfaelle
|
||||
|
||||
- **Paperless Stack-ENV-Ausnahme:** `PAPERLESS_DBPASS`/`PAPERLESS_REDIS` bleiben Komodo-Stack-ENV (kein `_FILE`-Support im Image); Konsequenzen fuer DR siehe `docs/DISASTER_RECOVERY.md` Phase 2.
|
||||
- **ddns-updater in `frontend_net`:** braucht Cloudflare-API; `backend_net` ist internal.
|
||||
- **mail-archiver Hybrid:** `frontend_net` (IMAP) + `backend_net` (DB), App-Auth zusaetzlich zu Authelia.
|
||||
- Vollstaendige technische Ausnahmen-Liste mit Begruendung: `HOMELAB_ARCHITECTURE_MASTER_V2.md` §10 (bleibt dort autoritativ).
|
||||
+14
-63
@@ -1,6 +1,10 @@
|
||||
# Rollback Guide - Homelab
|
||||
# Rollback Guide - Homelab
|
||||
|
||||
Typ: Runbook · Stand: 2026-06-11 · Status: aktiv
|
||||
|
||||
Dieses Dokument beschreibt den sicheren Rueckweg im aktuellen GitOps-Betrieb.
|
||||
Rollback-Anleitungen fuer bereits entfernte Dienste (Uptime-Kuma, Grafana-/
|
||||
InfluxDB-Altstack, Stirling-PDF) liegen in der Git-Historie, nicht mehr hier.
|
||||
|
||||
---
|
||||
|
||||
@@ -72,59 +76,14 @@ Bei Problemen mit Borg UI oder Dump-Automatisierung:
|
||||
3. Persistenz unter `/mnt/user/appdata/borg-ui/` und `/mnt/user/backups/borg/dumps/` nicht blind loeschen
|
||||
4. Restore zuerst in einen Testpfad schreiben, nicht direkt in Produktivpfade
|
||||
|
||||
## BentoPDF / Stirling-PDF Rollback
|
||||
## Monitoring-Stack Rollback
|
||||
|
||||
Bei Problemen mit BentoPDF:
|
||||
|
||||
1. Git-Stand auf die letzte funktionierende Stirling-PDF-Compose zuruecknehmen oder gezielt `apps/bentopdf` wieder durch `apps/stirling-pdf` ersetzen
|
||||
2. Commit + Push nach Gitea
|
||||
3. betroffenen Stack in Komodo redeployen
|
||||
4. `https://pdf.kaleschke.info` pruefen
|
||||
|
||||
Die alte Stirling-PDF-Persistenz unter `/mnt/user/appdata/stirling-pdf` nicht loeschen, solange der BentoPDF-Ersatz nicht fachlich abgenommen ist.
|
||||
|
||||
## Grafana / InfluxDB Rollback
|
||||
|
||||
Vor dem ersten produktiven Einsatz reicht es, den vorbereiteten Stack nicht zu deployen oder per Ruecknahme-Commit aus dem Repo zu entfernen.
|
||||
|
||||
Nach einem Deploy:
|
||||
|
||||
1. alten Grafana/InfluxDB-Stack in Komodo gestoppt lassen; der fruehere Compose-Pfad `ops/grafana-influxdb` ist seit 2026-05-26 nicht mehr im aktiven Repo
|
||||
2. Persistenz unter `/mnt/user/appdata/grafana` und `/mnt/user/appdata/influxdb3` unangetastet lassen
|
||||
3. Secrets unter `/mnt/user/appdata/secrets/grafana_admin_password.txt`, `/mnt/user/appdata/secrets/grafana_influxdb_token.txt` und `/mnt/user/appdata/secrets/influxdb3_admin_token.json` nur nach bewusstem Entscheid entfernen
|
||||
4. Grafana-Domain und InfluxDB-Zugriff testen, bis klar ist, dass keine produktiven Dashboards oder Writer mehr davon abhaengen
|
||||
|
||||
## Monitoring-Zielstack Rollback
|
||||
|
||||
Der Zielzustand ist `monitoring/` als einziger Observability-Stack. Bei Problemen nach der Migration:
|
||||
`monitoring/` ist der einzige Observability-Stack. Bei Problemen:
|
||||
|
||||
1. `monitoring` in Komodo stoppen oder auf den letzten funktionierenden Commit zurueckgehen
|
||||
2. nur im echten Notfall die abgeloesten Altstaende aus der Git-Historie vor dem Repo-Cleanup wiederherstellen, z. B. aus Commit `ff5991c`; nicht dauerhaft parallel zum Zielstack betreiben
|
||||
3. named volumes `prometheus_data`, `loki_data`, `promtail_positions`, `grafana_data` sowie `/mnt/user/appdata/influxdb3` nicht blind loeschen
|
||||
4. Secrets `monitoring_grafana_admin_password.txt`, `monitoring_grafana_influxdb_token.txt` und `influxdb3_admin_token.json` nur nach bewusstem Entscheid entfernen
|
||||
5. Home Assistant Writer erst wieder umstellen, wenn `curl -i http://192.168.178.58:8181/` erwartbar `401 Unauthorized` liefert
|
||||
6. Grafana-Datasources `Prometheus`, `Loki` und `InfluxDB 3 Core` testen
|
||||
|
||||
## Uptime Kuma Removal Rollback
|
||||
|
||||
Falls die Blackbox-/Grafana-Ablösung unerwartet nicht ausreicht:
|
||||
|
||||
1. per Ruecknahme-Commit `ops/uptime-kuma/docker-compose.yml`, die Blackbox-/Glance-/Authelia-Referenzen und die Restore-Freshness-Pruefung auf den letzten Uptime-Kuma-Stand zurueckbringen
|
||||
2. nach Gitea pushen und den Uptime-Kuma-Stack in Komodo neu anlegen oder aus dem letzten Stack-Backup wiederherstellen
|
||||
3. `/mnt/user/appdata/_archive/uptime-kuma-removed-2026-05-25` nach `/mnt/user/appdata/uptime-kuma` zurueckverschieben, falls die Archivierung bereits erfolgt ist
|
||||
4. `https://uptime.kaleschke.info` und die Monitore pruefen
|
||||
5. erst danach den Blackbox-/Grafana-Zielzustand erneut bewerten
|
||||
|
||||
## Glance Dashboard Rollback
|
||||
|
||||
Vor dem ersten produktiven Einsatz reicht es, den vorbereiteten Stack `ops/glance` nicht zu deployen oder per Ruecknahme-Commit aus dem Repo zu entfernen.
|
||||
|
||||
Nach einem Deploy:
|
||||
|
||||
1. `glance` in Komodo stoppen oder auf den letzten funktionierenden Commit zurueckgehen
|
||||
2. keine Produktivdaten loeschen; Glance nutzt nur Repo-Konfiguration und Stack-ENV
|
||||
3. pruefen, ob `https://glance.kaleschke.info` nicht mehr geroutet wird oder wieder den erwarteten Stand zeigt
|
||||
4. der `glance-docker-socket-proxy` darf nicht separat als Dauercontainer laufen bleiben
|
||||
2. named volumes `prometheus_data`, `loki_data`, `promtail_positions`, `grafana_data` sowie `/mnt/user/appdata/influxdb3` nicht blind loeschen
|
||||
3. Secrets (`monitoring_grafana_admin_password.txt`, `monitoring_grafana_influxdb_token.txt`, `influxdb3_admin_token.json`) nur nach bewusstem Entscheid entfernen
|
||||
4. Grafana-Datasources `Prometheus`, `Loki` und `InfluxDB 3 Core` testen
|
||||
|
||||
---
|
||||
|
||||
@@ -132,19 +91,11 @@ Nach einem Deploy:
|
||||
|
||||
Bevorzugte Quellen:
|
||||
|
||||
- Borg-Restore
|
||||
- erzeugte PostgreSQL-/MariaDB-Dumps
|
||||
- bekannte Appdata-Snapshots
|
||||
- Borg-Restore (zuerst in Testpfade unter `/mnt/user/backups/restore-lab/`)
|
||||
- erzeugte Dumps unter `/mnt/user/backups/borg/dumps/latest`
|
||||
- bekannte Appdata-Archivstaende unter `/mnt/user/appdata/_archive/`
|
||||
|
||||
Beispiele:
|
||||
|
||||
```bash
|
||||
cp -r /mnt/user/appdata/<service> /mnt/user/backup/
|
||||
```
|
||||
|
||||
```bash
|
||||
pg_dumpall > /mnt/user/backup/pg_dump_$(date +%Y%m%d).sql
|
||||
```
|
||||
Dienst-spezifische Restore-Quellen, Dumps und Smoke-Tests stehen in `docs/RESTORE_MATRIX.md`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user