Files
ROMFASTSQL/proxmox/cluster/incidents/2026-07-31-lxc110-dns-tailscale-oom.md
Claude Agent a6b26ba23d docs(lxc102): OOM cronic pe 4GB -> 12GB + refresh tabel resurse cluster
Alerta "OOM x2 on pvemini" (09:36) arata procese mici ucise (dbus-daemon,
oom_score_adj:200), dar mesajul kernel dadea containerul real:
oom_memcg=/lxc/102. OOM local containerului, nu presiune de host - pvemini
avea 24Gi disponibili si zram functional.

Baseline masurat cu ZERO sandbox-uri active: ~1.9GB (sbx 863M + claude 317M +
VS Code Remote 450M + docker/tailscale/portainer 205M). Un sandbox real mai
adauga ~1.9GB (containerd-shim) -> plafonul de 4GB era depasit sistematic.
Contoare cumulate: oom_kill 24, 9279 depasiri memory.high, memory.peak fix pe
limita, swap 510/512 epuizat.

Verificat explicit ca sbx NU are memory leak: RSS urca la ~863M la pornire si
se plafoneaza (esantionat la 10s timp de un minut).

Fix: pct set 102 --memory 12288 --swap 4096 (live, fara restart).

Tabelul de resurse din cluster/README.md era vechi (102 aparea ca "coolify
stopped", lipseau 110 si 171, RAM gresit peste tot) - regenerat din pvesh.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 10:23:10 +00:00

8.6 KiB

Incident 2026-07-31 — LXC 110 (moltbot): DNS mort după logout Tailscale + OOM

Severity: Medium (serviciu echo-core indisponibil ~8 min; fără pierdere de date) Detected: 2026-07-31 ~09:28 EEST (user — „nu mai răspunde la SSH, nu mai merge echo") Resolved: 2026-07-31 09:34 EEST (fix DNS) + 09:5x EEST (zram pe pve1) Author: Claude Code (mmarius28@gmail.com)


TL;DR — lanțul cauzal

  1. 06:26 UTC — LXC 110 se oprește după 65 zile uptime. În log-urile de shutdown: user-1000.slice: A process of this unit has been killed by the OOM killer. OOM local containerului (plafon 8GB), NU la nivel de host — pve1 nu a avut niciun OOM în 30 de zile și avea 18GB available.
  2. 06:26:59 — la revenire, tailscaled generează nodekey nou și rămâne delogat (machineAuthorized=false, authURL=true).
  3. DNS moare complet. LXC 110 nu avea nameserver în pct config, deci moștenea /etc/resolv.conf de la host-ul pve1 — iar acolo fișierul e scris de Tailscale și conținea doar MagicDNS (100.100.100.100 + fd7a:115c:a1e0::53). Cu Tailscale delogat, resolverul devine inaccesibil.
  4. echo-core.service intră în crash-loop cu telegram.error.TimedOut (restart counter ajunsese la 11).

Capcana de diagnostic: rețeaua L3 era perfect funcțională — ping 8.8.8.8 OK, gateway OK, rută OK. Doar rezoluția numelor pica. Ușor de interpretat greșit ca „bot stricat" sau „internet căzut".

SSH-ul „care nu răspundea" era doar containerul în curs de repornire — la verificare funcționa deja normal.


Diagnostic — comenzi cheie

# NU te lua după ping — verifică întâi rezoluția
getent hosts api.telegram.org        # gol => DNS mort
cat /etc/resolv.conf                 # doar 100.100.100.100 => depinde de Tailscale
ping -c2 8.8.8.8                     # OK => L3 e sănătos, problema e DNS
tailscale status                     # "Logged out."

# serviciile echo rulează ca user systemd (user moltbot)
su - moltbot -c 'XDG_RUNTIME_DIR=/run/user/1000 systemctl --user status echo-core'

Fix 1 — DNS explicit (aplicat)

# pe pve1
pct set 110 --nameserver '10.0.20.1 1.1.1.1'    # persistent, aplicat la următorul start

# live, fără restart de container (backup: /etc/resolv.conf.bak-2026-07-31)
printf '# --- BEGIN PVE ---\nnameserver 10.0.20.1\nnameserver 1.1.1.1\n# --- END PVE ---\n' \
  > /etc/resolv.conf

su - moltbot -c 'XDG_RUNTIME_DIR=/run/user/1000 systemctl --user restart echo-core'

Rezultat: Telegram getUpdates → 200 OK, Discord online, 0 restarturi ulterioare.

Expunere similară: orice alt LXC de pe pve1 fără nameserver explicit moștenește același resolv.conf Tailscale și va pica identic la un logout Tailscale.

Fix 2 — zram swap pe pve1 (aplicat)

pct config 110 avea swap: 4096, dar în container free -h arăta Swap: 0B. Cauza: limita cgroup exista corect pe host…

/sys/fs/cgroup/lxc/110/memory.max          = 8589934592   (8 GB)
/sys/fs/cgroup/lxc/110/memory.swap.max     = 4294967296   (4 GB)  <- plafon OK
/sys/fs/cgroup/lxc/110/memory.swap.current = 0                    <- nimic nu-l umple

…dar pve1 nu avea niciun swap (swapon --show gol, nimic în /etc/fstab). Limita cgroup e doar un plafon peste swap-ul host-ului; fără backing store fizic, kernelul nu are unde scrie paginile. Root-ul pve1 e pe ZFS (rpool/ROOT/pve-1), deci swapfile e exclus (risc de deadlock) — aceeași situație rezolvată pe pvemini în 2026-06-24.

# pe pve1 (host) — identic cu pvemini
apt install -y zram-tools
cat > /etc/default/zramswap <<'EOF'
# zram swap config - host buffer pentru spike-uri OOM (ex: LXC 110 moltbot)
ALGO=zstd
SIZE=8192
PRIORITY=100
EOF
systemctl restart zramswap.service    # enabled persistent la boot
swapon --show                         # /dev/zram0  8G  prio 100

Verificare în container — cei 4GB au acum backing real:

free -h  →  Swap: 4.0Gi

Vârfurile tranzitorii fac swap-out în loc de OOM-kill instant.


Rămas de făcut (necesită acțiune user)

Item Detalii
Re-auth Tailscale în LXC 110 Necesită login interactiv din browser (tailscale up regenerează URL-ul). Până atunci IP-ul 100.120.119.70 nu răspunde; accesul pe 10.0.20.173 e normal.
Bridge WhatsApp deconectat {"connected":false,"qr":null} pe 127.0.0.1:8098. Discord + Telegram merg. Probabil necesită re-pairing prin QR.
Monitorizare De urmărit dacă MemoryHigh pe TTS chiar oprește recurența — următorul episod ar trebui să se manifeste ca throttling, nu ca kill.

OOM-ul NU e izolat — istoric recurent

Verificarea jurnalului complet (nu doar boot-ul curent) arată că OOM-ul din 31 iulie e al cincilea episod, nu un accident:

Apr 25 08:34:53  echo-core.service: Failed with result 'oom-kill'
May 28 14:09:36  echo-core.service: Failed with result 'oom-kill'   <- 1.4G memory peak
May 28 14:15:44  echo-core.service: Failed with result 'oom-kill'
May 28 14:18:13  echo-core.service: Failed with result 'oom-kill'
May 28 14:18:13  supertonic-tts.service: Failed with result 'oom-kill'
Jul 31 06:26:22  user-1000.slice: killed by the OOM killer  -> reboot

Pe 28 mai: 4 kill-uri în 9 minute, echo-core luând cu el și supertonic-tts. Log-ul de atunci confirmă lipsa swap-ului: 1.4G memory peak, 0B memory swap peak — fără backing store, kernelul trece direct la kill.

Cauza structurală: servicii fără limite

Cele 7 servicii user systemd (echo-core, echo-taskboard, echo-whatsapp-bridge, pocket-tts, supertonic-tts, romfast-website, dbus) rulează toate fără plafon:

MemoryMax=infinity
MemoryHigh=infinity

Deci orice serviciu poate consuma singur toți cei 8 GB ai containerului, iar OOM killer-ul alege victime după oom_score_adj — de unde procesele mici ucise aiurea (dbus-daemon, sd-pam) care fac diagnosticul derutant. Stiva TTS e cea mai grea: pocket-tts ~945 MB + supertonic ~500 MB, în repaus.

Fix 3 — MemoryHigh pe stiva TTS (aplicat)

MemoryHigh face throttling + reclaim în loc de kill, deci serviciul degradează elegant sub presiune. MemoryMax e plasa de siguranță: izolează un eventual kill în interiorul serviciului, în loc să lase OOM killer-ul să aleagă victime aleatorii în tot containerul.

Drop-in-uri în ~/.config/systemd/user/<serviciu>.service.d/limits.conf (user moltbot):

Serviciu RSS repaus MemoryHigh MemoryMax
pocket-tts ~945 MB 1536M 2G
supertonic-tts ~500 MB 1024M 1536M
su - moltbot
mkdir -p ~/.config/systemd/user/pocket-tts.service.d
cat > ~/.config/systemd/user/pocket-tts.service.d/limits.conf <<'EOF'
[Service]
MemoryHigh=1536M
MemoryMax=2G
EOF
export XDG_RUNTIME_DIR=/run/user/1000
systemctl --user daemon-reload
systemctl --user restart pocket-tts supertonic-tts
systemctl --user show pocket-tts -p MemoryHigh,MemoryMax,MemoryCurrent   # verificare

Verificat post-aplicare: ambele active/running, porturile 7788 + 7789 deschise, echo-core neîntrerupt. Consum după restart: pocket-tts 773M, supertonic 463M.

Restul serviciilor (echo-core, echo-taskboard, echo-whatsapp-bridge, romfast-website) au rămas fără limite — TTS-ul e consumatorul dominant. De reevaluat dacă apar OOM-uri cu altă victimă.

Prevenție

  • zram pe pve1 amortizează spike-urile (aplicat) — dar singur e paliativ: fără limite pe servicii, swap-ul doar întârzie kill-ul. Fixul de fond e MemoryHigh pe TTS (aplicat).
  • DNS explicit pe LXC 110 elimină dependența de Tailscale (aplicat).
  • De evaluat același --nameserver pentru celelalte LXC-uri de pe pve1.
  • Alertare pe NRestarts la serviciile user systemd ar fi prins crash-loop-ul mai devreme decât raportarea manuală.

Legături: ../../lxc110-moltbot/README.md · ../../lxc171-claude-agent/README.md (secțiunea „Memorie & OOM" — incidentul zram pvemini 2026-06-24)

Al doilea OOM în aceeași zi, alt container, alt mecanism: LXC 102 (docker/sbx) a generat alertă „OOM x2 on pvemini" la 09:36. Acolo host-ul avea swap funcțional — pur și simplu containerul era subdimensionat (4GB pentru sbx + VS Code + Claude). Ridicat la 12GB. Detalii: ../../lxc102-docker/README.md → „Memorie".

Numitorul comun al ambelor cazuri: OOM local unui cgroup de container, deși host-ul avea marjă largă, plus victime alese după oom_score_adj (procese mici, irelevante) care ascund adevăratul consumator. Primul reflex: citește oom_memcg= din mesajul kernel.