Skip to content

docs(docker-compose): add deployment cookbook (6 recipes)#594

Open
IrosTheBeggar wants to merge 2 commits into
masterfrom
docs/docker-compose-cookbook
Open

docs(docker-compose): add deployment cookbook (6 recipes)#594
IrosTheBeggar wants to merge 2 commits into
masterfrom
docs/docker-compose-cookbook

Conversation

@IrosTheBeggar

@IrosTheBeggar IrosTheBeggar commented May 15, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a Docker Compose cookbook under docs/docker-compose/ — six drop-in recipes plus an index README, and a "Docker Compose recipes" section in the project README linking to each.

Recipe Description
default/ streaming-only, single linuxserver/mstream container
with-mpd/ server-side audio playback via sidecar MPD over a shared Unix socket. Music dirs mounted at the same path in both containers (the mpd adapter sends absolute file:// URIs with no rewriting). autoBootServerAudio=false deliberately prefers MPD, so no config override is needed
with-transmission/ mStream + Transmission daemon. Completed downloads become library-visible via a shared volume + mStream's RPC-driven path auto-detection. mStream supports three torrent clients (Transmission, qBittorrent, Deluge); the README explains why Transmission is recommended
ssl-nginx/ nginx reverse proxy + acme.sh wildcard cert via Cloudflare DNS-01. Domain parameterized via .env; adapted from a working personal-infra setup
dev/ source bind-mount with node --watch for hot reload. npm ci (not npm install) so the bind-mounted lockfile isn't rewritten
dev-everything/ dev/ + DLNA + Subsonic + rust-server-audio + ALSA /dev/snd passthrough preconfigured. Linux host only

Audit findings (this revision)

Audited every recipe against the codebase config schema and the linuxserver image env contracts. Notable:

  • with-transmission RPC whitelist (critical fix). A fresh Transmission only whitelists 127.0.0.1 and guards against DNS rebinding, so it would 403 every RPC call from mStream — which connects across the Docker network (private-range IP, Host header transmission). The recipe now sets WHITELIST=127.0.0.1,10.*.*.*,172.*.*.*,192.168.*.* and HOST_WHITELIST=transmission (env contract confirmed from linuxserver's docs). USER/PASS auth remains the real security boundary.
  • with-mpd socket + readiness (documented). New README covers cross-container Unix-socket permission alignment (the most likely runtime failure) and the MPD-readiness startup race. Verified that autoBootServerAudio=false prefers MPD, so the recipe works with no config override.
  • Image pinning (noted). Recipes track :latest by linuxserver convention; cookbook README notes pinning a digest/tag for reproducible production.
  • Verified OK, no change: musl rust-parser auto-selects on the Alpine linuxserver image; dev-everything correctly pairs a glibc base with the glibc rust-server-audio binary; ssl-nginx parking + renewal logic is sound.

Test plan

Static validation (Docker engine was unavailable for live runs this revision): docker compose config passes for all six recipes; the transmission whitelist values render intact through interpolation.

Verified live in an earlier revision on Docker Desktop:

  • default/ → HTTP 200; rust-parser picks the musl variant inside the Alpine image
  • dev/ → boots after npm ci + migrations; HTTP 200
  • ssl-nginx/ image builds; entrypoint env-guard + sed templating correct
  • dev-everything/ image builds (libasound2 + alsa-utils + mpv)

Needs a Linux host with a real audio device / Cloudflare zone — not testable from Docker Desktop on Windows:

  • with-mpd/ and dev-everything/ end-to-end (need /dev/snd)
  • with-transmission/ end-to-end RPC (validate the whitelist fix against a live daemon)
  • ssl-nginx/ real Let's Encrypt issuance against a Cloudflare-managed zone

🤖 Generated with Claude Code

@IrosTheBeggar IrosTheBeggar force-pushed the docs/docker-compose-cookbook branch 2 times, most recently from 088c3aa to 7ef07f3 Compare May 19, 2026 17:42
IrosTheBeggar and others added 2 commits May 29, 2026 19:09
Five drop-in compose.yml recipes under docs/docker-compose/ for common
mStream deployments:

- default/         streaming-only, single linuxserver/mstream container
- with-mpd/        server-side audio via sidecar MPD over a shared Unix
                   socket; music dirs mounted at the same path in both
                   containers (mStream's mpd adapter sends absolute
                   file:// URIs with no path rewriting)
- ssl-nginx/       nginx reverse proxy + acme.sh wildcard cert via
                   Cloudflare DNS-01. Domain parameterized via .env;
                   adapted from a working personal-infra setup
- dev/             source bind-mount with node --watch for hot reload
- dev-everything/  dev/ with DLNA, Subsonic, rust-server-audio, and
                   ALSA /dev/snd passthrough preconfigured

README.md gets a new "Docker Compose recipes" subsection under
"Installing mStream" linking to the cookbook and each recipe.

Smoke-testing against a real Docker daemon also surfaced two gitignore
gaps closed here: save/db/* (the .rescan-pending marker leaked through
the *.db-only patterns) and docs/docker-compose/*/{config,mstream-config,
music}/ + .env (runtime artifacts from running the recipes that
shouldn't be committed back to the repo).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the mStream + Transmission recipe (recreating work lost when a
worktree was torn down) and folds in fixes surfaced by auditing all
recipes against the codebase and the linuxserver image contracts.

with-transmission/:
- compose.yml runs linuxserver/transmission beside mStream, sharing a
  ./downloads volume (rw for the daemon, ro for mStream) so completed
  torrents become library-visible with no copying.
- CRITICAL fix vs the first draft: set WHITELIST + HOST_WHITELIST. A
  fresh Transmission only whitelists 127.0.0.1 and guards against DNS
  rebinding, so it would 403 every RPC call from mStream — which
  connects across the Docker network (a private-range IP, Host header
  `transmission`). WHITELIST widens rpc-whitelist to the private ranges
  Docker uses; HOST_WHITELIST allows the service-name Host. USER/PASS
  auth remains the real security boundary. (Env-var contract confirmed
  from linuxserver's published docs.)
- Transmission WebUI bound to 127.0.0.1 since .env ships a placeholder
  password; peer port 51413 tcp+udp exposed.

with-mpd/README.md (new): documents two audit findings — cross-container
Unix-socket permission alignment (the most likely runtime failure) and
the MPD-readiness startup race. Also records the verified boot-flow fact
that autoBootServerAudio=false deliberately prefers MPD, so the recipe
needs no config override.

Cross-cutting:
- .gitignore: ignore docs/docker-compose/*/downloads/ and
  */transmission-config/ (recipe runtime artifacts — downloaded media
  and daemon state must not be committed).
- Cookbook README: note that recipes track :latest by linuxserver
  convention and to pin a digest/tag for reproducible production.
- README.md + cookbook index: list with-transmission; note the
  three-client support with Transmission recommended.

Audit also verified (no change needed): musl rust-parser auto-selects on
the Alpine linuxserver image; dev-everything correctly pairs a glibc
base with the glibc rust-server-audio binary; ssl-nginx entrypoint
parking + renewal logic is sound.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@IrosTheBeggar IrosTheBeggar force-pushed the docs/docker-compose-cookbook branch from 7ef07f3 to 6798104 Compare May 29, 2026 23:23
@IrosTheBeggar IrosTheBeggar changed the title docs(docker-compose): add cookbook with 5 deployment recipes docs(docker-compose): add deployment cookbook (6 recipes) May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant