Docker Setup
Run Music Hub as an always-on server on a NAS, Linux box, seedbox, or Docker Desktop. You get the web UI, library database, and mobile pairing — not the Electron desktop app.
Docker is available now and still treated as a testing channel while more NAS/server setups are covered. If something breaks, tell us on Telegram (opens in a new tab) or WhatsApp (opens in a new tab).
1. Download compose
mkdir -p music-hub
cd music-hub
curl -O https://music-hub.gordo.design/docker-compose.ymlThat file publishes:
- TCP
38472— web UI + API - UDP
42424— Personal Private network (Iroh) for the phone off Wi‑Fi
2. Point it at your music
Edit docker-compose.yml and uncomment/set a music mount plus registration:
volumes:
- ./data:/data
- /path/to/your/music:/music:ro # 1) host folder visible inside the container
environment:
- MUSIC_FOLDER=/music # 2) Music Hub scans that container pathExample on a Linux NAS:
- /volume1/music:/music:roBoth steps matter. A volume alone does not add the folder to the library. Inside Music Hub always use the container path (/music), never the host path.
You can skip MUSIC_FOLDER and add /music later in Settings → Folders.
Add more than one music folder
Mount every host folder at its own container path, then list all of those
container paths in MUSIC_FOLDER, separated by ::
volumes:
- ./data:/data
- /volume1/music:/music:ro
- /volume1/samples:/samples:ro
- /volume2/archive:/archive:ro
environment:
- MUSIC_FOLDER=/music:/samples:/archiveAfter the container starts, Music Hub registers the three paths as three
library roots. They appear independently in Settings → Folders and in the
Folders view, and tracks keep their corresponding folder source. You can
add another root later from Settings → Folders by using its container path,
for example /samples2; mounting the volume alone is not enough.
Use the container paths (/music, /samples, /archive) everywhere inside
Music Hub. The host paths (/volume1/music, /volume1/samples, etc.) are only
used on the Docker host and are not valid paths in the Music Hub UI.
3. Tell phones your Wi‑Fi IP
Phones cannot use localhost or Docker’s internal 172.x address. Set the host’s LAN IP before starting.
Mac (Wi‑Fi):
ipconfig getifaddr en0
# example → 192.168.1.40Linux:
hostname -I | awk '{print $1}'Create a .env next to docker-compose.yml:
MUSIC_HUB_ADVERTISED_LOCAL_IP=192.168.1.40Or export it in the shell:
export MUSIC_HUB_ADVERTISED_LOCAL_IP=192.168.1.40Update this when you change Wi‑Fi networks.
4. Start
docker compose up -d
docker compose psOpen the UI on the LAN IP (best for pairing QR):
http://192.168.1.40:38472On the same machine only, http://localhost:38472 also works.
5. Pair the phone (same Wi‑Fi first)
- Open the web UI on the LAN IP.
- Go to Settings → Pairing.
- Arm pairing if needed.
- Scan the QR with the Music Hub mobile app.
- Keep the phone on the same Wi‑Fi for the first connect.
If the QR still shows localhost or 172.x.x.x, fix MUSIC_HUB_ADVERTISED_LOCAL_IP, recreate the container (docker compose up -d), and scan a fresh QR.
6. Listen away from home (Personal Private network)
No Tailscale. No port-forward. Personal Private network (Iroh) is built into the server.
- License the hub if remote access is gated (paid desktop license).
- Settings → Remote → leave Personal Private network on.
- Pair once on Wi‑Fi (step 5).
- Leave home Wi‑Fi and play — the phone should move to the private network route.
Compose must keep 42424:42424/udp open (already in the downloaded file). The container needs outbound internet for relay/direct connectivity.
Updating
docker compose pull
docker compose up -dBack up ./data before major updates. Migrations run on startup.
Data layout
./data/ ← keep on SSD
music.db
music.db-wal
config.json
logs/
/music/ ← your library (volume mount)Music files stay on the mounted folder; they are not copied into the image.
Useful environment variables
| Variable | Purpose |
|---|---|
MUSIC_HUB_ADVERTISED_LOCAL_IP | Host Wi‑Fi IP for QR + Iroh dial (192.168.1.40) |
MUSIC_FOLDER | Container path(s) to register on boot (/music) |
HUB_NAME | Optional display name |
MUSIC_HUB_TRUSTED_ORIGINS | LAN subnets trusted for admin (default covers typical 192.168 / 172.16) |
NAS notes
Same model on Synology, Unraid, and TrueNAS:
- Persistent folder for
/data(SSD if you can). - Mount the music share as
/music:ro. - Publish TCP 38472 and UDP 42424.
- Set
MUSIC_HUB_ADVERTISED_LOCAL_IPto the NAS LAN IP. - Open
http://<nas-ip>:38472and pair from that QR.
Troubleshooting
One-shot diagnostics:
curl -fsSL https://music-hub.gordo.design/docker-troubleshoot.sh | shOr against another host:
URL=http://192.168.1.40:38472 curl -fsSL https://music-hub.gordo.design/docker-troubleshoot.sh | shUI does not open
docker compose ps
docker compose logs --tail=100 music-hub
curl http://localhost:38472/api/pingExpected:
{"status":"ok"}Phone cannot pair / wrong IP in QR
- Set
MUSIC_HUB_ADVERTISED_LOCAL_IPto the host Wi‑Fi IP. - Open the UI as
http://<that-ip>:38472, not only localhost. - Confirm the phone browser can open the same URL.
docker compose up -dagain and scan a new QR.
Music folder empty
docker compose exec music-hub ls /musicIf empty, fix the host path in compose. If files show but the library is empty, add /music in Settings → Folders or set MUSIC_FOLDER=/music.
Off Wi‑Fi / Personal Private network fails
- Confirm compose maps
42424:42424/udp. - Confirm
MUSIC_HUB_ADVERTISED_LOCAL_IPis the host LAN IP (not172.x). - Pair once on Wi‑Fi first, then leave Wi‑Fi.
- Check logs:
docker compose logs --tail=200 music-hub.
Image architecture
ghcr.io/gordo-labs/music-hub/server:latest is multi-arch (linux/amd64 + linux/arm64). If pull fails with an architecture error, report it in Telegram or WhatsApp.