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:
co-authored by
Claude Opus 5
parent
d6dfe5a293
commit
a61a7b2c31
@@ -5,12 +5,20 @@ import routers.op25_controller as op25_controller
|
||||
from internal.logger import create_logger
|
||||
from internal.liquidsoap_config_utils import generate_liquid_script
|
||||
from models import IcecastConfig
|
||||
from config import settings, bind_host
|
||||
|
||||
LOGGER = create_logger(__name__)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
if settings.op25_debug_expose:
|
||||
LOGGER.warning(
|
||||
"OP25_DEBUG_EXPOSE=true — the op25 control API (:8001) and OP25's "
|
||||
"HTTP terminal (:8081) are bound to 0.0.0.0 and reachable by "
|
||||
"ANYTHING on this node's LAN with NO authentication. This is a "
|
||||
"debugging aid only; do not leave it set on a deployed node."
|
||||
)
|
||||
try:
|
||||
config = IcecastConfig(
|
||||
icecast_host=os.getenv("ICECAST_HOST", "localhost"),
|
||||
@@ -28,3 +36,12 @@ async def lifespan(app: FastAPI):
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
|
||||
app.include_router(op25_controller.create_op25_router(), prefix="/op25")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Launched directly (see Dockerfile CMD) instead of via `uvicorn main:app
|
||||
# --host ...` so the bind address is driven by OP25_DEBUG_EXPOSE (config.py)
|
||||
# rather than a value baked into the image at build time.
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run("main:app", host=bind_host(), port=8001, reload=True)
|
||||
|
||||
Reference in New Issue
Block a user