# Private station mode SUB/WAVE is public by default: anyone with the address can open the player and anyone who guesses `/stream.mp3` can listen. If you'd rather keep your station to yourself (issue #478), **admin → Settings → Station → Privacy** gives you two independent locks. Both locks share **one station password**, set in the same place. Turning on either lock requires a password first. ## Private player (UI lock) Swaps the public web pages (`/`, `/listen`) for a password prompt. Type the station password and the player appears as normal; the browser remembers it. `/admin` and `/onboarding` keep working (the admin console keeps its own separate sign-in). Applies live — no restart. This only hides the interface. The now-playing JSON endpoints stay public (the player and admin dash rely on them), and the stream URL still works — for actual gating you want the stream password too. ## Stream password (the real boundary) Turns on Icecast listener authentication for every mount (`/stream.mp3`, `/stream.opus`, `/stream.flac`, `/stream.aac`). The same station password, for all listeners — Icecast only speaks HTTP basic auth, so there are no per-user accounts (and no OIDC; that's not viable for a live audio stream). How it works under the hood: the controller writes `state/icecast_listener_auth.txt`, and on the next broadcast restart the Icecast config gains per-mount `` blocks pointing at the controller's `POST /listener-auth`. Icecast asks the controller on every listener connect, so: - **Enabling/disabling needs a mixer restart** (the admin UI tells you, same as the Opus/AAC toggles). - **Password changes apply live** — the controller validates each connect against the current settings. - **If the controller is down, new listeners can't connect** (fail closed); already-connected listeners keep playing. > **Running your own reverse proxy?** `POST /listener-auth` answers 200 or 401 > depending on whether the submitted password is right, which makes it a > password oracle for anyone who can reach it — and it's the *same* password > that guards the private player. Icecast always calls the controller directly > over the internal network, so the endpoint never needs to be reachable from > the internet. The bundled Caddy config returns 404 for > `/api/listener-auth`; if you use `docker-compose.byo.yml` with your own > Traefik/nginx/Caddy, block that path too. The controller slows repeated > failed attempts as a backstop (correct passwords are never delayed), but > not exposing the path at all is the real protection. ### Tuning in with a password - **Web player** — asks for the password once and remembers it in the browser. If the private player is on too, the single prompt unlocks both the interface and the audio. Under the hood it rides a `?auth=PASSWORD` token on the stream URL (browsers can't attach basic auth to an `