Skip to content

Pi-hole v6 API sessions are never closed (no logout) — exhausts webserver.api.max_sessions and 429s all clients #50

Description

@jusseppe88

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:

  1. Call DELETE /api/auth (logout) once PlugNPiN finishes its config changes in a run, so the seat is released immediately, or
  2. 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!

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions