From b7dfdad6215e3aa4212e1704d487304fcf7eeb34 Mon Sep 17 00:00:00 2001 From: Micha Date: Sun, 17 May 2026 10:41:29 +0200 Subject: [PATCH] Consolidate monitoring target stack --- HOMELAB_ARCHITECTURE_MASTER_V2.md | 49 +++++++------ README.md | 2 +- docs/AI_CONTEXT.md | 8 ++- docs/DISASTER_RECOVERY.md | 2 +- docs/GITOPS_DRIFT_RUNBOOK.md | 14 ++-- docs/HOME_ASSISTANT_INFLUXDB_ECOWITT.md | 6 +- docs/MIGRATION_LOG.md | 7 ++ docs/NEXT_SPRINT_TODO_2026-05-16.md | 13 ++-- docs/REPO_MAP.md | 15 +++- docs/RESTORE_MATRIX.md | 8 ++- docs/ROLLBACK.md | 11 +++ docs/SECRETS_MAP.md | 4 ++ docs/SERVICE_CATALOG.md | 15 ++-- docs/STORAGE_LAYOUT.draft.md | 2 +- monitoring/README.md | 58 +++++++++++++++ monitoring/docker-compose.yml | 70 +++++++++++++++---- .../provisioning/datasources/datasources.yml | 14 ++++ monitoring/stack.env.example | 3 + ops/grafana-influxdb/README.md | 4 ++ ops/loki/README.md | 6 ++ ops/policy-checks/exceptions.json | 3 + 21 files changed, 250 insertions(+), 64 deletions(-) create mode 100644 monitoring/README.md create mode 100644 monitoring/stack.env.example diff --git a/HOMELAB_ARCHITECTURE_MASTER_V2.md b/HOMELAB_ARCHITECTURE_MASTER_V2.md index 358bfcf..7706bd0 100644 --- a/HOMELAB_ARCHITECTURE_MASTER_V2.md +++ b/HOMELAB_ARCHITECTURE_MASTER_V2.md @@ -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) diff --git a/README.md b/README.md index c64e781..e64cc38 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/docs/AI_CONTEXT.md b/docs/AI_CONTEXT.md index bcf00ba..6b26ebf 100644 --- a/docs/AI_CONTEXT.md +++ b/docs/AI_CONTEXT.md @@ -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 diff --git a/docs/DISASTER_RECOVERY.md b/docs/DISASTER_RECOVERY.md index f118e3a..72925ce 100644 --- a/docs/DISASTER_RECOVERY.md +++ b/docs/DISASTER_RECOVERY.md @@ -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/` diff --git a/docs/GITOPS_DRIFT_RUNBOOK.md b/docs/GITOPS_DRIFT_RUNBOOK.md index d598527..3020124 100644 --- a/docs/GITOPS_DRIFT_RUNBOOK.md +++ b/docs/GITOPS_DRIFT_RUNBOOK.md @@ -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 diff --git a/docs/HOME_ASSISTANT_INFLUXDB_ECOWITT.md b/docs/HOME_ASSISTANT_INFLUXDB_ECOWITT.md index a43deaf..e3dbf6b 100644 --- a/docs/HOME_ASSISTANT_INFLUXDB_ECOWITT.md +++ b/docs/HOME_ASSISTANT_INFLUXDB_ECOWITT.md @@ -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 diff --git a/docs/MIGRATION_LOG.md b/docs/MIGRATION_LOG.md index 2ce8bcd..9d9f512 100644 --- a/docs/MIGRATION_LOG.md +++ b/docs/MIGRATION_LOG.md @@ -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. diff --git a/docs/NEXT_SPRINT_TODO_2026-05-16.md b/docs/NEXT_SPRINT_TODO_2026-05-16.md index 0f083d3..9ab007e 100644 --- a/docs/NEXT_SPRINT_TODO_2026-05-16.md +++ b/docs/NEXT_SPRINT_TODO_2026-05-16.md @@ -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 diff --git a/docs/REPO_MAP.md b/docs/REPO_MAP.md index 9d7af6c..b65a8d4 100644 --- a/docs/REPO_MAP.md +++ b/docs/REPO_MAP.md @@ -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 diff --git a/docs/RESTORE_MATRIX.md b/docs/RESTORE_MATRIX.md index c56fc3b..e27d07f 100644 --- a/docs/RESTORE_MATRIX.md +++ b/docs/RESTORE_MATRIX.md @@ -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. diff --git a/docs/ROLLBACK.md b/docs/ROLLBACK.md index ba417d0..062ef76 100644 --- a/docs/ROLLBACK.md +++ b/docs/ROLLBACK.md @@ -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 diff --git a/docs/SECRETS_MAP.md b/docs/SECRETS_MAP.md index 9d92f94..93f3594 100644 --- a/docs/SECRETS_MAP.md +++ b/docs/SECRETS_MAP.md @@ -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 diff --git a/docs/SERVICE_CATALOG.md b/docs/SERVICE_CATALOG.md index f30ef01..77a39f5 100644 --- a/docs/SERVICE_CATALOG.md +++ b/docs/SERVICE_CATALOG.md @@ -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 | diff --git a/docs/STORAGE_LAYOUT.draft.md b/docs/STORAGE_LAYOUT.draft.md index 765fc41..2860d8d 100644 --- a/docs/STORAGE_LAYOUT.draft.md +++ b/docs/STORAGE_LAYOUT.draft.md @@ -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 diff --git a/monitoring/README.md b/monitoring/README.md new file mode 100644 index 0000000..a819b5d --- /dev/null +++ b/monitoring/README.md @@ -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`. diff --git a/monitoring/docker-compose.yml b/monitoring/docker-compose.yml index c809cf1..cf92eb0 100644 --- a/monitoring/docker-compose.yml +++ b/monitoring/docker-compose.yml @@ -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 diff --git a/monitoring/grafana/provisioning/datasources/datasources.yml b/monitoring/grafana/provisioning/datasources/datasources.yml index 61cfa51..e582b68 100644 --- a/monitoring/grafana/provisioning/datasources/datasources.yml +++ b/monitoring/grafana/provisioning/datasources/datasources.yml @@ -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 diff --git a/monitoring/stack.env.example b/monitoring/stack.env.example new file mode 100644 index 0000000..af41733 --- /dev/null +++ b/monitoring/stack.env.example @@ -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 diff --git a/ops/grafana-influxdb/README.md b/ops/grafana-influxdb/README.md index e80b621..ec64cd6 100644 --- a/ops/grafana-influxdb/README.md +++ b/ops/grafana-influxdb/README.md @@ -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`. diff --git a/ops/loki/README.md b/ops/loki/README.md index ddc6142..8758272 100644 --- a/ops/loki/README.md +++ b/ops/loki/README.md @@ -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: diff --git a/ops/policy-checks/exceptions.json b/ops/policy-checks/exceptions.json index 4c53aff..3a2e762 100644 --- a/ops/policy-checks/exceptions.json +++ b/ops/policy-checks/exceptions.json @@ -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"