Docker / NAS (optional)

Docker Setup

Optional. Most people do not need a server: Getting started is the main path, and Choose your setup shows when Docker helps.

Run Tape 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://tapemusicsuite.com/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 Tape 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, Tape 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 Tape Music Hub. The host paths (/volume1/music, /volume1/samples, etc.) are only used on the Docker host and are not valid paths in the Tape 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 Connections (sidebar).
  3. Arm pairing if needed.
  4. Scan the QR with the Tape 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 (Iroh))

No Tailscale. No port-forward. Personal Private Network (Iroh) is built into the server. How the routes work: Network Documentation.

  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.

docker compose down / pull stops the container gracefully; the compose file allows 60 seconds (stop_grace_period) so the database closes cleanly. If you use your own compose file, add:

services:
  music-hub:
    stop_grace_period: 60s

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.
  6. Keep stop_grace_period: 60s (already in the downloaded compose). Docker's default is 10 seconds: on a large library the hub may need longer to close its database cleanly, and if Docker kills it first the next start runs a full integrity check before the UI opens.

Large libraries (hundreds of thousands to millions of tracks)

  • The hub stays responsive while it works: big counts, searches and rebuilds run in background threads. The first open of some views (filters, a far scroll position, To listen) can take a few seconds on millions of tracks.
  • First import reads the tags of every file once (title, artist, album, artwork). On millions of new files that is many hours in the background; the library is browsable meanwhile, with file names until each file is read.
  • Above 250,000 tracks automatic folder watching and the scan at every start are off. Use Rescan folders in Settings after adding or removing music.
  • Use an SSD for ./data: the database of a 4 million track library is about 5 GB.

Troubleshooting

One-shot diagnostics:

curl -fsSL https://tapemusicsuite.com/docker-troubleshoot.sh | sh

Or against another host:

URL=http://192.168.1.40:38472 curl -fsSL https://tapemusicsuite.com/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 (Iroh) 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.