Bind OP25 control API and terminal to loopback by default

Both :8001 (FastAPI control API) and :8081 (OP25's HTTP terminal) listened on
0.0.0.0 with no authentication, on a container that is privileged with /dev
mounted and network_mode: host. Nodes get deployed to third-party sites, so
that exposed start/stop/retune to anyone on the host's LAN.

All three containers share the host network namespace, so edge-node still
reaches both over 127.0.0.1 unchanged. OP25_DEBUG_EXPOSE=true restores the
old 0.0.0.0 binding and logs a loud warning; it is off by default.

Confirmed against boatbod/op25 gr310 that the terminal's http:<host>:<port>
string is honoured as a real bind address (http_server.py splits it and hands
the host to create_server), so no flag was invented.

Also reorder models.py so IcecastConfig precedes ConfigGenerator, which
annotates a field with it. That only worked because python:slim-trixie is
currently Python 3.14, where PEP 649 defers annotation evaluation; on 3.13 or
earlier the same file is a hard NameError at import.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Logan Cusano
2026-08-16 09:33:25 -04:00
co-authored by Claude Opus 5
parent d6dfe5a293
commit a61a7b2c31
6 changed files with 81 additions and 11 deletions
+5
View File
@@ -8,6 +8,11 @@ services:
ICECAST_SOURCE_PASSWORD: ${ICECAST_SOURCE_PASSWORD:-hackme}
ICECAST_ADMIN_PASSWORD: ${ICECAST_ADMIN_PASSWORD:-admin}
# No `ports:` here — network_mode: host makes it a no-op either way. The
# control API (:8001) and OP25's HTTP terminal (:8081) are unauthenticated,
# so they bind 127.0.0.1 by default (see OP25_DEBUG_EXPOSE in .env.example)
# rather than being exposed. edge-node still reaches both over localhost
# because it shares this host network namespace.
op25:
image: ${IMAGE_REGISTRY:-git.vpn.cusano.net}/${DOCKER_ORG:-logan}/${DOCKER_REPO:-node-26}/op25-client:stable
build: ./op25-container