homelab-codex-ws/docs/infra/monitoring-coverage-2026-07-14.md
2026-07-14 19:25:51 +02:00

32 KiB
Raw Permalink Blame History

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:1617: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 AC 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 runningcrash-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/<node>/services.yaml (_load_desired_state(), linie 161195). Flaga monitor: false (linie 182186) 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/<node>/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/<node>/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/<node>/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 <kontener> --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 12 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/<name>/, 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 <project>_<service> 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/<node>/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):

    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 EF: NIE odtwarzać — tylko dopisać nowe kontenery i odhaczyć wykonane paczki. Zmienić klasyfikację wolno tylko świadomą decyzją (to sekcje DECYZYJNE).