--- okf: "0.1" type: audit visibility: private status: active updated: 2026-07-14 as_of: 2026-07-14 links: [] --- # Monitoring coverage — co biega vs co jest monitorowane (recon 2026-07-14) **Pytanie:** czy wszystkie serwisy floty są monitorowane? **Odpowiedź krótka:** NIE. Biega **76 kontenerów** na 5 osiągalnych węzłach, alertowanych jest **15** (~20%). **61 kontenerów** działa bez alertowania — w tym krytyczne: vaultwarden (hasła), forgejo (git = źródło prawdy GitOps), immich (zdjęcia), homeassistant5 (dom), obie instancje NPM (ingress), agent-system-telegram-bot (sam kanał alertów). --- ## Metadane zbierania danych | | | |---|---| | **Data zebrania** | 2026-07-14, 17:16–17:17 UTC | | **Metoda** | `docker ps --format '{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'` | | **PIHA** | ssh `piha` (100.108.208.3, user oskar) — 17:16:37Z | | **VPS** | ssh `vps` (100.95.58.48, user oskar) — 17:16:39Z | | **SOLARIA** | lokalnie (sesja biegła na solarii) — 17:16:41Z | | **LUSTRO** | ssh `pi@100.99.85.73` (uwaga: user **pi**, nie oskar) — 17:17:11Z | | **SATURN** | ssh `oskar@100.121.168.72` — 17:17:21Z | | **CHELSTY-INFRA / CHELSTY-HA** | OFFLINE — `tailscale status`: last seen 42 dni temu. **Do weryfikacji po powrocie online.** | | **Kod** | branch `task/monitoring-coverage-recon` @ parent `d5139c9` (master) | Sekcje A–C to **STAN NA DZIEŃ ZBIERANIA** (zmienny — przy odświeżaniu przewalidować w całości). Sekcja E (klasyfikacja) i F (plan) to **DECYZJE** (trwałe — przy odświeżaniu tylko dopisać nowe kontenery). --- ## Jak działa monitoring w tym systemie (zweryfikowane w kodzie, stan na d5139c9) Warstwy, od detekcji do alertu: 1. **node-agent** (`services/node-agent/src/node_agent.py`, `check_containers()` ~linia 305): czyta docker socket i emituje eventy dla **WSZYSTKICH kontenerów z restart policy** (`unless-stopped`/`always`/`on-failure`) — NIE filtruje po services.yaml. Emituje: `containers_not_running` (exited/dead), `healthcheck_failed` (running+unhealthy), `service_healthy` (running). Kontenery w stanie `created` pomija. **Uwaga (gap):** kontener w stanie `restarting` (crash-loop) nie pasuje ani do `exited/dead` ani do `running` — **crash-loop nie generuje żadnego eventu** (zaobserwowane na lustro/watchtower, patrz niżej). Nazwa kanoniczna = label `com.docker.compose.service` (fallback: nazwa kontenera). Zdeployowany na: piha, vps, solaria, lustro (na saturnie NIE). 2. **stability-agent** (`services/stability-agent/src/stability_agent.py`): również raportuje wszystkie kontenery (bez filtra) — eventy `containers_not_running`, `mqtt_unreachable`, `disk_usage_high` + publikacja do Redis. Biega na piha, vps, solaria (poza services.yaml!). 3. **Observer** (`scripts/observer/observer.py`, uruchamiany w control-plane@VPS): syntetyzuje eventy do `/opt/homelab/world/{services,nodes,incidents}.json`. Rejestruje **wszystko** (na dziś 116 wpisów w services.json, w tym wszystkie shadow kontenery). Widoczność ≠ alert. 4. **Supervisor** (`services/control-plane/src/supervisor.py`, `reconcile()` linia 288): generuje akcje (`redeploy`/`container_restart` → pending → Telegram → operator) **WYŁĄCZNIE dla serwisów zadeklarowanych w `hosts//services.yaml`** (`_load_desired_state()`, linie 161–195). Flaga `monitor: false` (linie 182–186) wyklucza serwis z desired-state — serwis jest udokumentowany, ale supervisor go pomija. **To jest jedyny filtr: detekcja jest flotowa, alertowanie tylko dla zadeklarowanych.** Dodatkowo supervisor routuje niezależnie od desired-state: eventy `ha_*` (z ha-diag-agent), `node_offline/stale/online` (liveness węzłów z heartbeatów node-agenta) i `disk_pressure`. 5. **fleet-prometheus** (`services/fleet-prometheus/`, VPS): scrape node_exporterów = **liveness HOSTA, nie serwisów**. Scrape'uje: vps, piha, solaria, lustro. Świadomie NIE: saturn (workstation, często off), chelsty (LTE, exporter DOWN — do zbadania osobno). Alert `NodeDown` (rules/liveness.yml) tylko dla `vps|piha` (solaria/lustro bywają planowo wyłączane). Bez Alertmanagera — alerty odbiera brain-watchdog. 6. **brain-watchdog** (`services/brain-watchdog/`, PIHA): pilnuje świeżości control-plane (/summary) + polluje `PROMETHEUS_URL/api/v1/alerts` i forwarduje do Telegrama. 7. **ha-diag-agent** (piha → HA "ken" localhost:8123; chelsty-infra → chelsty-ha): diagnostyka HA (websocket, integracje, encje) → supervisor routuje na alert/restart **niezależnie od services.yaml** (dziś wisi `container-restart-piha-homeassistant` mimo braku wpisu HA w hosts/piha/services.yaml). **Definicja "monitorowany" w tym raporcie** = supervisor wygeneruje akcję/alert gdy serwis padnie = wpis w `hosts//services.yaml` bez `monitor: false`, z nazwą zgodną z nazwą compose-service kontenera. --- ## A. Stan faktyczny — pełne listy kontenerów (STAN NA 2026-07-14) ### PIHA — 42 kontenery | Kontener | Obraz | Status | Porty | |---|---|---|---| | node-agent | node-agent-node-agent | Up 22h (healthy) | — | | paperless | ghcr.io/paperless-ngx/paperless-ngx:2.14 | Up 47h (healthy) | 192.168.31.5:8210→8000 | | vikunja | vikunja/vikunja:latest | Up 4d | 0.0.0.0:3456→3456 | | vikunja-db | postgres:16-alpine | Up 4d (healthy) | 5432 (internal) | | brain-watchdog | brain-watchdog-brain-watchdog | Up 4d (healthy) | — | | paperless-db | postgres:16-alpine | Up 4d (healthy) | 192.168.31.5:5434→5432 | | paperless-broker | redis:7-alpine | Up 4d (healthy) | 192.168.31.5:6380→6379 | | llm-gateway | llm-gateway-llm-gateway | Up 11d (healthy) | 100.108.208.3:8080→8080 | | kb-postgres | pgvector/pgvector:pg16 | Up 2w (healthy) | 0.0.0.0:5433→5432 | | agent-system-webui | agent-system-webui | Up 2w | 0.0.0.0:18180→8080 | | agent-system-runtime-materializer | agent-system-runtime-materializer | Up 2w | — | | agent-system-telegram-bot | agent-system-telegram-bot | Up 2w | — | | ha-diag-agent | ha-diag-agent-ha-diag-agent | Up 2w (healthy) | — | | stability-agent | stability-agent-stability-agent | Up 2w (healthy) | — | | agent-system-redis | redis:7 | Up 2w | 0.0.0.0:6379→6379 | | nginxproxymanager-app-1 | jc21/nginx-proxy-manager:latest | Up 2w | 0.0.0.0:80-81→80-81, 443→443 | | homeassistant5 | ghcr.io/home-assistant/home-assistant:stable | Up 2w | (host network, :8123) | | immich_server | ghcr.io/immich-app/immich-server:release | Up 2w (healthy) | 0.0.0.0:2283→2283, 8081-8082 | | immich_postgres | tensorchord/pgvecto-rs:pg14-v0.2.0 | Up 2w (healthy) | 5432 (internal) | | immich_machine_learning | ghcr.io/immich-app/immich-machine-learning:release | Up 2w (healthy) | — | | immich_redis | redis:6.2-alpine | Up 2w (healthy) | 6379 (internal) | | forgejo_dind | docker:dind | Up 2w | 2375-2376 (internal) | | forgejo | codeberg.org/forgejo/forgejo:7 | Up 12d | 0.0.0.0:3000→3000, 222→22 | | forgejo-db-1 | postgres:14 | Up 2w | 5432 (internal) | | zigbee2mqtt | koenkk/zigbee2mqtt | Up 3d | 0.0.0.0:8087→8080 | | audiobookshelf | ghcr.io/advplyr/audiobookshelf:latest | Up 2w | 0.0.0.0:13378→80 | | grafana | grafana/grafana-enterprise:latest | Up 2w | 0.0.0.0:9003→3000 | | wikijs-db-1 | postgres:15-alpine | Up 2w | 5432 (internal) | | code-server | lscr.io/linuxserver/code-server:latest | Up 2w | 0.0.0.0:8443→8443 | | portainer | portainer/portainer-ce:latest | Up 2w | 0.0.0.0:8008→8000, 9009→9000 | | prom | prom/prometheus:latest | Up 2w | 0.0.0.0:9090→9090 | | homepage | ghcr.io/gethomepage/homepage:latest | Up 2w (healthy) | 0.0.0.0:3033→3000 | | actual-server | actualbudget/actual-server:latest-alpine | Up 2w | 0.0.0.0:5006→5006 | | mqtt-exporter-mqtt-exporter-1 | kpetrem/mqtt-exporter:latest | Up 2w | 0.0.0.0:9000→9000 | | node-exporter | quay.io/prometheus/node-exporter:latest | Up 2w | — | | wikijs-wiki-1 | ghcr.io/requarks/wiki:2 | Up 2w | 0.0.0.0:3300→3000 | | owntracks-recorder | owntracks/recorder:latest | Up 2w | 0.0.0.0:8083→8083 | | vaultwarden | vaultwarden/server:latest | Up 2w (healthy) | 0.0.0.0:3012→80 | | pihole-exporter | ekofr/pihole-exporter:latest | Up 2w | 0.0.0.0:9617→9617 | | fail2ban-prometheus-exporter-exporter-1 | registry.gitlab.com/hctrdev/fail2ban-prometheus-exporter:latest | Up 2w **(unhealthy)** | 0.0.0.0:9191→9191 | | owntracks-prometheus-exporter-prometheus-owntracks-exporter-1 | linusgroh/prometheus-owntracks-exporter | Up 2w | 0.0.0.0:8780→80 | | own-tracks-frontend-owntracks-frontend-1 | owntracks/frontend | Up 2w | 0.0.0.0:8084→80 | Zmiany vs audyt 2026-06-30 (`docs/infra/inventory-2026-06-30.md`): **przybyły** paperless, paperless-db, paperless-broker (Deploy 1, 2026-07-10); **zniknęły** diskover i elasticsearch (w audycie 06-30 były w 33 shadow; dziś nie biegają). 06-30: 40 kontenerów → dziś: 42. ### VPS — 24 kontenery | Kontener | Obraz | Status | Porty | |---|---|---|---| | control-plane-executor | control-plane-executor | Up 46m (healthy) | — | | control-plane-observer | control-plane-observer | Up 46m (healthy) | — | | control-plane-supervisor | control-plane-supervisor | Up 46m (healthy) | — | | control-plane-ui | control-plane-operator-ui | Up 46m (healthy) | 0.0.0.0:18180→8080 | | fleet-prometheus | prom/prometheus:v3.5.0 | Up 2w (healthy) | 100.95.58.48:9090→9090 | | node-agent | node-agent-node-agent | Up 2w (healthy) | — | | humanai-mailer | humanai-mailer | Up 2w | — | | humanai-landing | humanai-landing | Up 2w | 80 (internal) | | umami | ghcr.io/umami-software/umami:postgresql-latest | Up 2w (healthy) | 3000 (internal) | | umami-db | postgres:16-alpine | Up 2w (healthy) | 5432 (internal) | | node_exporter | quay.io/prometheus/node-exporter:latest | Up 5w | (host network :9100) | | stability-agent | stability-agent-stability-agent | Up 5w (healthy) | — | | outline-outline-1 | outlinewiki/outline:1.6.1 | Up 5w (healthy) | 0.0.0.0:3000→3000 | | outline-postgres-1 | 4e6e670bb069 (anonimowy image ID!) | Up 5w (healthy) | 5432 (internal) | | outline-redis-1 | redis:7-alpine | Up 5w (healthy) | 6379 (internal) | | ai-cluster-service-ops-worker-1 | ai-cluster-service-ops-worker | Up 5w | — | | ai-cluster-codex-worker-1 | ai-cluster-codex-worker | Up 5w | — | | ai-cluster-openclaw-1 | ai-cluster-openclaw | Up 5w (healthy) | 0.0.0.0:8000→8000 | | ai-cluster-planner-worker-1 | ai-cluster-planner-worker | Up 5w | — | | ai-cluster-redis-1 | redis:7-alpine | Up 5w | 6379 (internal) | | mosquitto | eclipse-mosquitto:2 | Up 5w | 100.95.58.48:1883→1883 | | joplin-server | joplin/server:latest | Up 5w | 127.0.0.1:22300→22300 | | npm | jc21/nginx-proxy-manager:latest | Up 5w | 0.0.0.0:80-81→80-81, 443→443 | | joplin-db | postgres:18 (pre-release tag!) | Up 5w (healthy) | 5432 (internal) | **gokapi NIE biega** mimo deklaracji w hosts/vps/services.yaml — supervisor poprawnie to wykrył: w `/opt/homelab/actions/pending/` wisi `redeploy-vps-gokapi.json`. To dowód, że monitoring desired-state DZIAŁA dla zadeklarowanych serwisów. ### SOLARIA — 5 kontenerów | Kontener | Obraz | Status | Porty | |---|---|---|---| | paperless-worker | ghcr.io/paperless-ngx/paperless-ngx:2.14 | Up 5h (healthy) | 8000 (internal) | | planner-agent | planner-agent-planner-agent | Up 5h (healthy) | — | | node-agent | node-agent-node-agent | Up 5h (healthy) | — | | stability-agent | stability-agent-stability-agent | Up 5h (healthy) | — | | node_exporter | quay.io/prometheus/node-exporter:latest | Up 5h | (host network :9100) | ### LUSTRO — 4 kontenery | Kontener | Obraz | Status | Porty | |---|---|---|---| | node-agent | node-agent-node-agent | Up 20h (healthy) | — | | node-exporter | quay.io/prometheus/node-exporter:latest | Up 20h | (host network :9100) | | piper-tts | piper-tts-rpi5 | Up 20h | 0.0.0.0:5000→5000, 10200→10200 | | pi-watchtower-1 | containrrr/watchtower | **Restarting (1) — crash-loop!** | — | **pi-watchtower-1 jest w crash-loopie** i przez lukę w node-agencie (stan `restarting` nie generuje eventu, patrz sekcja o mechanizmie) — **nikt tego nie widzi**; world-state pokazuje `lustro/watchtower healthy` (stary event `service_healthy`). ### SATURN — 1 kontener | Kontener | Obraz | Status | Porty | |---|---|---|---| | agent-system-webui | agent-system-webui | Up 9h | 0.0.0.0:8080→8080 | Stack control-plane z audytu 06-30 (executor/observer/supervisor/ui) już NIE biega na saturnie — posprzątane. Saturn nie ma node-agenta, nie ma services.yaml, nie jest scrape'owany przez fleet-prometheus → **węzeł całkowicie poza monitoringiem** (świadomie: workstation, często off). ### CHELSTY-INFRA / CHELSTY-HA — OFFLINE (42 dni) Niedostępne przez Tailscale (last seen ~2026-06-02). Deklaracje: chelsty-infra = ha-diag-agent, node-agent, mosquitto, zigbee2mqtt, frigate; chelsty-ha = homeassistant (`monitor: false`). `world/services.json` nadal pokazuje serwisy chelsty-infra jako "healthy" — to STĘCHŁY stan (status serwisów nie wygasa; liveness wygasa tylko na poziomie węzła). **Do weryfikacji po powrocie online**, w tym: czy alerty `node_offline` dla chelsty odpaliły 42 dni temu. --- ## B. Stan deklarowany — hosts//services.yaml (STAN NA 2026-07-14) | Węzeł | Zadeklarowane serwisy | monitor: false? | |---|---|---| | piha | ha-diag-agent, node-agent, brain-watchdog, vikunja, llm-gateway, kb-postgres | — | | vps | node-agent, control-plane, node_exporter, fleet-prometheus, gokapi | — | | solaria | node-agent | — | | lustro | node-agent | — | | saturn | **BRAK PLIKU services.yaml** | — | | chelsty-infra | ha-diag-agent, node-agent, mosquitto, zigbee2mqtt, frigate | — | | chelsty-ha | homeassistant | **TAK** (node-agent tam nie zdeployowany; HA kryty pośrednio przez MQTT) | Razem: **18 deklaracji alertowalnych** (w tym 5 na offline'owym chelsty-infra) + 1 z monitor:false. Uwaga: `stability-agent` ma katalogi w `hosts/{piha,solaria,vps}/runtime/`, ale NIE ma wpisów w żadnym services.yaml — sam strażnik nie jest pilnowany. --- ## C. Luka — biega, ale poza alertowaniem (STAN NA 2026-07-14) Pokrycie per węzeł (kontenery alertowane / biegające): | Węzeł | Biega | Alertowane | Luka | |---|---|---|---| | PIHA | 42 | 6 (node-agent, ha-diag-agent, brain-watchdog, vikunja, llm-gateway, kb-postgres) | **36** | | VPS | 24 | 7 (node-agent, control-plane ×4¹, node_exporter, fleet-prometheus) | **17** | | SOLARIA | 5 | 1 (node-agent) | **4** | | LUSTRO | 4 | 1 (node-agent) | **3** | | SATURN | 1 | 0 | **1** | | **RAZEM** | **76** | **15** | **61 (~80%)** | ¹ control-plane to 1 deklaracja pokrywająca 4 kontenery — node-agent na VPS probe'uje endpoint HTTP :18180/summary i emituje `service_healthy`/`service_unhealthy` dla logicznego serwisu "control-plane" (`_check_control_plane_health()`). Częściowe pokrycie (nie liczone jako "alertowane" powyżej): - **homeassistant5@piha** — ha-diag-agent pilnuje websocketu HA i supervisor generuje `container_restart`/`alert_only` niezależnie od services.yaml. Padnięcie HA zostanie zauważone. Brak jednak wpisu desired-state (drift "kontener zniknął" nie będzie wykryty). - **node-exporter@piha** — jego padnięcie = `up==0` w fleet-prometheus = alert NodeDown (piha) przez brain-watchdog → Telegram. Pośrednio alertowany. - **node_exporter@solaria, node-exporter@lustro** — scrape'owane, ale świadomie wyłączone z reguły NodeDown (węzły planowo wyłączane) → brak alertu. - **gokapi@vps** — zadeklarowany, NIE biega; drift poprawnie wykryty (pending `redeploy-vps-gokapi.json`). Luka deploymentu, nie monitoringu. --- ## D. Nowe serwisy KB — weryfikacja wpisu z backlogu (f135365) Backlog ("Nowe serwisy KB nie sa w monitoringu", 2026-07-12) **potwierdzony w połowie** — paperless i paperless-worker faktycznie poza monitoringiem; gokapi/llm-gateway/kb-postgres są OK: | Serwis | services// w repo? | hosts/*/services.yaml? | Biega? | Alertowany? | |---|---|---|---|---| | paperless (+db, +broker) | ✓ (+ hosts/piha/runtime/paperless) | ✗ | ✓ piha (healthy) | **✗ LUKA** | | paperless-worker | ✓ (owner_node: solaria) | ✗ | ✓ solaria (healthy) | **✗ LUKA** | | nextcloud | ✓ (owner_node: piha, commit 7e5577c) | ✗ | ✗ nigdzie (nie zdeployowany) | ✗ (nie dotyczy — dodać wpis RAZEM z deployem) | | gokapi | ✓ (owner_node: vps) | ✓ hosts/vps | **✗ nie biega** | ✓ — drift wykryty, wisi `redeploy-vps-gokapi` | | llm-gateway | ✓ (owner_node: piha) | ✓ hosts/piha | ✓ piha (healthy) | ✓ | | kb-postgres | ✓ (owner_node: piha) | ✓ hosts/piha | ✓ piha (healthy) | ✓ | --- ## E. Klasyfikacja niemonitorowanych kontenerów (DECYZJA — trwała) Kategorie: - **A (pełny GitOps):** krytyczny — docelowo compose w `services/`, service.yaml, deploy przez deploy.sh. Każde A dostaje NAJPIERW wpis monitoringowy (krok B) — tanio, od razu. - **B (tylko monitoring):** deployment zostaje jak jest; dodać do `hosts//services.yaml` → supervisor alarmuje gdy padnie. - **C (świadomie poza):** padnięcie nie boli / narzędzie jednorazowe. Uzasadnienie obowiązkowe. Kontenery pomocnicze stacka (db/redis/broker) dziedziczą kategorię stacka — w services.yaml deklaruje się serwis główny (padnięcie db zwykle wywala healthcheck głównego kontenera). ### PIHA (36 luk) | Kontener | Co robi | Kategoria | Uzasadnienie | |---|---|---|---| | vaultwarden | menedżer haseł | **A** (najpierw B) | Hasła całej rodziny — padnięcie/utrata danych boli maksymalnie; musi być w GitOps z backupem i alertem | | forgejo, forgejo-db-1, forgejo_dind | git hosting + CI | **A** (najpierw B) | Źródło prawdy GitOps + OIDC dla vikunji; bez forgejo nie ma deployów; już zidentyfikowane w audycie 06-30 (owner_node błędnie=saturn) | | homeassistant5 | Home Assistant "ken" (dom) | **A** (najpierw B) | Automatyka domu; częściowo kryty przez ha-diag-agent (websocket), ale bez wpisu desired-state; wpis `homeassistant` w services.yaml domknie lukę | | immich_server, immich_postgres, immich_machine_learning, immich_redis | zdjęcia rodzinne | **A** (najpierw B) | Dane niereprodukowalne (zdjęcia); padnięcie = brak backupu telefonów w tle, zauważalne późno | | nginxproxymanager-app-1 | ingress LAN (*.kapala.org: HA, immich, paperless, cloud…) | **A** (najpierw B) | Pojedynczy punkt wejścia do wszystkich usług domowych; padnięcie = "wszystko nie działa" | | paperless, paperless-db, paperless-broker | KB: dokumenty (OCR pipeline) | **B** | Już w GitOps (services/paperless + runtime override) — brakuje TYLKO wpisu w services.yaml; przypadek z backlogu f135365 | | stability-agent | watchdog węzła | **B** | Repo-managed (runtime override jest); strażnik musi być pilnowany; dotyczy też vps i solarii | | zigbee2mqtt | bridge Zigbee→MQTT (ken) | **B** | services/zigbee2mqtt istnieje (owner=piha); sensory domowe przestają raportować gdy padnie | | agent-system-telegram-bot | kanał alertów Telegram | **B** | Jak padnie, ŻADEN alert nie dojdzie — a nikt się nie dowie; pilnować w pierwszej kolejności | | agent-system-webui | operator UI (approve akcji) | **B** | Bez niego nie da się zatwierdzać akcji z przeglądarki; część pętli human-in-the-loop | | agent-system-redis | redis dla agent-system | **B** | Zależność telegram-bota i webui; tani wpis | | agent-system-runtime-materializer | materializacja runtime agentów | **B** | Część stacka agent-system; padnięcie cichaczem psuje odświeżanie stanu | | wikijs-wiki-1, wikijs-db-1 | wiki | **B** | Notatki/dokumentacja domowa — padnięcie boli umiarkowanie, wpis jest tani | | actual-server | budżet domowy | **B** | Dane finansowe; używany regularnie, padnięcie zauważalne przy wpisywaniu wydatków | | prom | domowy Prometheus (LAN) | **B** | Źródło metryk domowych (HA, piha OS); padnięcie = dziura w historii; UWAGA: ma plaintext token HAOS (anti-pattern, patrz services/fleet-prometheus/prometheus.yml komentarz) | | owntracks-recorder | lokalizacja rodziny (backend) | **C** | Hobby/eksperyment; padnięcie = luka w śladzie lokalizacji, nie boli operacyjnie | | own-tracks-frontend-… | frontend owntracks | **C** | Czysta wizualizacja | | owntracks-prometheus-exporter-… | exporter owntracks | **C** | Pomocniczy; objaw padnięcia = brak metryk, widoczny w grafanie | | mqtt-exporter-mqtt-exporter-1 | exporter MQTT→prom | **C** | Jak wyżej | | pihole-exporter | exporter pihole | **C** | Jak wyżej | | fail2ban-prometheus-exporter-… | exporter fail2ban | **C** | Jak wyżej; DZIŚ unhealthy — naprawić lub usunąć (follow-up) | | node-exporter | metryki hosta dla fleet-prometheus | **C** | Pośrednio alertowany: padnięcie = up==0 = NodeDown(piha) przez brain-watchdog | | grafana | dashboardy | **C** | Wizualizacja; padnięcie zauważalne przy wejściu, zero utraty danych (provisioning/db na dysku) | | homepage | strona startowa | **C** | Kosmetyka | | audiobookshelf | audiobooki | **C** | Media; restart ręczny wystarczy | | code-server | IDE w przeglądarce | **C** | Narzędzie dev, używane ad-hoc | | portainer | GUI dockera | **C** | Narzędzie administracyjne ad-hoc; wręcz kandydat do usunięcia (GitOps ma być źródłem prawdy) | ### VPS (17 luk) | Kontener | Co robi | Kategoria | Uzasadnienie | |---|---|---|---| | npm | publiczny ingress okit.pl | **A** (najpierw B) | Cała publiczna powierzchnia (share.okit.pl, vikunja.okit.pl…); manifesty A już istnieją na NIEZMERGOWANEJ gałęzi `feat/vps-service-migration` (commit 862c04a, cutover niewykonany) | | mosquitto | broker MQTT ai-cluster | **B** | services/mosquitto istnieje ale owner_node=piha (błąd — biega na VPS od tygodni, audyt 06-30 poz. 3); szyna komunikacji ai-cluster | | stability-agent | watchdog węzła | **B** | Jak na piha | | outline-outline-1, outline-postgres-1, outline-redis-1 | wiki zespołowa | **B** | Notatki; manifesty na gałęzi feat/vps-service-migration; przy okazji naprawić anonimowy image ID postgresa (audyt 06-30 poz. 19) | | joplin-server, joplin-db | sync notatek | **B** | Notatki osobiste; przy okazji zejść z postgres:18 pre-release (audyt 06-30 poz. 20) | | ai-cluster-codex-worker-1, ai-cluster-planner-worker-1, ai-cluster-service-ops-worker-1, ai-cluster-openclaw-1, ai-cluster-redis-1 | workery agentowe | **B** | Padnięcie = agenci przestają mielić kolejki (objawia się późno); docelowo migracja compute na SOLARIA (CLAUDE.md), monitoring dodać już teraz | | humanai-landing, humanai-mailer | strona publiczna + mailer | **B** | Publiczna wizytówka — padnięcie boli reputacyjnie i cicho (nikt nie patrzy); brak w repo (audyt 06-30 poz. 21) | | umami, umami-db | analityka www | **C** | Statystyki odwiedzin; padnięcie = luka w danych analitycznych, nie boli operacyjnie | ### SOLARIA (4 luki) | Kontener | Co robi | Kategoria | Uzasadnienie | |---|---|---|---| | paperless-worker | OCR/konsument kolejki KB | **B** | Przypadek wprost z backlogu f135365: "jesli worker padnie (…) dowiesz sie po tym, ze kolejka nie jest przetwarzana"; repo+runtime są, brakuje wpisu | | planner-agent | agent planowania | **B** | services/planner-agent istnieje (owner=solaria ✓); audyt 06-30 poz. 14 | | stability-agent | watchdog węzła | **B** | Jak na piha/vps | | node_exporter | metryki hosta | **C** | Scrape'owany, ale solaria świadomie poza NodeDown (planowe wyłączenia); alerting wróci z anomaly-detection (backlog) | ### LUSTRO (3 luki) | Kontener | Co robi | Kategoria | Uzasadnienie | |---|---|---|---| | piper-tts | TTS dla magic mirror | **C** | Padnięcie = lustro nie mówi; kosmetyka. Jeśli tani wpis — można podnieść do B przy okazji | | node-exporter | metryki hosta | **C** | Jak solaria — świadomie poza NodeDown | | pi-watchtower-1 | auto-update obrazów | **C** + **follow-up PILNY** | DZIŚ w crash-loopie, niewykrywalnym przez node-agent (luka na stan `restarting`). Decyzja operatora: naprawić albo USUNĄĆ (watchtower na edge = niekontrolowane pulle, sprzeczne z GitOps) | ### SATURN (1 luka) | Kontener | Co robi | Kategoria | Uzasadnienie | |---|---|---|---| | agent-system-webui | operator UI (kopia dev?) | **C** | Saturn = workstation, często wyłączony; świadomie poza monitoringiem (jak w fleet-prometheus). Wyjaśnić czemu biega duplikat UI z pihy (follow-up) | --- ## F. Plan domknięcia — paczki na jedną sesję każda (DECYZJA — trwała) **Zasada procesowa (z backlogu, do utrwalenia):** wpis w `hosts//services.yaml` + `inventory/topology.yaml` to CZĘŚĆ deployu każdego nowego serwisu, nie osobny krok "kiedyś". **⚠ Gotcha techniczna dla WSZYSTKICH paczek (sprawdzić przed każdym wpisem):** supervisor matchuje klucz `node/nazwa-serwisu` z nazwą kanoniczną kontenera = label `com.docker.compose.service` (node_agent.py `_canonical_container_name()`). Dla stacków compose'owych to NIE jest nazwa kontenera: np. `nginxproxymanager-app-1` ma compose-service **"app"**, `wikijs-wiki-1` → "wiki", stąd w world/services.json wiszą kolizyjne klucze typu `piha/app`, `piha/db`, `piha/redis`, `piha/database`. Przed dodaniem wpisu sprawdzić na hoście: `docker inspect --format '{{ index .Config.Labels "com.docker.compose.service" }}'` — i jeśli label koliduje/jest ogólnikowy, najpierw nadać `container_name` + porządny compose project name albo poprawić observer (patrz follow-upy). Bez tego wpis będzie wiecznym `missing_service` i zaspamuje kolejkę akcji. ### Paczka 1 — KB + już-zGitOps'owane serwisy (najtańsza-najważniejsza; czysta kategoria B) Serwisy, które JUŻ są w repo (services/ + runtime overrides) — brakuje tylko rejestracji: 1. `hosts/piha/services.yaml`: + paperless, + stability-agent, + zigbee2mqtt 2. `hosts/solaria/services.yaml`: + paperless-worker, + planner-agent, + stability-agent 3. `hosts/vps/services.yaml`: + stability-agent, + npm, + mosquitto (i naprawić `services/mosquitto/service.yaml` owner_node: piha→vps oraz `services/npm` — potwierdzić że nazwa compose-service = "npm") 4. `inventory/topology.yaml`: dopisać ww. do sekcji węzłów 5. Weryfikacja: po 1–2 cyklach supervisora `world/services.json` ma klucze o zgodnych nazwach, kolejka pending NIE zawiera fałszywych `missing_service`; test driftu: `docker stop paperless-worker` na chwilę → pojawia się akcja → `docker start` → akcja auto-cancelled (test wymaga zgody operatora; alternatywnie tylko obserwacja biernie) 6. Domknięcie wiszącego driftu: zdeployować gokapi na VPS (akcja `redeploy-vps-gokapi` już czeka na approve) — UWAGA: brak `hosts/vps/runtime/gokapi/docker-compose.override.yml` z mem_limit (reguła VPS 4GB) — dodać przed deployem. ### Paczka 2 — krytyczne shadow na PIHA (kategoria B dla przyszłych A) Wpisy monitoringowe (bez ruszania deploymentu!) dla: vaultwarden, forgejo, homeassistant (kontener homeassistant5), immich, nginxproxymanager (compose-service prawdopodobnie "app" — patrz gotcha!), agent-system (telegram-bot, webui, redis, runtime-materializer), wikijs, actual-server, prom. Każdy wpis poprzedzony sprawdzeniem compose-label na hoście. Jeśli labels kolidują (db/app/redis) — najpierw follow-up "canonical naming" (niżej) albo wpis odroczony z adnotacją. ### Paczka 3 — VPS shadow (kategoria B + przygotowanie cutover) 1. Wpisy: outline, joplin, ai-cluster, humanai-landing, humanai-mailer (+ umami jeśli tanio) 2. Przejrzeć gałąź `feat/vps-service-migration` (commit 862c04a: manifesty npm/outline/joplin/ ai-cluster; cutover NIE wykonany) — zdecydować: merge + cutover per checklista z CLAUDE.md, czy przepisać od nowa. UWAGA: CLAUDE.md już dziś twierdzi "All VPS services are now GitOps-managed" — to NIEPRAWDA na masterze; poprawić doc albo zmergować gałąź. ### Paczka 4 — pełny GitOps dla krytycznych (kategoria A; JEDEN serwis = JEDNA sesja) Kolejność wg bólu: 1) vaultwarden, 2) forgejo, 3) npm@piha + npm@vps (cutover), 4) immich, 5) homeassistant5. Dla każdego: compose do `services//`, service.yaml, env.example, healthcheck.sh, runtime override w `hosts/piha/runtime/`, deploy przez deploy.sh. **Reguła migracji danych: ścieżki danych zostają NA MIEJSCU** (CLAUDE.md) — zero przenoszenia wolumenów bez osobnego planu. ### Paczka 5 — porządki i decyzje C (follow-upy) - **lustro/pi-watchtower-1**: naprawić albo usunąć (crash-loop TERAZ; watchtower vs GitOps) - **piha/fail2ban-exporter**: unhealthy od ≥2 tyg. — naprawić albo usunąć - **saturn/agent-system-webui**: wyjaśnić czemu biega; usunąć jeśli pozostałość dev - **nextcloud**: przy deployu (osobna sesja per plan KB) wpis do services.yaml OD RAZU - **chelsty**: po powrocie online powtórzyć inwentaryzację (sekcja "Jak odświeżyć") - **saturn**: decyzja czy dostaje node-agenta + services.yaml (dziś świadomie poza) ### Follow-upy techniczne w kodzie monitoringu (poza zakresem tego reconu, do osobnych tasków) 1. **node-agent nie widzi stanu `restarting`** (crash-loop = cisza) — dodać gałąź dla `status == "restarting"` w `check_containers()` → event `containers_not_running` lub nowy typ `container_crash_loop`. Dowód: lustro/pi-watchtower-1. 2. **Kolizje nazw kanonicznych** w observerze/node-agencie: label `com.docker.compose.service` bez project-name daje klucze `piha/db`, `piha/app`, `piha/redis` (dziś w world/services.json są duplikaty typu `piha/immich_server` I `piha/immich-server`). Propozycja: klucz `_` albo preferować container_name gdy label jest ogólnikowy. 3. **Stęchły world-state dla offline węzłów**: serwisy chelsty-infra "healthy" 42 dni po zniknięciu węzła — status serwisu powinien degradować się razem z liveness węzła. 4. **Alerting solaria/lustro**: świadomie wyłączone z NodeDown; docelowo anomaly detection (istniejący backlog "Plan: Monitoring floty — Prometheus jako źródło prawdy"). --- ## TL;DR - **Biega:** 76 kontenerów (42 piha, 24 vps, 5 solaria, 4 lustro, 1 saturn); chelsty-infra/ha offline od ~42 dni — niezweryfikowane. - **Alertowane:** 15 kontenerów przez 13 deklaracji desired-state (+ HA częściowo przez ha-diag-agent, + node-exporter@piha pośrednio przez NodeDown, + gokapi: zadeklarowany, niezdeployowany, drift POPRAWNIE wykryty i wisi w pending). - **Luka:** 61 kontenerów (~80%) bez alertowania. Detekcja (node-agent/observer) widzi wszystko; filtr jest w supervisorze — alertuje TYLKO to, co wpisane w `hosts//services.yaml` (bez `monitor: false`). - **Najboleśniejsze luki:** vaultwarden (hasła), forgejo (git), immich (zdjęcia), homeassistant5 (dom, częściowo kryty), npm ×2 (cały ingress), agent-system-telegram-bot (kanał alertów pilnujący wszystkiego innego, sam niepilnowany). - **Znaleziska przy okazji:** lustro/watchtower w crash-loopie niewykrywalnym przez node-agent (luka na stan `restarting`); fail2ban-exporter@piha unhealthy; gokapi czeka na deploy; CLAUDE.md błędnie twierdzi że VPS jest w pełni GitOps (manifesty na niezmergowanej gałęzi). - **Co najpierw:** Paczka 1 (wpisy dla paperless, paperless-worker, stability-agent ×3, zigbee2mqtt, npm, mosquitto, planner-agent — wszystko już w repo, tylko rejestracja) → Paczka 2 (krytyczne shadow PIHA) → Paczka 3 (VPS) → Paczka 4 (pełny GitOps po kolei). --- ## Jak odświeżyć ten dokument 1. Stan faktyczny (sekcja A) — jedna pętla (uwaga na userów ssh: lustro=pi, reszta=oskar; solaria/saturn wg tego skąd odpalasz): ```bash for target in oskar@100.108.208.3 oskar@100.95.58.48 oskar@100.100.231.104 \ pi@100.99.85.73 oskar@100.121.168.72 oskar@100.98.91.98; do echo "===== $target =====" ssh -o ConnectTimeout=10 -o BatchMode=yes "$target" \ "date -u +%Y-%m-%dT%H:%M:%SZ; docker ps --format '{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'" done ``` (kolejno: piha, vps, solaria, lustro, saturn, chelsty-infra; chelsty-infra pomiń jeśli offline) 2. Stan deklarowany (sekcja B): `grep -A2 "^services:" hosts/*/services.yaml` + ręcznie sprawdzić flagi `monitor: false`. 3. Luka (sekcja C): porównać 1 z 2 per węzeł; pamiętać że 1 deklaracja może pokrywać stack wielokontenerowy (control-plane, vikunja) i że match idzie po labelu `com.docker.compose.service`, nie po nazwie kontenera. 4. Wiszące akcje/drifty: `ssh vps ls /opt/homelab/actions/pending/`. 5. Sekcje E–F: NIE odtwarzać — tylko dopisać nowe kontenery i odhaczyć wykonane paczki. Zmienić klasyfikację wolno tylko świadomą decyzją (to sekcje DECYZYJNE).