icecast: its passwords are a file the mesh writes, not the image's environment #146

Merged
mesh-admin merged 1 commits from feat/icecast-for-ace into main 2026-09-30 14:38:17 +00:00
Contributor

Converts icecast for ace's migration (HAL -> nox-mesh). Preparation only; nothing assigned.

  • Passwords: ${secret:source|admin|relay} rendered into a mesh-written icecast.xml (root 0600, mounted :ro at /etc/icecast.xml). icecast reads it as root then drops to uid 100. The secrets-in-environment exemption and server.env are removed (ADR 0086).
  • Directories placed: state (config, secrets, route binding) and logs (owner 100:101). The image declares VOLUME /var/log/icecast, so without the logs dir every container got a new anonymous volume.
  • Module network icecast: the sidecar reaches http://icecast:8000 rather than assuming machine port 8000 on host networking.
  • stream is routed (requires route, label icecast), matching how HAL serves icecast..
  • Image pin unchanged: it is the digest ace runs (icecast 2.4.4).

Verified: catalogue tests (MESH_CATALOGUE=this tree) pass. A throwaway container of the pinned image with the rendered file (dummy secrets) ran as the icecast user. status-json returned 200; admin returned 401 without credentials and 200 with them. A source PUT mounted and a listener received the stream. A wrong source password got 401. Logs were written into the uid-100 dir.

Known gap: <hostname>, <location>, <admin> and <admin-user> are XML and assignments merge only into JSON, so they keep neutral defaults. Playlists (.m3u) therefore say http://localhost:8000/... ; on ace today they say http://icecast.zurag.be:8000/..., which is not reachable from outside either.

Converts icecast for ace's migration (HAL -> nox-mesh). Preparation only; nothing assigned. - Passwords: `${secret:source|admin|relay}` rendered into a mesh-written `icecast.xml` (root 0600, mounted :ro at /etc/icecast.xml). icecast reads it as root then drops to uid 100. The `secrets-in-environment` exemption and `server.env` are removed (ADR 0086). - Directories placed: `state` (config, secrets, route binding) and `logs` (owner 100:101). The image declares VOLUME /var/log/icecast, so without the logs dir every container got a new anonymous volume. - Module network `icecast`: the sidecar reaches `http://icecast:8000` rather than assuming machine port 8000 on host networking. - `stream` is routed (`requires route`, label `icecast`), matching how HAL serves icecast.<domain>. - Image pin unchanged: it is the digest ace runs (icecast 2.4.4). Verified: catalogue tests (MESH_CATALOGUE=this tree) pass. A throwaway container of the pinned image with the rendered file (dummy secrets) ran as the icecast user. status-json returned 200; admin returned 401 without credentials and 200 with them. A source PUT mounted and a listener received the stream. A wrong source password got 401. Logs were written into the uid-100 dir. Known gap: `<hostname>`, `<location>`, `<admin>` and `<admin-user>` are XML and assignments merge only into JSON, so they keep neutral defaults. Playlists (.m3u) therefore say http://localhost:8000/... ; on ace today they say http://icecast.zurag.be:8000/..., which is not reachable from outside either.
mesh-admin added 1 commit 2026-09-29 21:39:48 +00:00
The image seds ICECAST_*_PASSWORD from the environment into /etc/icecast.xml;
ADR 0086 wants secrets as files. icecast starts as root, reads its config, then
drops to uid 100, so a root-owned 0600 icecast.xml rendered with ${secret:...}
and mounted read-only works and the entrypoint's seds never fire (no env set).
The "secrets-in-environment" exemption and server.env are gone.

Also: directories are placed (state, logs owned 100:101 so the image's VOLUME
/var/log/icecast is not an anonymous volume per container, as HAL learned);
the server and sidecar share a module network, so the sidecar reaches
http://icecast:8000 instead of assuming machine port 8000 on the host; the
stream endpoint is routed (label "icecast"), as HAL served it via traefik.
Secrets remain mesh-vault grants (requires secret), now under ${dir:state}.

Verified: catalogue tests with MESH_CATALOGUE pointed at this tree; a
throwaway container of the pinned digest (the one ace runs) with the rendered
file (dummy secrets, root 0600, :ro): runs as icecast, status-json 200,
admin 401 without / 200 with the admin secret, a source PUT with the source
secret mounts, a listener receives it, a wrong source password gets 401, logs
land in the uid-100 directory.
mesh-admin merged commit 9c97a8a134 into main 2026-09-30 14:38:14 +00:00
mesh-admin deleted branch feat/icecast-for-ace 2026-09-30 14:38:15 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-catalog#146