# Audyt odchudzania PIHA — 2026-07-02

> Faza 1 (READ-ONLY) modulu 0 filaru dokumentow (`docs/kb/modules/00-piha-slim.md`).
> Zadna akcja nie zostala wykonana — wylacznie `docker stats/inspect/logs`, `ss`, `curl` (odczyt).
> Stan w momencie audytu: **RAM 7.9Gi total, 5.0Gi used, 2.9Gi available; swap 4Gi total, 2.0Gi uzyty.**
> 41 kontenerow Up (inwentaryzacja 2026-06-30 liczyla 40; wszystkie nadal biega).
>
> **AKTUALIZACJA 2026-07-02 (FAZA 2):** czesc rekomendacji zostala skorygowana po review
> Oskara i wykonana — patrz sekcja [Korekta po review + egzekucja](#korekta-po-review--egzekucja-2026-07-02)
> na koncu dokumentu. W skrocie: ES+diskover UBITE; llm-gateway ZOSTAJE (wlasny kod);
> immich ZOSTAJE NA PIHA na stale.

## Podsumowanie: ile RAM da sie zwolnic

| Kategoria | Kontenery | RAM (suma rezydentna) |
|---|---|---|
| **BEZPIECZNY USUN** | elasticsearch, diskover, llm-gateway | **~917 MiB** |
| **PRZENIES** (kandydat: SOLARIA) | immich (4 kontenery) | **~620 MiB** |
| Razem potencjal | 7 kontenerow | **~1.54 GiB** |

Po samym "BEZPIECZNY USUN": available rosnie z ~2.9Gi do **~3.8Gi** — kryterium modulu
(>= 1.5Gi available stabilnie) spelnione z duzym zapasem jeszcze przed migracja immich.
Dodatkowo elasticsearch (JVM, heap 512m ale RSS ~900Mi) jest glownym podejrzanym o
zajety swap — po jego usunieciu presja na swap powinna realnie spasc.

Uwaga metodyczna: `docker stats` pokazuje pamiec rezydentna (bez stron w swapie), wiec
realny zysk moze byc *wiekszy* niz suma powyzej.

## Kluczowe ustalenia (odpowiedzi na pytania modulu)

1. **elasticsearch (895Mi) sluzy WYLACZNIE diskoverowi** — nie wikijs.
   Dowody:
   - siec `diskover_default` zawiera tylko `elasticsearch` + `diskover`; wikijs siedzi
     w `wikijs_default` ze swoim postgresem (`DB_TYPE=postgres`, brak zmiennych ES);
   - jedyny indeks uzytkowy: `diskover-pimedia`, 133 862 dok., **21.8 MB**, utworzony
     **2025-10-15** — od ~8.5 miesiaca zero reindeksacji (index_total=43 to tylko geoip);
   - 92 zapytania search w 5 dni uptime (szum UI/healthcheck), zero polaczen
     established na :9200 w trakcie audytu; homepage nie ma widgetu diskover/ES.
2. **diskover to martwy indekser**: zaindeksowal raz w pazdzierniku 2025, logi puste od
   >=24h, web-UI nieuzywane. Trzyma przy zyciu ES wart ~900Mi RAM dla 22MB danych.
3. **llm-gateway nie ma zadnego konsumenta**: jedyny ruch w logach to Prometheus
   odpytujacy `/v1/metrics` i dostajacy **404** (target nazwany `watchtower` w prom —
   oczekuje watchtowera na :8080, a port zajal llm-gateway). Zero polaczen na :8080.
4. **Na PIHA dziala host-owy mosquitto (systemd, port 1883)** — inwentaryzacja
   2026-06-30 mowila "na PIHA nie ma mosquitto" (prawda tylko dla Dockera). To
   KRYTYCZNA zaleznosc: zigbee2mqtt (`mqtt://192.168.31.5:1883`), owntracks-recorder,
   mqtt-exporter i RPi-Reporter-MQTT2HA-Daemon lacza sie do niego. Nie ruszac.
5. **forgejo na PIHA to origin repo GitOps** (`ssh://git@100.108.208.3:222/...` = PIHA
   Tailscale, port 222) + provider OIDC dla vikunji. Absolutnie ZOSTAW.
6. **prom 342% CPU** z pierwszego pomiaru to byl chwilowy burst — powtorny pomiar:
   1.87% CPU. Bez alarmu, ale 513Mi RAM to kandydat do tuningu retencji (osobno).

## Tabela glowna: shadow-kontenery

RAM = rezydentny z `docker stats` w trakcie audytu. Kontenery GitOps (ha-diag-agent,
node-agent, brain-watchdog, vikunja, vikunja-db, kb-postgres, stability-agent) pominiete
zgodnie z zakresem.

| Kontener | RAM | Kto uzywa | Zywy? | Kategoria | Uzasadnienie | Zysk |
|---|---|---|---|---|---|---|
| **elasticsearch** | 895Mi | tylko diskover (siec `diskover_default`) | Up, ale indeks z 2025-10-15; brak polaczen na :9200 | **BEZPIECZNY USUN** | 900Mi RAM dla 22MB martwego indeksu; wikijs uzywa postgresa, nie ES | **895Mi** |
| **diskover** | 7Mi | nikt (web-UI :9999 bez ruchu, logi puste) | martwy funkcjonalnie | **BEZPIECZNY USUN** | jednorazowy indekser, ostatni bieg 8.5 mies. temu; usuwac RAZEM z ES | 7Mi |
| **llm-gateway** | 15Mi | nikt (tylko 404 od prom) | Up, zero realnego ruchu | **BEZPIECZNY USUN** | brak konsumenta; przy okazji zwalnia port 8080 i usuwa falszywy target prom | 15Mi |
| immich_server | 416Mi | uzytkownik (vhosty immich.okit.pl, foty.kapala.org; widget homepage) | Up, tylko logi version-check w 48h | **PRZENIES** | foto+ML nie musi byc na always-on Pi; SOLARIA ma GPU i RAM; wymaga planu migracji danych (biblioteka na NVMe /home) | 416Mi |
| immich_postgres | 165Mi | immich | Up | **PRZENIES** | razem z immich | 165Mi |
| immich_machine_learning | 30Mi | immich | Up | **PRZENIES** | ML na arm64 CPU to marnotrawstwo; na SOLARIA zyska GPU | 30Mi |
| immich_redis | 10Mi | immich | Up | **PRZENIES** | razem z immich | 10Mi |
| forgejo_dind | 36Mi | forgejo CI (runner) | Up, logi puste >=48h | **DECYZJA OSKARA** | jesli CI na PIHA nieuzywane → stop (36Mi); jesli uzywane sporadycznie → zostaje | (36Mi) |
| code-server | 15Mi | vhost code-server.okit.pl, link w homepage | Up, logi puste, 0 polaczen na :8443 | **DECYZJA OSKARA** | nieuzywany od >=24h, ale zysk trywialny; kwestia higieny, nie RAM | (15Mi) |
| portainer | 22Mi | vhost portainer.okit.pl | Up, idle | **DECYZJA OSKARA** | UI do zarzadzania kontenerami — koliduje filozoficznie z GitOps, ale bywa przydatny awaryjnie | (22Mi) |
| mqtt-exporter-mqtt-exporter-1 | 22Mi | prom (target `mqtt-exporter` up) | Up, ale DEGRADED: "metric limit reached (2000)" w logach | **DECYZJA OSKARA** | duplikat: na hoscie biega DRUGI exporter (`/opt/mqtt-exporter/exporter.py`, root, od cze27); ktorys z dwoch jest zbedny — wymaga rozstrzygniecia ktory faktycznie serwuje :9000 (potrzebny root) | (22Mi) |
| **forgejo** | 173Mi | **origin repo GitOps** (SATURN commituje tu), vikunja OIDC, vhost | Up, aktywny | **ZOSTAW** | krytyczna infrastruktura; naprawic owner_node (rozjazd #2) | — |
| forgejo-db-1 | 31Mi | forgejo | Up | **ZOSTAW** | baza forgejo | — |
| homeassistant5 | 626Mi | ha-diag-agent (target localhost:8123), vhosty ha.kapala.org / ha-embed | Up, aktywny | **ZOSTAW** | HA "ken"; dodac do repo (rozjazd #5) | — |
| nginxproxymanager-app-1 | 234Mi | **32 vhosty** okit.pl/kapala.org (wiki, immich, vault, grafana, forgejo, ha, ...) | Up, aktywny | **ZOSTAW** | glowny reverse proxy LAN+public na PIHA; konsolidacja z NPM@VPS = osobny temat (rozjazd #4) | — |
| zigbee2mqtt | 117Mi | HA (via mosquitto hostowy), vhost zigbee.okit.pl | Up, aktywny | **ZOSTAW** | service.yaml owner=piha ✓; naprawic topology (rozjazd #15) | — |
| prom | 513Mi | grafana (datasource), vhost prometheus.okit.pl | Up, 23 targety | **ZOSTAW** | rdzen monitoringu = rola PIHA; osobno: tuning retencji moze zbic RAM | — |
| grafana | 183Mi | uzytkownik (vhost, homepage), zrodlo: prom | Up | **ZOSTAW** | rdzen monitoringu | — |
| node-exporter | 22Mi | prom (target up) | Up | **ZOSTAW** | metryki hosta | — |
| pihole-exporter | 13Mi | prom (target up) | Up | **ZOSTAW** | scrape'owany | — |
| fail2ban-prometheus-exporter | 14Mi | prom (target up) | Up | **ZOSTAW** | scrape'owany | — |
| owntracks-prometheus-exporter | 16Mi | prom (target up) | Up | **ZOSTAW** | scrape'owany; to on polluje `/api/0/last` recordera | — |
| owntracks-recorder | 3Mi | exporter + frontend + mosquitto hostowy | Up, aktywnie odpytywany | **ZOSTAW** | dziala, kosztuje grosze | — |
| own-tracks-frontend | 3Mi | uzytkownik (vhost owntracks-frontend.okit.pl) | Up | **ZOSTAW** | 3Mi | — |
| vaultwarden | 18Mi | uzytkownik (vault.okit.pl) | Up (healthy) | **ZOSTAW** | menedzer hasel — krytyczny, tani | — |
| wikijs-wiki-1 | 73Mi | uzytkownik (wiki.okit.pl, homepage) | Up, tylko joby konserwacyjne w logach | **ZOSTAW** | wiki z publicznym vhostem; ruch odczytu nie loguje sie na poziomie info — brak dowodu smierci; **nie zalezy od ES** | — |
| wikijs-db-1 | 14Mi | wikijs | Up | **ZOSTAW** | baza wiki | — |
| audiobookshelf | 27Mi | uzytkownik (audiobooks.okit.pl) | Up | **ZOSTAW** | apka uzytkowa, tania | — |
| actual-server | 19Mi | uzytkownik (budget.okit.pl) | Up | **ZOSTAW** | budzet domowy, tani | — |
| homepage | 90Mi | uzytkownik (home.okit.pl) | Up (healthy) | **ZOSTAW** | dashboard-agregator | — |
| agent-system-webui | 8Mi | telegram-bot (`CONTROL_PLANE_URL=http://webui:8080`), port 18180 | Up | **ZOSTAW** | aktywny flow zatwierdzania akcji na PIHA | — |
| agent-system-telegram-bot | 26Mi | operator (Telegram) | Up, polling co 10s | **ZOSTAW** | to JEST kanal human-in-the-loop z architektury | — |
| agent-system-runtime-materializer | 22Mi | zapisuje `/opt/homelab/world` co 10s | Up, aktywny | **ZOSTAW** | zywy komponent agent-systemu | — |
| agent-system-redis | 10Mi | runtime-materializer (`REDIS_HOST=redis`), webui | Up | **ZOSTAW** | broker agent-systemu | — |

Nota o "shadow": agent-system-\*, forgejo, zigbee2mqtt i npm MAJA definicje w
`services/` w repo (kompozycje na PIHA startowane z `/home/oskar/homelab-codex-ws/services/...`
na samym PIHA), ale brakuje ich w `hosts/piha/services.yaml` — to luka deklaracyjna,
nie brak definicji. Reszta shadow-stackow zyje w `/home/pi/<nazwa>/` i `/opt/`.

## Rekomendacje w kolejnosci (zysk / ryzyko)

1. **Stop + disable: elasticsearch + diskover** (razem, to jeden stack `/home/pi/diskover`)
   — zysk ~902Mi, ryzyko ~zero (jedyny konsument ES to diskover; indeks martwy od
   pazdziernika 2025). Przed usunieciem obrazow/wolumenow: zostawic wolumen ES na
   tydzien "na wszelki wypadek" (22MB danych; ewentualnie `elasticdump` do pliku).
2. ~~**Stop: llm-gateway** (`/opt/llm-gateway`) — zysk 15Mi + porzadek: znika port 8080
   i wiecznie failujacy target `watchtower` w prom (albo poprawic prom config w kroku 5).~~
   **WYCOFANE po review** — llm-gateway to wlasny kod Oskara, czesc systemu agentowego;
   zostaje. Patrz sekcja korekty.
3. ~~**Decyzja: migracja immich na SOLARIA** — zysk ~620Mi na PIHA. Wymaga osobnego planu
   migracji (biblioteka zdjec + postgres pgvecto-rs; reguly repo: "data paths stay in
   place at cutover" → to pelnoprawny projekt, nie quick-win). ML na GPU SOLARII to
   dodatkowy bonus jakosciowy.~~
   **WYCOFANE po review** — immich musi byc dostepny 24/7, a SOLARIA jest wlaczana
   sesyjnie. Immich zostaje na PIHA na stale.
4. **Decyzja: forgejo_dind** — jesli CI nieaktywne: stop (36Mi). Sprawdzic w UI forgejo
   czy sa zarejestrowane runnery/ostatnie buildy.
5. **Porzadki po-usuwaniu (osobny task, poza faza 1):** wyczyscic target `watchtower`
   z konfiguracji prom; rozstrzygnac duplikat mqtt-exporter (host vs kontener — kontener
   ma przepelniony limit 2000 metryk, wiec i tak wymaga naprawy); rozwazyc tuning
   retencji prom (513Mi).
6. **GitOps-yzacja tego co zostaje** (kryterium modulu): dopisac do
   `hosts/piha/services.yaml` co najmniej: forgejo(+db,+dind jesli zostaje),
   homeassistant, npm-piha, agent-system, homepage, monitoring-stack — zgodnie z
   backlogiem rozjazdow #2/#4/#5/#23.

## Ryzyka i zaleznosci (czego NIE ruszac i dlaczego)

- **forgejo (+forgejo-db-1)** — origin GitOps repo i OIDC vikunji. Awaria = brak
  push/pull dla calej floty. Nie ruszac bez planu.
- **Host-owy mosquitto (systemd, :1883)** — POZA Dockerem, latwo przeoczyc. Zaleza od
  niego: zigbee2mqtt, owntracks-recorder, mqtt-exporter, RPi-Reporter, posrednio HA.
  Zadna akcja kontenerowa go nie dotyczy, ale przy porzadkach hostowych: nie dotykac.
  (Korekta do inwentaryzacji 2026-06-30: mosquitto NA PIHA istnieje — host-level.)
- **nginxproxymanager-app-1** — pojedynczy punkt wejscia dla ~32 vhostow. Restart =
  chwilowa niedostepnosc wszystkiego z okit.pl. Konsolidacje z VPS-owym NPM planowac
  osobno.
- **homeassistant5** — target ha-diag-agenta; jego restart wygeneruje eventy/akcje w
  agent-systemie (planowane restarty robic swiadomie).
- **agent-system-\*** — zywy human-in-the-loop (Telegram). Nie mylic ze "starymi
  agent-system kontenerami" z backlogu — sa aktywne co 10s.
- **wikijs** — brak dowodu uzycia w logach, ale to charakter poziomu logowania, nie
  dowod smierci; ma publiczny vhost. Ewentualna emerytura wiki = decyzja produktowa
  Oskara, nie porzadkowa.
- **elasticsearch: kolejnosc** — najpierw stop diskover, potem ES (nie odwrotnie), zeby
  diskover nie zaczal krzyczec do martwego ES. W praktyce: `docker-compose down` calego
  stacka `/home/pi/diskover` za jednym zamachem (FAZA 2, po zgodzie).

## Obserwacje poboczne (poza zakresem, do backlogu)

- prom ma 6 targetow **down** (node-exportery: .11, .60, .40, .6, .8 oraz haos-glances) —
  szum w monitoringu, warte przegladu.
- Kontenerowy mqtt-exporter jest funkcjonalnie zdegradowany (limit 2000 metryk
  osiagniety — czesc sensorow NIE jest eksportowana do prom od dluzszego czasu).
- Na hoscie biegaja tez procesy poza Dockerem: RPi-Reporter-MQTT2HA-Daemon,
  `/opt/mqtt-exporter/exporter.py` (root) — host-level shadow, nieobjete inwentaryzacja.

## Korekta po review + egzekucja (2026-07-02)

FAZA 2 wykonana po review Oskara. Decyzje i korekty wzgledem fazy 1:

### Korekta 1: llm-gateway ZOSTAJE (wlasny kod, system agentowy)

Audyt oznaczyl llm-gateway jako "BEZPIECZNY USUN — zero konsumentow" na podstawie
chwilowego braku ruchu. **Za slabe kryterium dla wlasnego serwisu** — kontener zostaje.

Udokumentowana rola (odczyt `/opt/llm-gateway` na PIHA, 2026-07-02):

- **Co to jest**: wlasny FastAPI-router LLM Oskara (Python 3.12, fastapi+httpx+uvicorn),
  ~90 linii w `app/main.py`. Compose project `llm-gateway`, katalog `/opt/llm-gateway`
  (root, pliki z 2026-04-20/21), port `8080:8080`, `restart: unless-stopped`.
- **Co robi**: proxy/router do **Ollamy na SOLARIA** (`http://solaria:11434/api/generate`).
  Dwa endpointy: `POST /api/chat` → model `deepcoder:14b`; `POST /api/code` → model
  `deepseek-coder:latest` (z twardym promptem "return only code/command" + heurystyka
  `looks_like_shell_command`). `GET /` = healthcheck (`{"status": "gateway ok"}`).
- **Kto go wola dzis**: zaden kontener agent-system-\* nie ma env wskazujacego na
  llm-gateway (telegram-bot ma `CONTROL_PLANE_URL=http://webui:8080` — to WEWNETRZNY
  webui w sieci compose, nie llm-gateway; jego `ENABLE_LLM_FALLBACK=false` uzywa
  `OPENCLAW_BASE_URL`, nie gatewaya). Jedyny ruch: Prometheus (blednie, patrz nizej).
  To infrastruktura "na zawolanie" dla agentow, nie martwy kod.
- **Gdzie zrodlo**: `/opt/llm-gateway` NIE jest repo git. Przeszukano PIHA
  (`/opt`, `/home/pi`, `/home/oskar`, maxdepth) — **jedyna kopia `main.py` to
  `/opt/llm-gateway/app/main.py`**. W repo homelab-codex brak zrodla (tylko wzmianki
  w docs; `ollama_client.py` w korzeniu repo gada z Ollama bezposrednio, nie przez
  gateway). **Status: kod tylko na dysku PIHA — DO ZARCHIWIZOWANIA** (backlog).
- Znany bug konfiguracyjny monitoringu: Prometheus na PIHA ma target nazwany
  `watchtower` celujacy w :8080 i odpytujacy `/v1/metrics` → wieczne 404 w logach
  gatewaya (backlog).

### Korekta 2: immich ZOSTAJE NA PIHA NA STALE

Rekomendacja "przenies na SOLARIA" wykreslona: immich musi byc dostepny **24/7**
(vhosty immich.okit.pl / foty.kapala.org), a SOLARIA jest wlaczana **sesyjnie** —
nie nadaje sie na hosting always-on. Wiersze immich_\* w tabeli glownej czytac jako
**ZOSTAW** (kategoria PRZENIES niewazna).

### Korekta 3: reszta kandydatow "DECYZJA OSKARA" — ZOSTAJE

forgejo_dind, code-server, portainer, mqtt-exporter (kontener) — wszystkie zostaja
bez zmian. Duplikat mqtt-exporter i limit 2000 metryk pozostaja w backlogu jako
osobny temat.

### Egzekucja: elasticsearch + diskover UBITE (jedyne dwa)

Wykonane 2026-07-02 ~16:28 CEST na PIHA, w kolejnosci z audytu (najpierw diskover):

1. Oba kontenery = jeden compose project `diskover` (`/home/pi/diskover/docker-compose.yml`),
   restart `unless-stopped`; brak jednostek systemd i wpisow cron — jedyny mechanizm
   autostartu to same kontenery.
2. `docker stop diskover` → `docker stop elasticsearch` — czysto (Exited 0 / 143).
3. Obserwacja ~2 min: zero restart-loopow, logi wikijs ciche, nic nie krzyczy.
4. `docker compose -p diskover down` — kontenery usuniete, siec `diskover_default`
   usunieta. Po reboocie nic ich nie wskrzesi (kontenery nie istnieja).
5. **Dane ES NIE skasowane**: bind mount `/home/pi/diskover/esdata` (indeks
   `diskover-pimedia`, ~22MB) zostal na dysku nietkniety — `compose down` nie rusza
   bind mountow. Obrazy tez zostawione (ewentualne `docker image prune` = osobna decyzja).

### Zysk faktyczny

| Metryka | Przed (16:27) | Po (16:31) | Delta |
|---|---|---|---|
| RAM available | 2.8Gi | **3.8Gi** | **+1.0Gi** |
| RAM used | 5.1Gi | 4.1Gi | −1.0Gi |
| Swap used | 2.0Gi | 1.9Gi | −0.1Gi (spadek presji; pelny efekt po czasie) |
| Kontenery Up | 41 | 39 | −2 (elasticsearch, diskover) |

Kryterium modulu 0 (**>= 1.5Gi available stabilnie**) — **SPELNIONE** z zapasem
(3.8Gi), bez ruszania immich i llm-gateway. Zysk zgodny z prognoza audytu
(~902Mi rezydentne + strony ES wyswapowane).
