Consolidate monitoring target stack

This commit is contained in:
2026-05-17 10:41:29 +02:00
parent 61625a7a1c
commit b7dfdad621
21 changed files with 250 additions and 64 deletions
+27 -22
View File
@@ -47,14 +47,14 @@
## 2. Architektur-Prinzipien
### P1 — Traefik ist der einzige öffentliche HTTP(S)-Einstiegspunkt
Kein Webdienst veröffentlicht finale direkte Host-Ports außer `traefik` selbst. Begründete Ausnahmen: `gitea`-SSH (Port 222), `AdGuard Home` (Port 53/DNS + 8082/Admin), `Tailscale`, `Plex-Media-Server` und `influxdb3-core` Port 8181 als LAN-only Writer-Endpunkt fuer Home Assistant.
Kein Webdienst veröffentlicht finale direkte Host-Ports außer `traefik` selbst. Begründete Ausnahmen: `gitea`-SSH (Port 222), `AdGuard Home` (Port 53/DNS + 8082/Admin), `Tailscale`, `Plex-Media-Server` und `monitoring-influxdb3-core` Port 8181 als LAN-only Writer-Endpunkt fuer Home Assistant.
### P2 — Das Setup bleibt bewusst einfach: `frontend_net` + `backend_net` + app-interne Netze
- `frontend_net` = Proxy-/Web-Netz
- `backend_net` = intern für DB/Cache/App-Kommunikation
- zusätzliche Netze nur app-intern, wenn technisch nötig (`mealie_internal`, `immich_default`, `dns_net`)
Es gibt **keine künstlichen globalen Zusatznetze** wie `admin_net`, `monitoring_net` oder `media_net`.
Es gibt **keine künstlichen globalen Zusatznetze** wie `admin_net` oder `media_net`. `monitoring_net` ist die dokumentierte Ausnahme fuer den zentralen Observability-Stack.
### P3 — Datenbanken gehören nie ins `frontend_net`
Postgres, Redis und ähnliche Dienste laufen ausschließlich in `backend_net` oder einem eigenen internen Compose-Netz.
@@ -90,8 +90,10 @@ Jeder produktive Container nutzt `restart: unless-stopped`, außer eine Ausnahme
| `mealie_internal` | bridge, `internal: true` | internes Netz nur für `mealie` + `mealie-postgres` | ✅ umgesetzt |
| `immich_default` | Compose-intern, `internal: true` | internes Immich-Netz | ✅ umgesetzt |
| `nextcloud_internal` | bridge, `internal: true` | internes Netz nur fuer `nextcloud` + `nextcloud-postgres` + `nextcloud-redis` | ✅ vorbereitet |
| `grafana_influx_internal` | Compose-intern, `internal: true` | interne Grafana-zu-InfluxDB-Kommunikation | ✅ umgesetzt |
| `grafana_influx_lan` | Compose-intern, bridge | nicht-oeffentliches Zusatznetz nur fuer Docker Host-Port-Publishing von InfluxDB 8181 | ✅ umgesetzt |
| `monitoring_net` | Compose-intern, bridge | zentraler Observability-Stack fuer Prometheus, Loki, Grafana, Promtail, Exporter und InfluxDB | Zielzustand |
| `monitoring_influx_lan` | Compose-intern, bridge | nicht-oeffentliches Zusatznetz nur fuer Docker Host-Port-Publishing von InfluxDB 8181 | Zielzustand |
| `grafana_influx_internal` | Compose-intern, `internal: true` | alte Grafana-zu-InfluxDB-Kommunikation | abgeloester Altstand |
| `grafana_influx_lan` | Compose-intern, bridge | altes Docker Host-Port-Publishing von InfluxDB 8181 | abgeloester Altstand |
| `host` | host | nur für echte Sonderfälle | begründet |
### 3.2 Finales Diagramm (vereinfacht)
@@ -121,8 +123,10 @@ App-interne Netze
├── mealie_internal (internal: true) ✅
├── immich_default (internal: true) ✅
├── nextcloud_internal (internal: true) ✅
├── grafana_influx_internal (internal: true)
── grafana_influx_lan (Bridge fuer LAN-Port-Publishing, keine Traefik-Route)
├── monitoring_net (zentraler Observability-Stack)
── monitoring_influx_lan (Bridge fuer LAN-Port-Publishing, keine Traefik-Route)
├── grafana_influx_internal (Altstand)
└── grafana_influx_lan (Altstand)
Host-Sonderfälle
├── tailscale
@@ -160,7 +164,7 @@ Diese Dienste sind **keine Public Apps**:
- `glances` — glances.kaleschke.info (Middleware)
- `speedtest-tracker` — speedtest.kaleschke.info (Middleware)
- `bentopdf` — pdf.kaleschke.info (Middleware)
- `grafana`grafana.kaleschke.info (Middleware)
- `monitoring-grafana`monitoring.kaleschke.info (Middleware)
- `hermes-dashboard` — hermes.kaleschke.info (Middleware)
- `Traefik-Dashboard`
- `AdGuard Home` — Port 8082 direkt auf die Admin-UI (`80` im Container), kein Traefik, nur LAN-Zugang
@@ -294,10 +298,11 @@ Legende Status:
| `glances` | ✅ | `frontend_net` | Traefik + Middleware | aktiv via `glances.kaleschke.info` | — |
| `scrutiny` | ✅ | `frontend_net` | Traefik + Middleware | aktiv via `scrutiny.kaleschke.info`, Git-Stack | `privileged` später prüfen |
| `speedtest-tracker` | ✅ | `frontend_net` | Traefik + Middleware | aktiv via `speedtest.kaleschke.info` | — |
| `grafana` | | `frontend_net`, `grafana_influx_internal` | Traefik + Middleware | aktiv via `grafana.kaleschke.info`, InfluxDB-Datenquelle provisioniert; laeuft aktuell als `user: "0"` wegen Host-Appdata-Permissions | Wetter-/HA-Dashboard aufbauen; UID/GID-Hardening spaeter pruefen |
| `influxdb3-core` | | `grafana_influx_internal`, `grafana_influx_lan` + LAN-Bind | LAN-Port nur fuer interne Writer | InfluxDB 3 Core fuer Metriken; keine Traefik-/Public-Freigabe; Port 8181 nur via `INFLUXDB_BIND_IP`; laeuft aktuell als `user: "0"` wegen Host-Appdata-Permissions | HA-Write-Token und Sensor-Export finalisieren; UID/GID-Hardening spaeter pruefen |
| `monitoring-grafana` | Ziel | `frontend_net`, `monitoring_net` | Traefik + Middleware | zentrale UI via `monitoring.kaleschke.info`; Datasources fuer Prometheus, Loki und InfluxDB | nach Deploy testen |
| `monitoring-influxdb3-core` | Ziel | `monitoring_net`, `monitoring_influx_lan` + LAN-Bind | LAN-Port nur fuer interne Writer | InfluxDB 3 Core fuer Home-Assistant-/Ecowitt-Langzeitdaten; keine Traefik-/Public-Freigabe; Port 8181 nur via `INFLUXDB_BIND_IP` | HA-Write-Token und Sensor-Export finalisieren |
| `loki` | ✅ | `backend_net` | intern | interner Container-Logspeicher ohne Public Route; Grafana greift ueber Loki-Datasource zu | Retention/Storage nach erstem Produktivlauf beobachten |
| `alloy` | | `backend_net` | intern | Docker-Log-Collector mit read-only Docker-Socket-Ausnahme; schreibt nach Loki | keine Secrets; Socket-Ausnahme regelmaessig pruefen |
| `monitoring-promtail` | Ziel | `monitoring_net` | intern | Docker-Log-Collector mit read-only Docker-Socket-Ausnahme; schreibt nach Loki | Socket-Ausnahme regelmaessig pruefen |
| `grafana` / `influxdb3-core` / `loki` / `alloy` | Altstand | diverse | abgeloest | nicht parallel zum `monitoring/`-Zielstack betreiben | nach erfolgreicher Migration stoppen |
### 7.7 Noch offene Sonderfälle
@@ -395,9 +400,8 @@ Für den laufenden Betrieb gilt stattdessen:
| `mail-archiver` | `frontend_net` + `backend_net` | braucht Internetzugang für IMAP-Abruf (GMX, Gmail) und DB-Zugang |
| `traefik/dynamic/*` | manueller Host-Sync trotz GitOps | File-Provider bleibt bewusst fuer `middlewares.yml`, `tls.yml` und `dashboards.yml`; Komodo deployed diese Dateien nicht automatisch |
| `nextcloud` | keine zentrale ForwardAuth-Middleware | Nextcloud bringt eigene Auth, Clients und WebDAV/CardDAV-Endpunkte mit; Traefik bleibt Reverse Proxy, Auth bleibt app-nativ |
| `influxdb3-core` | Host-Port 8181 auf LAN-IP | Home Assistant laeuft in einer VM ausserhalb des Compose-Netzes und muss Metriken schreiben koennen; keine Traefik-Route, kein `frontend_net`, Zugriff nur ueber Token und LAN-IP `INFLUXDB_BIND_IP` |
| `grafana`, `influxdb3-core` | `user: "0"` | aktueller Live-Stand fuer Host-Appdata-/Plugin-Permissions; als Ausnahme dokumentiert, spaeter separat mit UID/GID-Test haerten |
| `alloy` | Docker-Socket read-only | Docker-Log-Discovery fuer Loki; keine Schreibrechte, keine Appdaten-Persistenz ueber den Socket |
| `monitoring-influxdb3-core` | Host-Port 8181 auf LAN-IP | Home Assistant laeuft in einer VM ausserhalb des Compose-Netzes und muss Metriken schreiben koennen; keine Traefik-Route, kein `frontend_net`, Zugriff nur ueber Token und LAN-IP `INFLUXDB_BIND_IP` |
| `monitoring-promtail` | Docker-Socket read-only | Docker-Log-Discovery fuer Loki; keine Schreibrechte, keine Appdaten-Persistenz ueber den Socket |
---
@@ -547,19 +551,20 @@ Mutable Tags wie `latest`, `stable`, `release` oder reine Major-Tags wurden auf
- `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 Grafana/InfluxDB vorbereitet (2026-04-30)
### 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.
- `grafana` wird als geschuetztes Monitoring-UI unter `grafana.kaleschke.info` betrieben.
- `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 `influxdb3-core` zusaetzlich zum internen Grafana-Netz `grafana_influx_lan`. Das ist keine Public-App-Freigabe und ersetzt nicht die Token-Authentifizierung.
- `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.
- `grafana` und `influxdb3-core` laufen aktuell als `user: "0"`; das ist als Host-Appdata-Permissions-Ausnahme dokumentiert und wird nicht nebenbei geaendert.
- Die alten Pfade `ops/grafana-influxdb` und `ops/loki` sind abgeloeste Altstaende und sollen nach erfolgreichem Monitoring-Deploy nicht parallel betrieben werden.
### Loki/Alloy Logging-Baseline (2026-05-16)
- `loki` laeuft intern auf `backend_net`, ohne Traefik-Route und ohne Host-Port.
- `alloy` sammelt Docker-Logs ueber `/var/run/docker.sock:ro` und schreibt sie an Loki.
- Grafana bekommt eine provisionierte Loki-Datasource und einfache Start-Dashboards fuer Logs, Restart-Events und Error-Rate.
### 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)
+1 -1
View File
@@ -64,4 +64,4 @@ Bei Restore-, Host-Ausfall- oder Wiederanlauf-Fragen zusaetzlich:
- Mutable Image-Tags sind auf die aktuell laufenden Digests eingefroren; echte Versions-Upgrades erfolgen bewusst separat.
- Disaster-Recovery und dienstspezifische Restore-Quellen sind in `docs/DISASTER_RECOVERY.md` und `docs/RESTORE_MATRIX.md` beschrieben.
- Der verbindliche Detailablauf steht in `docs/WORKFLOW.md`.
- `nextcloud`, `bentopdf` und `grafana-influxdb` folgen dem dokumentierten Netz-/Secret-/Traefik-Modell; Grafana/InfluxDB ist fuer Home-Assistant-Wetterdaten vorbereitet.
- `nextcloud`, `bentopdf` und `monitoring` folgen dem dokumentierten Netz-/Secret-/Traefik-Modell; der zentrale Monitoring-Stack buendelt Prometheus, Loki, Promtail, Grafana und InfluxDB 3 Core.
+5 -3
View File
@@ -78,11 +78,13 @@ Nach Aenderungen an `services.json` oder `check_health.py`: `git pull` auf der V
### Monitoring / Metriken
- Grafana laeuft unter `grafana.kaleschke.info` hinter Traefik + Authelia.
- InfluxDB 3 Core ist nicht public und nicht im `frontend_net`.
- Zielzustand ist ein zentraler Stack `monitoring/` unter `https://monitoring.kaleschke.info`.
- `monitoring-grafana` ist die zentrale UI fuer Prometheus, Loki und InfluxDB 3 Core.
- `monitoring-prometheus` sammelt Infrastruktur-Metriken; `monitoring-loki` + `monitoring-promtail` sammeln Docker-Logs.
- `monitoring-influxdb3-core` ist nicht public und nicht im `frontend_net`.
- Home Assistant schreibt ueber LAN-only Port 8181 nach InfluxDB, gebunden ueber `INFLUXDB_BIND_IP`.
- Ein `401 Unauthorized` von InfluxDB ohne Token ist beim Reachability-Test ein Erfolgssignal.
- Grafana und InfluxDB laufen aktuell als `user: "0"`; nicht ad hoc aendern, sondern als eigenen UID/GID-Hardening-Sprint behandeln.
- `ops/loki` und `ops/grafana-influxdb` sind abgeloeste Altstaende und sollen nach erfolgreichem Monitoring-Deploy nicht parallel betrieben werden.
## Deployment-Logik
+1 -1
View File
@@ -273,7 +273,7 @@ Ziel:
22. `ops/glances/`
23. `ops/scrutiny/`
24. `ops/speedtest/`
25. `ops/grafana-influxdb/`
25. `monitoring/`
26. `ops/hermes-agent/`
27. `infra/ddns-updater/`
+7 -7
View File
@@ -90,18 +90,18 @@ Sollzustand:
Soll fuer Home Assistant:
```bash
cd /mnt/user/services/stacks/grafana
cd /mnt/user/services/stacks/monitoring
git fetch --all --prune
git reset --hard origin/master
docker compose --env-file .env -p grafana -f ops/grafana-influxdb/docker-compose.yml up -d --force-recreate --no-deps influxdb3-core
docker compose --env-file .env -p monitoring -f monitoring/docker-compose.yml up -d --force-recreate --no-deps influxdb3-core
```
Danach pruefen:
```bash
docker network ls | grep -E "grafana|influx"
docker inspect influxdb3-core --format '{{json .NetworkSettings.Networks}}'
docker inspect influxdb3-core --format '{{json .NetworkSettings.Ports}}'
docker network ls | grep -E "monitoring|influx"
docker inspect monitoring-influxdb3-core --format '{{json .NetworkSettings.Networks}}'
docker inspect monitoring-influxdb3-core --format '{{json .NetworkSettings.Ports}}'
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep influx
ss -ltnp | grep 8181
curl -i --max-time 5 http://192.168.178.58:8181/
@@ -110,12 +110,12 @@ curl -i --max-time 5 http://192.168.178.58:8181/
Erwartung:
- Komodo Workspace `HEAD` entspricht `origin/master`.
- `influxdb3-core` haengt an `grafana_grafana_influx_internal` und `grafana_grafana_influx_lan`.
- `monitoring-influxdb3-core` haengt an `monitoring_monitoring_net` und `monitoring_monitoring_influx_lan`.
- Docker zeigt `192.168.178.58:8181->8181/tcp`.
- `ss` zeigt `docker-proxy` auf `192.168.178.58:8181`.
- `curl` bekommt `401 Unauthorized` von InfluxDB.
Hinweis: Im Compose-File heissen die Netze `grafana_influx_internal` und `grafana_influx_lan`. Durch den Compose-Projektnamen `grafana` werden daraus zur Laufzeit die Docker-Netze `grafana_grafana_influx_internal` und `grafana_grafana_influx_lan`.
Hinweis: Im Compose-File heissen die Netze `monitoring_net` und `monitoring_influx_lan`. Durch den Compose-Projektnamen `monitoring` koennen daraus zur Laufzeit Docker-Netze mit Projektpraefix werden.
## Stop-Regel
+3 -3
View File
@@ -15,13 +15,13 @@ Ziel: Home Assistant schreibt ausgewaehlte Ecowitt- und Energiesensoren nach Inf
Der Stack haelt InfluxDB bewusst ohne Traefik-Route. Fuer Home Assistant wird nur der HTTP-Port `8181` auf einer internen LAN-Adresse veroeffentlicht.
In Komodo/Stack-Environment fuer `ops/grafana-influxdb` setzen:
Im Zielzustand in Komodo/Stack-Environment fuer `monitoring` setzen:
```env
INFLUXDB_BIND_IP=192.168.178.58
```
`192.168.178.58` ist die LAN-IP des Docker-Hosts, auf dem `influxdb3-core` laeuft. Nicht `0.0.0.0` verwenden, wenn es nicht notwendig ist.
`192.168.178.58` ist die LAN-IP des Docker-Hosts, auf dem `monitoring-influxdb3-core` laeuft. Nicht `0.0.0.0` verwenden, wenn es nicht notwendig ist.
Danach den Stack neu deployen und von Home Assistant aus pruefen:
@@ -97,7 +97,7 @@ ha core restart
## 5. Grafana Smoke-Test
In Grafana mit der bestehenden Datenquelle `InfluxDB 3 Core` eine SQL-Abfrage testen:
In `https://monitoring.kaleschke.info` mit der bestehenden Datenquelle `InfluxDB 3 Core` eine SQL-Abfrage testen:
```sql
SHOW TABLES
+7
View File
@@ -16,6 +16,13 @@ Dieses Dokument ist nur noch ein historischer Verlauf. Der aktuelle operative Ab
## Historische Meilensteine
### 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.
+9 -4
View File
@@ -1,6 +1,6 @@
# Aktuelle Restliste - KalliLab CORE
Stand: 2026-05-16
Stand: 2026-05-17
Diese Datei ersetzt die alte Sprint-Liste vom 2026-05-16. Die damaligen Backup-, Posture-, Logging- und Hardening-Bloecke sind weitgehend erledigt oder dokumentiert. Sie bleibt nur als kurze Restliste fuer die naechsten bewussten Arbeitspakete bestehen.
@@ -11,15 +11,20 @@ Diese Datei ersetzt die alte Sprint-Liste vom 2026-05-16. Die damaligen Backup-,
- Gitea Webhook-Allowlist: `GITEA__webhook__ALLOWED_HOST_LIST` ist auf `komodo-core,localhost,127.0.0.1,192.168.178.0/24` eingeschraenkt.
- Backup-Konsistenz: SQLite-/Nextcloud-Dumps, Borg-Scope fuer Nextcloud-Daten, Restore-Matrix und Freshness-Checks sind umgesetzt.
- Posture-/Cert-/Drift-Checks: Skripte und Unraid User Scripts sind vorhanden und geplant.
- Loki/Alloy Logging: Stack, Grafana-Datasource, Dashboards und Logging-Resilienz-Doku sind vorhanden.
- Monitoring-Zielstack: `monitoring/` buendelt Prometheus, Loki, Promtail, Grafana, node-exporter, cAdvisor und InfluxDB 3 Core im Repo-Zielzustand.
- Docker-Log-Rotation: Unraid-native Rotation ist dokumentiert; keine separate `/etc/docker/daemon.json` setzen.
## Morgen / bewusst spaeter
- Monitoring live finalisieren:
- Secrets `monitoring_grafana_admin_password.txt`, `monitoring_grafana_influxdb_token.txt`, `influxdb3_admin_token.json` auf dem Host pruefen/anlegen
- `monitoring` in Komodo deployen
- alte Stacks `ops/loki` und `ops/grafana-influxdb` nach erfolgreichem Smoke-Test stoppen
- `https://monitoring.kaleschke.info`, Prometheus Targets, Loki-Logs und InfluxDB-Datasource pruefen
- Home Assistant -> InfluxDB finalisieren:
- HA-Token/Writer final pruefen
- erste Messwerte in InfluxDB verifizieren
- Grafana-HA-/Wetter-Dashboard aufbauen
- Grafana-HA-/Wetter-Dashboard in `monitoring-grafana` aufbauen
- Disk1-NTFS-Migration Phase 2:
- bleibt bewusst separates Migrationsfenster
- `posture-check` darf bis dahin die dokumentierte NTFS-Warnung melden
@@ -30,7 +35,7 @@ Diese Datei ersetzt die alte Sprint-Liste vom 2026-05-16. Die damaligen Backup-,
## Verbleibende bekannte Warnings
- `ddns-updater`, `glances`, `scrutiny`: nutzen noch `latest...@sha256`; spaeter durch konkrete Versionstags ersetzen, sofern upstream sinnvoll versioniert.
- `grafana` und `influxdb3-core`: laufen weiterhin als `user: "0"`; dokumentierte Uebergangsausnahme, UID/GID-Hardening spaeter separat testen.
- `ops/grafana-influxdb` und `ops/loki`: bleiben nur noch als Rollback-/Migrationsreferenz im Repo, nach Live-Migration nicht parallel betreiben.
- `scrutiny`: bleibt `privileged: true`; dokumentierte SMART-Ausnahme, spaeter erneut pruefen.
## Regel
+13 -2
View File
@@ -49,6 +49,10 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
| `ops/grafana-influxdb/provisioning/dashboards/*.json` | Grafana Dashboards fuer Container-Logs, Restart-Events und Error-Rate |
| `ops/loki/config/loki-config.yml` | Loki Filesystem/Retention-Konfiguration fuer internen Logspeicher |
| `ops/loki/config/config.alloy` | Alloy Docker-Log-Collector-Konfiguration |
| `monitoring/prometheus/prometheus.yml` | Prometheus Scrape-Konfiguration fuer dedizierten Monitoring-Stack |
| `monitoring/loki/loki-config.yml` | Loki Filesystem/Retention-Konfiguration fuer dedizierten Monitoring-Stack |
| `monitoring/promtail/promtail-config.yml` | Promtail Docker-Socket-Discovery fuer dedizierten Monitoring-Stack |
| `monitoring/grafana/provisioning/*` | Grafana Datasource-/Dashboard-Provisioning fuer Prometheus und Loki |
| `ops/borg-ui/scripts/pre-backup-dumps.sh` | Host-seitiges Dump-Skript fuer PostgreSQL, SQLite-Container-Dumps und Komodo Mongo |
| `services/posture-check/posture-check.sh` | Host-seitiger Posture-Check fuer Filesystem, Mover-Drift, NVMe-SMART, Fuellstand und ntfy-Alarmierung |
| `services/posture-check/docker-critical-events.sh` | Host-seitiger Docker-Event-Watcher fuer kritische ntfy-Alarme |
@@ -57,6 +61,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
| `ops/hermes-agent/hermes.env.example` | Beispiel fuer Hermes `.env`; echte Datei liegt auf Host-Appdata |
| `ops/hermes-agent/stack.env.example` | Beispiel fuer Hermes Stack-ENV; echte `stack.env` bleibt host-/komodoseitig und ist per `.gitignore` ausgeschlossen |
| `ops/grafana-influxdb/stack.env.example` | `INFLUXDB_BIND_IP` Default `127.0.0.1`; auf Unraid fuer Home Assistant auf LAN-IP setzen |
| `monitoring/stack.env.example` | `INFLUXDB_BIND_IP` Default `127.0.0.1`; im Zielzustand fuer Home Assistant auf LAN-IP setzen |
| `ops/komodo/stack.env.example` | Komodo Stack-ENV-Beispiel, Secret-Werte nicht enthalten |
## Stack-Inventar
@@ -102,8 +107,9 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
| code-server | `ops/code-server/docker-compose.yml` | `code-server` -> `lscr.io/linuxserver/code-server:4.116.0@sha256:...` | `code.kaleschke.info` | `frontend_net` | keine | Passwort-Datei, Workspace-Mounts |
| Filebrowser | `ops/filebrowser/docker-compose.yml` | `filebrowser` -> `filebrowser/filebrowser:v2.63.2@sha256:...` | `files.kaleschke.info` | `frontend_net` | keine | Documents/Photos/Projekte-Mounts, Admin-UI hinter Authelia |
| Glances | `ops/glances/docker-compose.yml` | `glances` -> `nicolargo/glances:latest-full@sha256:...` | `glances.kaleschke.info` | `frontend_net` | keine | Rootfs/Docker-Socket fuer Monitoring |
| Grafana/InfluxDB | `ops/grafana-influxdb/docker-compose.yml` | `grafana`, `influxdb3-core` | `grafana.kaleschke.info` | `frontend_net`, `grafana_influx_internal`, `grafana_influx_lan` | `influxdb3-core`: `${INFLUXDB_BIND_IP:-127.0.0.1}:8181:8181` | InfluxDB LAN-only fuer Home Assistant; Grafana datasource token; beide Container laufen aktuell als `user: "0"` |
| Loki/Alloy | `ops/loki/docker-compose.yml` | `loki`, `alloy` | keine | `backend_net` | keine | interner Logspeicher und Docker-Log-Collector; Alloy nutzt Docker socket read-only |
| Grafana/InfluxDB | `ops/grafana-influxdb/docker-compose.yml` | `grafana`, `influxdb3-core` | `grafana.kaleschke.info` | `frontend_net`, `grafana_influx_internal`, `grafana_influx_lan` | `influxdb3-core`: `${INFLUXDB_BIND_IP:-127.0.0.1}:8181:8181` | abgeloester Altstand; nach erfolgreicher Migration durch `monitoring/` ersetzen |
| Loki/Alloy | `ops/loki/docker-compose.yml` | `loki`, `alloy` | keine | `backend_net` | keine | abgeloester Altstand; nach erfolgreicher Migration durch `monitoring-loki`/`monitoring-promtail` ersetzen |
| Monitoring | `monitoring/docker-compose.yml` | `monitoring-prometheus`, `monitoring-loki`, `monitoring-promtail`, `monitoring-grafana`, `monitoring-node-exporter`, `monitoring-cadvisor`, `monitoring-influxdb3-core`, optional `monitoring-grafana-dashboard-importer` | `monitoring.kaleschke.info` | `frontend_net`, `monitoring_net`, `monitoring_influx_lan` | `monitoring-influxdb3-core`: `${INFLUXDB_BIND_IP:-127.0.0.1}:8181:8181` | zentraler Zielstack fuer Prometheus/Loki/Grafana/InfluxDB; Promtail nutzt Docker socket read-only; Dashboard-Importer nur via `bootstrap`-Profil |
| Hermes Agent | `ops/hermes-agent/docker-compose.yml` | `hermes-gateway`, `hermes-dashboard` -> local build from Dockerfile | `hermes.kaleschke.info` via `${HERMES_DASHBOARD_HOST}` | `hermes_net`, dashboard zusaetzlich `frontend_net` | `8642` nur expose intern | SSH runner, Home Assistant optional, LLM provider env; Dashboard hinter Authelia |
| Komodo | `ops/komodo/docker-compose.yml` | `komodo-core`, `komodo-mongo`, `komodo-periphery` | `komodo.kaleschke.info` | `frontend_net`, `komodo_net` | keine | Mongo, Docker socket, `/mnt/user/services` workspace mount, Gitea DNS override |
| Scrutiny | `ops/scrutiny/docker-compose.yml` | `scrutiny` -> `ghcr.io/starosdev/scrutiny:latest-omnibus@sha256:...` | `scrutiny.kaleschke.info` | `frontend_net` | keine | `privileged: true`, device mounts fuer SMART |
@@ -134,6 +140,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
| `komodo.kaleschke.info` | Komodo | Traefik, native Komodo-Auth; keine pauschale ForwardAuth |
| `mail.kaleschke.info` | Mail Archiver | Traefik + Authelia + App-Auth |
| `mealie.kaleschke.info` | Mealie | Traefik |
| `monitoring.kaleschke.info` | Monitoring Grafana | Traefik + Authelia |
| `ntfy.kaleschke.info` | ntfy | Traefik |
| `paperless.kaleschke.info` | Paperless-ngx | Traefik |
| `paperless-gpt.kaleschke.info` | Paperless-GPT | Traefik + Authelia |
@@ -156,6 +163,8 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
| `nextcloud_internal` | Compose-intern | Nextcloud, Nextcloud Postgres, Nextcloud Redis |
| `grafana_influx_internal` | Compose-intern, `internal: true` | Grafana und InfluxDB |
| `grafana_influx_lan` | Compose-intern bridge | InfluxDB Host-Port-Publishing fuer LAN Writer |
| `monitoring_net` | Compose-/Stack-Netz bridge | Prometheus, Loki, Promtail, Monitoring-Grafana, node-exporter, cAdvisor; Traefik fuer Metrics-Scrape |
| `monitoring_influx_lan` | Compose-intern bridge | InfluxDB Host-Port-Publishing fuer LAN Writer im zentralen Monitoring-Stack |
| `komodo_net` | Compose-intern, `internal: true` | Komodo Core, Mongo, Periphery |
| `hermes_net` | Compose-intern bridge | Hermes Gateway/Dashboard |
| `host` | Host-Netz | Tailscale; Plex historisch ausserhalb Repo |
@@ -189,6 +198,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
| Uptime Kuma | `/mnt/user/appdata/uptime-kuma` |
| Grafana/InfluxDB | `/mnt/user/appdata/grafana`, Grafana provisioning, `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` |
| Loki/Alloy | `/mnt/user/appdata/loki/config`, `/mnt/user/appdata/loki/data`, `/mnt/user/appdata/alloy/config`, `/mnt/user/appdata/alloy/data` |
| Monitoring | named volumes `prometheus_data`, `loki_data`, `promtail_positions`, `grafana_data`, `influxdb3_data`, `influxdb3_plugins`; Provisioning im Repo unter `monitoring/grafana/provisioning` |
| Hermes Agent | `/mnt/user/appdata/hermes-agent/data`, `/mnt/user/appdata/hermes-agent/ssh`, SSH private key path |
| Komodo | `komodo_keys`, `/mnt/user/appdata/komodo/core`, `/mnt/user/appdata/komodo/mongo`, `/mnt/user/appdata/komodo/periphery`, `/mnt/user/services` |
@@ -212,6 +222,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
| Hermes Agent | provider keys, API server key, messaging tokens, Home Assistant token in Host `.env`; SSH private key als Host-Secret |
| Grafana/InfluxDB | Grafana Admin Password, InfluxDB Admin Token JSON, Grafana Datasource Token |
| Loki/Alloy | keine zusaetzlichen Secrets; Zugriff nur intern ueber `backend_net` |
| Monitoring | `monitoring_grafana_admin_password.txt`, `monitoring_grafana_influxdb_token.txt`, `influxdb3_admin_token.json` fuer zentrale Grafana-/InfluxDB-Funktionen |
## Skripte
+5 -3
View File
@@ -64,9 +64,10 @@ Sie ist die fachliche Ergaenzung zu `docs/DISASTER_RECOVERY.md`.
| Scrutiny | Teilweise rebuildbar | `/mnt/user/appdata/scrutiny` falls gewuenscht | InfluxDB bewusst nicht Teil des Critical-Scope | keine | Traefik, Authelia | UI startet, Laufwerke sichtbar |
| Speedtest Tracker | Share + Dump | `/mnt/user/appdata/speedtest-tracker/config` | `speedtest-tracker.sqlite.dump` | `APP_KEY`, `ADMIN_PASSWORD` | Traefik, Authelia | UI startet |
| BentoPDF | Rebuildbar | keine kritische Persistenz; alte Stirling-PDF-Daten unter `/mnt/user/appdata/stirling-pdf` bis zur Abnahme behalten | keine | keine separaten Secret-Dateien dokumentiert | Traefik, Authelia | UI startet, PDF-Tools verfuegbar, Office-Konvertierung ueber HTTPS funktioniert |
| Grafana | Share + Dump | `/mnt/user/appdata/grafana`, inklusive `provisioning/datasources/influxdb.yml` | `grafana.sqlite` | `grafana_admin_password.txt`, `grafana_influxdb_token.txt` | Traefik, Authelia, InfluxDB 3 Core | UI startet, InfluxDB-Datenquelle testet erfolgreich |
| InfluxDB 3 Core | Share | `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` | dateibasierter Object Store | `influxdb3_admin_token.json` | internes `grafana_influx_internal` Netz | `homelab`-Datenbank vorhanden, Grafana kann SQL-Abfrage ausfuehren |
| Loki / Alloy | Rebuild + begrenzte Logdaten | `/mnt/user/appdata/loki/config`, `/mnt/user/appdata/loki/data`, `/mnt/user/appdata/alloy/config` | keine primaere DB; Loki-Dateispeicher mit 30 Tagen Retention | keine zusaetzlichen Secrets | `backend_net`, Docker socket read-only, Grafana | Loki `/ready` ist gruen, Grafana-Datasource `Loki` kann Logs abfragen |
| Grafana | abgeloester Altstand | `/mnt/user/appdata/grafana`, inklusive `provisioning/datasources/influxdb.yml` | `grafana.sqlite` | `grafana_admin_password.txt`, `grafana_influxdb_token.txt` | Traefik, Authelia, InfluxDB 3 Core | Nur als Rollback-/Migrationsreferenz behalten, wenn `monitoring/` produktiv ist |
| InfluxDB 3 Core | abgeloester Altstand | `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` | dateibasierter Object Store | `influxdb3_admin_token.json` | internes `grafana_influx_internal` Netz | Nach Migration nicht blind loeschen; Datenuebernahme zu `monitoring-influxdb3-core` separat pruefen |
| Loki / Alloy | abgeloester Altstand | `/mnt/user/appdata/loki/config`, `/mnt/user/appdata/loki/data`, `/mnt/user/appdata/alloy/config` | keine primaere DB; Loki-Dateispeicher mit 30 Tagen Retention | keine zusaetzlichen Secrets | `backend_net`, Docker socket read-only, Grafana | Durch `monitoring-loki`/`monitoring-promtail` ersetzen |
| Monitoring Stack | Rebuild + named volumes | `prometheus_data`, `loki_data`, `promtail_positions`, `grafana_data`, `influxdb3_data`, `influxdb3_plugins`; Provisioning aus `monitoring/grafana/provisioning` | Prometheus-TSDB, Loki-Dateispeicher und InfluxDB-Dateistore; Diagnose-/Langzeitdaten, keine Tier-1-Restore-Quelle | `monitoring_grafana_admin_password.txt`, `monitoring_grafana_influxdb_token.txt`, `influxdb3_admin_token.json` | `monitoring_net`, `monitoring_influx_lan`, `frontend_net`, Traefik, Authelia, Docker socket read-only fuer Promtail, Host-Mounts fuer node-exporter/cAdvisor | `https://monitoring.kaleschke.info` leitet zu Authelia; Prometheus Targets sind up; Grafana-Datasources `Prometheus`, `Loki` und `InfluxDB 3 Core` funktionieren |
| Hermes Agent | VM-seitig offen | `/mnt/user/appdata/hermes-agent/data`, `/mnt/user/appdata/hermes-agent/ssh` | keine eigene DB | Host-`.env` fuer Provider-/API-/Home-Assistant-Tokens, `hermes_runner_id_ed25519`, `HERMES_DASHBOARD_HOST` | separate Hermes-VM/Runner, Traefik, Authelia, `hermes_net` | NAS-Stack nicht starten, solange Runner-VM und echte `.env` fehlen |
| ddns-updater | Rebuildbar | geringe Persistenzrelevanz | keine | Provider-Zugang ueber Stack ENV | Internetzugang | Update-Job laeuft |
@@ -90,6 +91,7 @@ Aktuell relevante Dump-Artefakte unter `/mnt/user/backups/borg/dumps/latest`:
- `filebrowser.bolt.dump`
- `borg-ui.sqlite`
- `grafana.sqlite`
- Monitoring-Stack: keine verpflichtenden Dump-Artefakte; Prometheus/Loki/Grafana named volumes sind Diagnose-/Dashboard-Zustand, keine primaere Restore-Quelle.
- `komodo-mongo.archive.gz` (noch gesondert verifizieren)
Die Dump-Erzeugung ist host-seitig ueber `ops/borg-ui/scripts/pre-backup-dumps.sh` vorgesehen.
+11
View File
@@ -94,6 +94,17 @@ Nach einem Deploy:
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:
1. `monitoring` in Komodo stoppen oder auf den letzten funktionierenden Commit zurueckgehen
2. bei Bedarf die abgeloesten Altstaende `ops/loki` und/oder `ops/grafana-influxdb` wieder starten
3. named volumes `prometheus_data`, `loki_data`, `promtail_positions`, `grafana_data`, `influxdb3_data` und `influxdb3_plugins` 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
---
## Daten-Rollback
+4
View File
@@ -49,6 +49,8 @@ Dieses Dokument listet sensible Daten, deren Ablageorte und die vorgesehene Einb
| Grafana | Admin Password | `/mnt/user/appdata/secrets/grafana_admin_password.txt` -> `GF_SECURITY_ADMIN_PASSWORD__FILE` | aktiv |
| InfluxDB 3 Core | Admin Token JSON | `/mnt/user/appdata/secrets/influxdb3_admin_token.json` -> Docker Secret `/run/secrets/influxdb3_admin_token` | aktiv |
| Grafana -> InfluxDB | Datasource Token | `/mnt/user/appdata/secrets/grafana_influxdb_token.txt` -> Docker Secret `/run/secrets/grafana_influxdb_token` | aktiv |
| Monitoring Grafana | Admin Password | `/mnt/user/appdata/secrets/monitoring_grafana_admin_password.txt` -> Docker Secret `/run/secrets/monitoring_grafana_admin_password` -> `GF_SECURITY_ADMIN_PASSWORD__FILE` | aktiv |
| Monitoring Grafana -> InfluxDB | Datasource Token | `/mnt/user/appdata/secrets/monitoring_grafana_influxdb_token.txt` -> Docker Secret `/run/secrets/monitoring_grafana_influxdb_token` | aktiv |
| Home Assistant -> InfluxDB | HA InfluxDB Token | `/homeassistant/secrets.yaml` -> `influxdb3_homeassistant_token` | geplant |
---
@@ -74,6 +76,8 @@ Dieses Dokument listet sensible Daten, deren Ablageorte und die vorgesehene Einb
|-- immich_postgres_password.txt
|-- komodo_mongo_password.txt
|-- mealie_postgres_password.txt
|-- monitoring_grafana_admin_password.txt
|-- monitoring_grafana_influxdb_token.txt
|-- nextcloud_admin_password.txt
|-- nextcloud_admin_user.txt
|-- nextcloud_postgres_password.txt
+11 -4
View File
@@ -65,10 +65,17 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und
| `speedtest-tracker` | Speedtest-Monitoring | `ops/speedtest/docker-compose.yml` | `https://speedtest.kaleschke.info` | Traefik + Authelia | `/mnt/user/appdata/speedtest-tracker/config` | Tier 3, `speedtest-tracker.sqlite.dump` | ja + Authelia | `APP_KEY`, `ADMIN_PASSWORD` Stack ENV |
| `filebrowser` | Datei-Browser fuer Documents/Photos/Projekte | `ops/filebrowser/docker-compose.yml` | `https://files.kaleschke.info` | Traefik + Authelia | `/mnt/user/appdata/filebrowser/*`, `/mnt/user/documents`, `/mnt/user/photos`, `/mnt/user/projekte` | Tier 3, `filebrowser.bolt.dump` + Share | ja + Authelia | Breiter Appdata-Mount entfernt; Secrets und Traefik-Dynamic-Config sind nicht mehr ueber Filebrowser gemountet |
| `code-server` | Web-Editor / Operations Workspace | `ops/code-server/docker-compose.yml` | `https://code.kaleschke.info` | Traefik + Authelia | `/mnt/user/appdata/code-server`, `/mnt/user/services/dev` | Tier 3 | ja + Authelia | Passwort ueber LSIO `FILE__PASSWORD`; Workspaces beachten |
| `grafana` | Metrik-Dashboard | `ops/grafana-influxdb/docker-compose.yml` | `https://grafana.kaleschke.info` | Traefik + Authelia, InfluxDB 3 Core | `/mnt/user/appdata/grafana`, Grafana provisioning | Tier 3, `grafana.sqlite` | ja + Authelia | Datasource wird provisioniert, Token ueber Secret; laeuft aktuell als `user: "0"` wegen Host-Appdata-Permissions |
| `influxdb3-core` | Zeitreihen-/Metrikdaten fuer Grafana und Home Assistant | `ops/grafana-influxdb/docker-compose.yml` | LAN `8181` je `INFLUXDB_BIND_IP`, keine Public URL | Grafana, Home Assistant Writer | `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` | Tier 3 | nein | LAN-only Host-Port-Ausnahme; `401 Unauthorized` beim Curl ohne Token ist erwarteter Reachability-Test; laeuft aktuell als `user: "0"` wegen Host-Appdata-Permissions |
| `loki` | zentraler Container-Logspeicher | `ops/loki/docker-compose.yml`, `ops/loki/config/loki-config.yml` | intern `http://loki:3100`, keine Public URL | `backend_net`, Grafana | `/mnt/user/appdata/loki/config`, `/mnt/user/appdata/loki/data` | Tier 3, transiente Logs mit 30 Tagen Retention | nein | Nur intern erreichbar; Grafana nutzt Loki als Datasource; Logs sind Diagnosematerial, keine primaere Restore-Quelle |
| `alloy` | Docker-Log-Collector fuer Loki | `ops/loki/docker-compose.yml`, `ops/loki/config/config.alloy` | intern | Docker socket read-only, Loki, `backend_net` | `/mnt/user/appdata/alloy/config`, `/mnt/user/appdata/alloy/data` | rebuildbar | nein | Dokumentierte Host-Observability-Ausnahme: `/var/run/docker.sock:/var/run/docker.sock:ro`; keine Appdaten, nur Log-Discovery |
| `grafana` | abgeloester Altstand fuer Grafana/InfluxDB | `ops/grafana-influxdb/docker-compose.yml` | `https://grafana.kaleschke.info` | Traefik + Authelia, InfluxDB 3 Core | `/mnt/user/appdata/grafana`, Grafana provisioning | Tier 3, `grafana.sqlite` | ja + Authelia | Nicht parallel zum neuen `monitoring/`-Zielstack betreiben; bleibt vorerst als Rollback-/Migrationsreferenz |
| `influxdb3-core` | abgeloester Altstand fuer Home-Assistant-Langzeitdaten | `ops/grafana-influxdb/docker-compose.yml` | LAN `8181` je `INFLUXDB_BIND_IP`, keine Public URL | Grafana, Home Assistant Writer | `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` | Tier 3 | nein | Nach erfolgreicher Migration durch `monitoring-influxdb3-core` ersetzen; alten Datenpfad nicht blind loeschen |
| `monitoring-grafana` | zentrale Observability-UI fuer Metriken, Logs und InfluxDB | `monitoring/docker-compose.yml` | `https://monitoring.kaleschke.info` | Traefik + Authelia, Prometheus, Loki, InfluxDB 3 Core | named volume `grafana_data`, Provisioning unter `monitoring/grafana/provisioning` | Tier 3, named volume | ja + Authelia | Admin-Passwort ueber `monitoring_grafana_admin_password.txt`; Dashboard-Importer ist optionales `bootstrap`-Profil |
| `monitoring-prometheus` | Metrik-Speicher fuer Homelab-Monitoring | `monitoring/docker-compose.yml`, `monitoring/prometheus/prometheus.yml` | intern `http://prometheus:9090` | `monitoring_net`, node-exporter, cAdvisor, Traefik-Metrics | named volume `prometheus_data` | Tier 3, transiente Metriken mit 30 Tagen Retention | nein | Scrapes: Prometheus, node-exporter, cAdvisor, Traefik `:8082` |
| `monitoring-loki` | Logspeicher fuer Monitoring-Stack | `monitoring/docker-compose.yml`, `monitoring/loki/loki-config.yml` | intern `http://loki:3100` | `monitoring_net`, Promtail, Grafana | named volume `loki_data` | Tier 3, transiente Logs mit 30 Tagen Retention | nein | Von bestehendem `ops/loki` getrennt; Doppelbetrieb bewusst pruefen |
| `monitoring-promtail` | Docker-Log-Collector fuer Monitoring-Loki | `monitoring/docker-compose.yml`, `monitoring/promtail/promtail-config.yml` | intern | Docker socket read-only, Docker json-file Logs, Loki | named volume `promtail_positions` | rebuildbar | nein | Dokumentierte Host-Observability-Ausnahme: `/var/run/docker.sock:/var/run/docker.sock:ro` und `/var/lib/docker/containers:ro`; keine Appdaten, nur Log-Discovery |
| `monitoring-node-exporter` | Host-Metriken fuer Prometheus | `monitoring/docker-compose.yml` | intern `:9100` | Host `/proc`, `/sys`, `/` read-only, Prometheus | kein kritischer Zustand | rebuildbar | nein | Host-Observability-Ausnahme mit read-only Rootfs/Proc/Sys-Mounts |
| `monitoring-cadvisor` | Container-Metriken fuer Prometheus | `monitoring/docker-compose.yml` | intern `:8080` | Docker/Host read-only Mounts, Prometheus | kein kritischer Zustand | rebuildbar | nein | Host-Observability-Ausnahme fuer Container-Metriken; keine direkten Ports |
| `monitoring-influxdb3-core` | InfluxDB 3 Core fuer Home-Assistant-/Ecowitt-Langzeitdaten | `monitoring/docker-compose.yml` | LAN `8181` je `INFLUXDB_BIND_IP`, keine Public URL | Monitoring-Grafana, Home Assistant Writer | named volumes `influxdb3_data`, `influxdb3_plugins` | Tier 3 | nein | LAN-only Host-Port-Ausnahme; `401 Unauthorized` beim Curl ohne Token ist erwarteter Reachability-Test |
| `loki` | abgeloester Altstand fuer Container-Logs | `ops/loki/docker-compose.yml`, `ops/loki/config/loki-config.yml` | intern `http://loki:3100`, keine Public URL | `backend_net`, Grafana | `/mnt/user/appdata/loki/config`, `/mnt/user/appdata/loki/data` | Tier 3, transiente Logs mit 30 Tagen Retention | nein | Durch `monitoring-loki` ersetzen; nicht parallel betreiben, ausser bewusst zur Migration |
| `alloy` | abgeloester Altstand fuer Docker-Log-Collection | `ops/loki/docker-compose.yml`, `ops/loki/config/config.alloy` | intern | Docker socket read-only, Loki, `backend_net` | `/mnt/user/appdata/alloy/config`, `/mnt/user/appdata/alloy/data` | rebuildbar | nein | Durch `monitoring-promtail` ersetzen; Socket-Ausnahme bleibt nur fuer aktive Collector relevant |
| `hermes-gateway` | Hermes Agent Gateway/API intern | `ops/hermes-agent/docker-compose.yml` | intern `8642` auf `hermes_net` | SSH Runner (VM 192.168.178.143), LLM Provider, optional Home Assistant | `/mnt/user/appdata/hermes-agent/data`, SSH key path | Tier 3, Borg/Share | nein | NAS-Stack bleibt deaktiviert, solange die separate Hermes-VM/Runner-Seite nicht wiederhergestellt ist; kein Docker-Socket |
| `hermes-dashboard` | Hermes Dashboard | `ops/hermes-agent/docker-compose.yml` | `https://hermes.kaleschke.info` via `${HERMES_DASHBOARD_HOST}` | `hermes-gateway`, Traefik + Authelia | shared read-only data mount | Tier 3, Borg/Share | ja + Authelia | Compose-Profil `dashboard`; aktuell VM-seitig offen, nicht Teil des NAS-Finalstarts |
+1 -1
View File
@@ -292,7 +292,7 @@ Diese Regeln sind nicht optional. Verstoß ist Incident, kein Feature-Request.
12. **Kein Backup-Lauf ohne vorgeschalteten Posture-Check (siehe §11).** Backup auf kompromittiertem Filesystem überschreibt unter Umständen den letzten guten Stand und kontaminiert die Backup-Historie.
**Dokumentierte Host-Observability-Ausnahmen (Operator-Entscheidung 2026-05-16):**
`glances`, `scrutiny` und `alloy` duerfen gezielt Host-/Device-Bind-Mounts ausserhalb `/mnt/user/...` nutzen, weil ihre Kernfunktion sonst nicht erfuellbar ist. Erlaubt sind nur die in `docs/SERVICE_CATALOG.md` pro Dienst genannten Binds. Diese Ausnahmen sind keine Datenpersistenz-Pfade und duerfen nicht fuer Appdaten, Backups oder normale Service-Konfiguration erweitert werden. Neue oder geaenderte Host-Binds brauchen eine explizite Doku-Aenderung im selben Commit.
`glances`, `scrutiny`, `monitoring-promtail`, `monitoring-node-exporter` und `monitoring-cadvisor` duerfen gezielt Host-/Device-Bind-Mounts ausserhalb `/mnt/user/...` nutzen, weil ihre Kernfunktion sonst nicht erfuellbar ist. Erlaubt sind nur die in `docs/SERVICE_CATALOG.md` pro Dienst genannten Binds. Diese Ausnahmen sind keine Datenpersistenz-Pfade und duerfen nicht fuer Appdaten, Backups oder normale Service-Konfiguration erweitert werden. Neue oder geaenderte Host-Binds brauchen eine explizite Doku-Aenderung im selben Commit. `alloy` ist nur noch als abgeloester Altstand relevant.
## 13. Soft Rules — Konventionen
+58
View File
@@ -0,0 +1,58 @@
# Monitoring Stack
Zielzustand: ein zentraler Observability-Stack fuer KalliLab CORE.
## Enthaltene Dienste
- `monitoring-grafana`: zentrale UI unter `https://monitoring.kaleschke.info`
- `monitoring-prometheus`: Metriken mit 30 Tagen Retention
- `monitoring-loki`: Container-Logs mit 30 Tagen Retention
- `monitoring-promtail`: Docker-Log-Discovery ueber read-only Docker-Socket
- `monitoring-node-exporter`: Host-Metriken
- `monitoring-cadvisor`: Container-Metriken
- `monitoring-influxdb3-core`: InfluxDB 3 Core fuer Home-Assistant-/Ecowitt-Langzeitdaten
Die alten Pfade `ops/loki` und `ops/grafana-influxdb` sind damit abgeloeste Altstaende. Sie bleiben vorerst im Repo als Rollback- und Migrationsreferenz, sollen aber nach erfolgreichem Live-Deploy nicht parallel betrieben werden.
## Secrets
Vor dem Deploy muessen diese Host-Dateien existieren:
```text
/mnt/user/appdata/secrets/monitoring_grafana_admin_password.txt
/mnt/user/appdata/secrets/monitoring_grafana_influxdb_token.txt
/mnt/user/appdata/secrets/influxdb3_admin_token.json
```
Alle Dateien mit Rechten `600` anlegen. Werte niemals ins Git schreiben.
## Stack Environment
Default ist sicher lokal:
```env
INFLUXDB_BIND_IP=127.0.0.1
```
Wenn Home Assistant aus der VM schreiben soll, in Komodo fuer den `monitoring`-Stack setzen:
```env
INFLUXDB_BIND_IP=192.168.178.58
```
## Migration
1. Secrets anlegen.
2. Alten `ops/loki`-Stack stoppen, wenn `monitoring-loki` und `monitoring-promtail` live gehen.
3. Alten `ops/grafana-influxdb`-Stack stoppen, wenn `monitoring-influxdb3-core` und `monitoring-grafana` live getestet sind.
4. `monitoring` via Komodo deployen.
5. Optionales Dashboard-Bootstrap-Profil einmalig ausfuehren.
6. Home Assistant Writer gegen `http://192.168.178.58:8181/` pruefen; `401 Unauthorized` ohne Token ist erwartbar.
## Smoke-Tests
- `https://monitoring.kaleschke.info` leitet zu Authelia.
- Grafana-Datasources `Prometheus`, `Loki` und `InfluxDB 3 Core` testen erfolgreich.
- Prometheus Targets: `prometheus`, `node-exporter`, `cadvisor`, `traefik`.
- Loki zeigt Container-Logs mit Labels `container`, `compose_project`, `compose_service`.
- InfluxDB 3 Core enthaelt die Datenbank `homelab`.
+57 -13
View File
@@ -62,15 +62,24 @@ services:
environment:
GF_SERVER_ROOT_URL: https://monitoring.kaleschke.info/
GF_SECURITY_ADMIN_USER: admin
GF_SECURITY_ADMIN_PASSWORD: ${GF_SECURITY_ADMIN_PASSWORD}
GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/monitoring_grafana_admin_password
GF_USERS_ALLOW_SIGN_UP: "false"
GF_AUTH_ANONYMOUS_ENABLED: "false"
entrypoint:
- /bin/sh
- -c
- |
export GRAFANA_INFLUXDB_TOKEN="$$(cat /run/secrets/monitoring_grafana_influxdb_token)"
exec /run.sh
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning:ro
networks:
- monitoring_net
- frontend_net
secrets:
- monitoring_grafana_admin_password
- monitoring_grafana_influxdb_token
expose:
- "3000"
security_opt:
@@ -78,6 +87,7 @@ services:
depends_on:
- prometheus
- loki
- influxdb3-core
labels:
- traefik.enable=true
- traefik.docker.network=frontend_net
@@ -85,19 +95,15 @@ services:
- traefik.http.routers.monitoring-grafana.entrypoints=websecure
- traefik.http.routers.monitoring-grafana.tls=true
- traefik.http.routers.monitoring-grafana.tls.certresolver=le
- traefik.http.routers.monitoring-grafana.middlewares=authelia@docker,secure-headers@file
- traefik.http.routers.monitoring-grafana.middlewares=authelia@file,secure-headers@file
- traefik.http.services.monitoring-grafana.loadbalancer.server.port=3000
# Docker-provider Authelia middleware requested for this stack.
- traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/authz/forward-auth
- traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true
- traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email
grafana-dashboard-importer:
image: python:3.13-alpine
container_name: monitoring-grafana-dashboard-importer
restart: unless-stopped
environment:
GF_SECURITY_ADMIN_PASSWORD: ${GF_SECURITY_ADMIN_PASSWORD}
restart: "no"
profiles:
- bootstrap
dns:
- 1.1.1.1
- 8.8.8.8
@@ -108,6 +114,8 @@ services:
- no-new-privileges:true
depends_on:
- grafana
secrets:
- monitoring_grafana_admin_password
command:
- /bin/sh
- -c
@@ -115,13 +123,13 @@ services:
python - <<'PY'
import base64
import json
import os
import time
import urllib.error
import urllib.request
grafana_url = "http://grafana:3000"
password = os.environ["GF_SECURITY_ADMIN_PASSWORD"]
with open("/run/secrets/monitoring_grafana_admin_password", encoding="utf-8") as secret:
password = secret.read().strip()
auth = base64.b64encode(f"admin:{password}".encode()).decode()
headers = {
"Authorization": f"Basic {auth}",
@@ -202,8 +210,7 @@ services:
}, dashboard_id)
print(f"Imported Grafana dashboard {dashboard_id}")
PY
echo "Dashboard import complete; keeping sidecar alive for Komodo status."
sleep infinity
echo "Dashboard import complete."
node-exporter:
image: prom/node-exporter:v1.9.1
@@ -246,10 +253,37 @@ services:
security_opt:
- no-new-privileges:true
influxdb3-core:
image: influxdb:3.9.1-core@sha256:1d58c8b9ac90153ae3a020ede2810c8284933dda50ac71e7573389ab6f012128
container_name: monitoring-influxdb3-core
restart: unless-stopped
ports:
- "${INFLUXDB_BIND_IP:-127.0.0.1}:8181:8181"
command:
- influxdb3
- serve
- --node-id=kallilabcore
- --object-store=file
- --data-dir=/var/lib/influxdb3/data
- --plugin-dir=/var/lib/influxdb3/plugins
- --admin-token-file=/run/secrets/influxdb3_admin_token
volumes:
- influxdb3_data:/var/lib/influxdb3/data
- influxdb3_plugins:/var/lib/influxdb3/plugins
secrets:
- influxdb3_admin_token
networks:
- monitoring_net
- monitoring_influx_lan
security_opt:
- no-new-privileges:true
networks:
monitoring_net:
name: monitoring_net
driver: bridge
monitoring_influx_lan:
driver: bridge
frontend_net:
external: true
@@ -258,3 +292,13 @@ volumes:
loki_data:
promtail_positions:
grafana_data:
influxdb3_data:
influxdb3_plugins:
secrets:
monitoring_grafana_admin_password:
file: /mnt/user/appdata/secrets/monitoring_grafana_admin_password.txt
monitoring_grafana_influxdb_token:
file: /mnt/user/appdata/secrets/monitoring_grafana_influxdb_token.txt
influxdb3_admin_token:
file: /mnt/user/appdata/secrets/influxdb3_admin_token.json
@@ -17,3 +17,17 @@ datasources:
editable: false
jsonData:
maxLines: 1000
- name: InfluxDB 3 Core
uid: monitoring-influxdb3-core
type: influxdb
access: proxy
url: http://influxdb3-core:8181
editable: false
jsonData:
version: SQL
dbName: homelab
httpMode: POST
insecureGrpc: true
secureJsonData:
token: $GRAFANA_INFLUXDB_TOKEN
+3
View File
@@ -0,0 +1,3 @@
# Safe default: local host only.
# Set this to the Unraid LAN IP, for example 192.168.178.58, when a VM such as Home Assistant must write to InfluxDB.
INFLUXDB_BIND_IP=127.0.0.1
+4
View File
@@ -1,7 +1,11 @@
# Grafana + InfluxDB 3 Core
Status: abgeloester Altstand. Der zentrale Zielzustand ist `monitoring/` mit `monitoring-grafana`, `monitoring-influxdb3-core`, Prometheus, Loki und Promtail.
Monitoring-Stack fuer Grafana + InfluxDB 3 Core. InfluxDB bleibt ohne Public Route; interne Writer wie Home Assistant koennen ueber einen gezielt gebundenen LAN-Port schreiben.
Nach erfolgreichem `monitoring/`-Deploy diesen Stack nicht parallel weiterbetreiben. Er bleibt vorerst als Rollback- und Migrationsreferenz im Repo.
## Quellen / Entscheidungen
- Grafana nutzt das offizielle OSS-Image `grafana/grafana:12.4.3`.
+6
View File
@@ -1,5 +1,7 @@
# Loki / Alloy
Status: abgeloester Altstand. Der zentrale Zielzustand ist `monitoring/` mit `monitoring-loki` und `monitoring-promtail`.
Internal logging stack for KalliLab CORE.
## Services
@@ -7,6 +9,10 @@ Internal logging stack for KalliLab CORE.
- `loki`: internal log store on `backend_net`, no Traefik route, `auth_enabled: false` because access is limited to internal Docker networking.
- `alloy`: Docker log collector. It mounts `/var/run/docker.sock:ro` as a documented observability exception and forwards Docker container logs to Loki.
## Migration note
Do not run this stack in parallel with `monitoring/` unless you are deliberately comparing collectors during migration. After `monitoring-loki` and `monitoring-promtail` are live and Grafana can query logs, stop this Komodo stack and keep the files only as rollback reference.
## Host sync
Before first deploy, sync the checked-in config files to appdata:
+3
View File
@@ -24,6 +24,9 @@
"influxdb3-core": [
"${INFLUXDB_BIND_IP:-127.0.0.1}:8181:8181"
],
"monitoring-influxdb3-core": [
"${INFLUXDB_BIND_IP:-127.0.0.1}:8181:8181"
],
"traefik": [
"80:80",
"443:443"