fix: move media server to 8093 — YOURLS/Apache owns 8092 on xNAS
Rebuild & Deploy / rebuild (push) Successful in 1m0s

The Unraid deployment's /media/api requests were answered by an
Apache/YOURLS stack squatting on 8092, surfacing as UI 503s; the CI
healthcheck (curl without -f) counted that 503 as healthy, so run #15
deployed green against a broken media server.

- media server port 8092 -> 8093 everywhere (server, MCP, agent, nginx,
  compose, CI, .env.example, docs, tests).
- healthchecks use curl -f in compose and rebuild.yml so HTTP error
  statuses fail deployment.
- tests default to the Unraid deployment (VOICE_WEB_URL=
  https://192.168.86.2:9178); token goes through nginx (loopback :8091
  is unreachable off-host); bind-mount-coupled tests skip on remote
  targets. AGENTS.md documents the convention and both failure modes.
This commit is contained in:
snowspeeder committed 2026-08-29 16:01:26 -04:00
1 parent d7c385301e
commit ce8fd1e046
11 files changed
+72 -28

No files matched your search

+18 -2
View File
@@ -9,7 +9,7 @@ One Docker container runs four processes via supervisord:
1. **LiveKit server** — open-source WebRTC media transport (port 7880 TCP, 7882 UDP muxed media)
2. **Voice agent** — Python LiveKit Agents pipeline: Azure STT → LLM (OpenWebUI) → Azure TTS
3. **Web frontend** — static HTML served by nginx (port 9178 by default)
4. **Media server** — FastAPI music library/player coordinator (port 8092 internal, proxied at /media/api/)
4. **Media server** — FastAPI music library/player coordinator (port 8093 internal, proxied at /media/api/)
```
Browser ──WebRTC──► LiveKit Server ──audio──► Agent
@@ -44,7 +44,7 @@ LAN access requires firewall rules: `9178/tcp` (UI + signaling), `7882/udp`
| 7880 | TCP | LiveKit HTTP/WS | internal only (proxied via nginx at /livekit/) |
| 7881 | TCP | LiveKit RTC media (TCP fallback) | LAN |
| 7882 | UDP | LiveKit RTC media (muxed) | LAN |
| 8092 | TCP | Media server (library, player state, stream proxy) | internal only (proxied via nginx at /media/api/) |
| 8093 | TCP | Media server (library, player state, stream proxy) | internal only (proxied via nginx at /media/api/) |
| 9178 | TCP | Web frontend (HTTPS) | LAN |
## Configuration
@@ -107,10 +107,23 @@ The LLM is instructed to:
## Testing
**Tests run against the Unraid deployment by default** (`https://192.168.86.2:9178`,
via `VOICE_WEB_URL` in tests/conftest.py) — that is the instance users hit
and the one CI (rebuild.yml) deploys on every push to master. The local dev
compose instance is for development only; set `VOICE_WEB_URL=https://localhost:9178`
to target it instead.
```bash
# Verify the container is running
docker compose ps
# Run the suite against the Unraid deployment (default)
python -m pytest tests/ -v -m "not slow"
# Real end-to-end YouTube Music download (network-heavy, gated)
HOPE_RUN_YTDLP_DOWNLOAD=1 python -m pytest tests/test_media.py -m slow
```
# Check all logs (single service: "voice")
docker compose logs -f voice
@@ -179,6 +192,9 @@ curl -s "https://eastus.tts.speech.microsoft.com/cognitiveservices/v1" \
- **External stream URLs are proxied, never played directly.** An `http://` radio URL would be blocked as mixed content on the HTTPS UI, so `GET /media/api/stream/{id}` re-serves the upstream over HTTPS with Range passthrough. Downloaded tracks on that endpoint just redirect to `/media/files/`.
- **Player state is per-room desired state, reconciled by the browser.** The media server never streams to anything; it records what SHOULD play per LiveKit room and the browser polls and reports back. Track ids for YouTube tracks are the video ids (dedupe by video_id); stream tracks get `s<uuid>`.
- **Anonymous yt-dlp first, cookies when flaky.** Search (`ytsearch`) and downloads work anonymously from a residential IP; if YouTube starts bot-blocking, drop a cookies.txt into `./media/cookies.txt` and set `YTDLP_COOKIES=/data/media/cookies.txt`.
- **Never hard-require container env in supervisord.** `%(ENV_X)s` expansion aborts the whole supervisord config when the var is missing, taking every program down (this silently killed the run-151 deploy). Programs with safe in-code defaults (media server) must inherit the container env instead of listing it.
- **Healthchecks must use `curl -f`.** Without it, any HTTP response — including a 503 from a squatter — counts as healthy. Run #15 deployed "healthy" against a broken media port this way.
- **Port 8092 is taken on xNAS.** An Apache/YOURLS stack occupies 8092 on the Unraid host; the media server uses 8093. Before picking a new internal port, probe the Unraid deployment host, not just the dev box.
## Git