Summary
PlugNPiN logs in to the Pi-hole v6 API but never logs out, so every reconcile leaks a server-side session. Over time these fill Pi-hole's API session seats (webserver.api.max_sessions, default 16). Once full, Pi-hole returns 429 {"error":{"key":"api_seats_exceeded"}} to every API client — the Pi-hole web UI and any other integration, not just PlugNPiN.
In my homelab this silently broke an unrelated Home Assistant Pi-hole integration for several days: its credentials were correct, but it could never obtain a session seat because PlugNPiN was holding them all.
Version: v0.10.0 (ghcr.io/deepspace2/plugnpin:latest)
Root cause
In pkg/clients/pihole/pihole.go:
Login() performs POST /api/auth and stores the returned sid, but there is no logout anywhere — nothing calls DELETE /api/auth.
refreshAuth() simply calls Login() again on a 401, which mints a new session and abandons the previous one rather than reusing or closing it.
Because a fresh Client logs in on each run, and the periodic RUN_INTERVAL sync plus every container start/stop event triggers a run, a new session is created repeatedly. Each one occupies a seat until it expires after webserver.session.timeout (default 30 min).
Impact / evidence
On a moderately active Docker host with default max_sessions=16, seats fill within minutes. GET /api/auth/sessions shows multiple lingering Go-http-client/1.1 sessions originating from PlugNPiN, and FTL.log repeats:
WARNING: No free API seats available (webserver.api.max_sessions = 16), not authenticating client
WARNING: API: API seats exceeded (key: api_seats_exceeded, hint: increase webserver.api.max_sessions)
All API clients are then locked out until sessions expire.
Suggested fix
Either of:
- Call
DELETE /api/auth (logout) once PlugNPiN finishes its config changes in a run, so the seat is released immediately, or
- Keep and reuse a single long-lived session across runs (validate/reuse
sid, and on 401 log out the stale session before logging in again) instead of abandoning sessions.
Pi-hole's API explicitly recommends deleting the session when done, precisely to avoid seat exhaustion.
Workaround
Raise webserver.api.max_sessions on the Pi-hole side (e.g. via FTLCONF_webserver_api_max_sessions), but that only delays exhaustion rather than fixing the leak.
Happy to test a fix or open a PR if helpful — thanks for the great tool!
Summary
PlugNPiN logs in to the Pi-hole v6 API but never logs out, so every reconcile leaks a server-side session. Over time these fill Pi-hole's API session seats (
webserver.api.max_sessions, default 16). Once full, Pi-hole returns429 {"error":{"key":"api_seats_exceeded"}}to every API client — the Pi-hole web UI and any other integration, not just PlugNPiN.In my homelab this silently broke an unrelated Home Assistant Pi-hole integration for several days: its credentials were correct, but it could never obtain a session seat because PlugNPiN was holding them all.
Version: v0.10.0 (
ghcr.io/deepspace2/plugnpin:latest)Root cause
In
pkg/clients/pihole/pihole.go:Login()performsPOST /api/authand stores the returnedsid, but there is no logout anywhere — nothing callsDELETE /api/auth.refreshAuth()simply callsLogin()again on a401, which mints a new session and abandons the previous one rather than reusing or closing it.Because a fresh
Clientlogs in on each run, and the periodicRUN_INTERVALsync plus every container start/stop event triggers a run, a new session is created repeatedly. Each one occupies a seat until it expires afterwebserver.session.timeout(default 30 min).Impact / evidence
On a moderately active Docker host with default
max_sessions=16, seats fill within minutes.GET /api/auth/sessionsshows multiple lingeringGo-http-client/1.1sessions originating from PlugNPiN, andFTL.logrepeats:All API clients are then locked out until sessions expire.
Suggested fix
Either of:
DELETE /api/auth(logout) once PlugNPiN finishes its config changes in a run, so the seat is released immediately, orsid, and on401log out the stale session before logging in again) instead of abandoning sessions.Pi-hole's API explicitly recommends deleting the session when done, precisely to avoid seat exhaustion.
Workaround
Raise
webserver.api.max_sessionson the Pi-hole side (e.g. viaFTLCONF_webserver_api_max_sessions), but that only delays exhaustion rather than fixing the leak.Happy to test a fix or open a PR if helpful — thanks for the great tool!