Docker Setup

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.yml

That 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 path

Example on a Linux NAS:

  - /volume1/music:/music:ro

Both 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:/archive

After 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.40

Linux:

hostname -I | awk '{print $1}'

Create a .env next to docker-compose.yml:

MUSIC_HUB_ADVERTISED_LOCAL_IP=192.168.1.40

Or export it in the shell:

export MUSIC_HUB_ADVERTISED_LOCAL_IP=192.168.1.40

Update this when you change Wi‑Fi networks.

4. Start

docker compose up -d
docker compose ps

Open the UI on the LAN IP (best for pairing QR):

http://192.168.1.40:38472

On the same machine only, http://localhost:38472 also works.

5. Pair the phone (same Wi‑Fi first)

  1. Open the web UI on the LAN IP.
  2. Go to Settings → Pairing.
  3. Arm pairing if needed.
  4. Scan the QR with the Music Hub mobile app.
  5. 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.

  1. License the hub if remote access is gated (paid desktop license).
  2. Settings → Remote → leave Personal Private network on.
  3. Pair once on Wi‑Fi (step 5).
  4. 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 -d

Back 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

VariablePurpose
MUSIC_HUB_ADVERTISED_LOCAL_IPHost Wi‑Fi IP for QR + Iroh dial (192.168.1.40)
MUSIC_FOLDERContainer path(s) to register on boot (/music)
HUB_NAMEOptional display name
MUSIC_HUB_TRUSTED_ORIGINSLAN subnets trusted for admin (default covers typical 192.168 / 172.16)

NAS notes

Same model on Synology, Unraid, and TrueNAS:

  1. Persistent folder for /data (SSD if you can).
  2. Mount the music share as /music:ro.
  3. Publish TCP 38472 and UDP 42424.
  4. Set MUSIC_HUB_ADVERTISED_LOCAL_IP to the NAS LAN IP.
  5. Open http://<nas-ip>:38472 and pair from that QR.

Troubleshooting

One-shot diagnostics:

curl -fsSL https://music-hub.gordo.design/docker-troubleshoot.sh | sh

Or against another host:

URL=http://192.168.1.40:38472 curl -fsSL https://music-hub.gordo.design/docker-troubleshoot.sh | sh

UI does not open

docker compose ps
docker compose logs --tail=100 music-hub
curl http://localhost:38472/api/ping

Expected:

{"status":"ok"}

Phone cannot pair / wrong IP in QR

  1. Set MUSIC_HUB_ADVERTISED_LOCAL_IP to the host Wi‑Fi IP.
  2. Open the UI as http://<that-ip>:38472, not only localhost.
  3. Confirm the phone browser can open the same URL.
  4. docker compose up -d again and scan a new QR.

Music folder empty

docker compose exec music-hub ls /music

If 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

  1. Confirm compose maps 42424:42424/udp.
  2. Confirm MUSIC_HUB_ADVERTISED_LOCAL_IP is the host LAN IP (not 172.x).
  3. Pair once on Wi‑Fi first, then leave Wi‑Fi.
  4. 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.