Remote library server for the ZenHoot music player. https://zenhoot.znowsoft.com
1.2K
Remote library server for the ZenHoot music player. Point it at a folder of music, and every ZenHoot install you own can browse and stream that library over your network.
Your files stay where they are. The server reads them, indexes them, and serves them — nothing is uploaded anywhere, and no account is needed to run it.
docker run -d --name zenhoot \
-p 9555:9555 \
-v /path/to/your/music:/music:ro \
-v ./zenhoot-cache:/cache \
-e DESTRUCTIVE_LOCALHOST_ONLY=false \
-e ZENHOOT_API_TOKEN=change-me-to-a-long-random-string \
znowf0x/zenhoot:latest
Then add a remote source in ZenHoot pointing at http://<this-host>:9555.
A ready-made compose file lives in the repository as docker-compose.example.yml.
| Tag | Meaning |
|---|---|
latest | Newest release |
1.0.0 | An exact version — use this if you want reproducible deploys |
1.0 | Newest patch of 1.0 |
1 | Newest release of major 1 |
Built for linux/amd64 and linux/arm64, so it runs on a NAS or a Raspberry Pi as well as on a server.
| Path | Purpose |
|---|---|
/music | Your library. Mount it :ro — the server only reads it unless you edit tags from the app. |
/cache | Artwork cache and the library index. Persist this, or every recreate triggers a full rescan. |
The cache directory has to be writable by the container. See PUID/PGID below.
| Variable | Default | What it does |
|---|---|---|
ZENHOOT_API_TOKEN | (unset) | Shared secret. Clients send it as X-API-Token. Set a long random one. |
DESTRUCTIVE_LOCALHOST_ONLY | true | When true, library-modifying requests are refused unless they came from this machine. |
ALLOWED_ORIGINS | (unset) | Extra browser origins allowed to call the API, comma separated. Loopback and the app's own schemes are always allowed. * disables the check. |
Read this one. The default
DESTRUCTIVE_LOCALHOST_ONLY=trueis what protects a server that has no token. The moment you set it tofalse— which you must, to reach the server from another device — that protection is gone andZENHOOT_API_TOKENis the only thing left. Settingfalsewithout a token leaves a server that any unauthenticated request on your network can rewrite.A token can also be set from the app after first launch; it is stored in
/cache/server-auth.json.
| Variable | Default | What it does |
|---|---|---|
PUID | 1000 | User id the server runs as. Set it to the owner of your cache directory (id -u). |
PGID | 1000 | Group id, likewise (id -g). |
PORT | 9555 | Port inside the container. |
MUSIC_DIR | /music | Where the library is mounted. |
CACHE_DIR | /cache | Where the index and artwork cache live. |
The container starts as root only long enough to adopt PUID/PGID, then drops to that user for the server process itself. Pass --user to Docker to skip this entirely if you would rather manage it yourself.
| Variable | Default | What it does |
|---|---|---|
SCAN_CONCURRENCY | CPU count, capped at 8 | Files parsed in parallel during a scan. Lower it on a NAS with spinning disks; raise it on fast NVMe. Hard maximum 32. |
Both of these are optional, and both are yours — ZenHoot ships with no API key of its own, because any key inside a distributed image can be read straight back out of it.
Without either key the server still finds lyrics through LRCLIB and artwork through MusicBrainz, Cover Art Archive and iTunes. Neither needs an account.
| Variable | Adds | Get one |
|---|---|---|
ACOUSTID_API_KEY | Identifies files by what they sound like, for tracks whose tags are wrong or missing | acoustid.org/new-application |
GENIUS_API_KEY | A second lyrics source behind LRCLIB — mostly older, rarer and non-English tracks | genius.com/api-clients/new (copy the Client Access Token) |
fpcalc (Chromaprint), which AcoustID fingerprinting needs, is already installed in this image — the key is the only missing piece.
Keys are read from the environment at startup and are never written into the image or the cache.
The image carries a healthcheck against GET /health, which returns {"ok":true,"uptime":N}. First boot of a large library indexes before it serves, so the check allows a 40 second start period.
SIGTERM reaches the server directly and it shuts down in well under a second.docker logs zenhoot.© ZNOWSOFT, LLC. ZenHoot is proprietary software; this image is distributed for use with the ZenHoot player.
Content type
Image
Digest
sha256:d13b6281d…
Size
105.4 MB
Last updated
about 1 month ago
docker pull znowf0x/zenhoot