Navidrome is an open-source, Subsonic/Airsonic-compatible music streaming server you host yourself. It indexes your library, serves it over the web, and ties into dozens of Subsonic-compatible mobile and desktop clients. This guide deploys Navidrome using Docker Compose with Traefik handling automatic HTTPS, persistent volumes for the music library and the metadata database. By the end, you'll have Navidrome streaming your music library securely at your domain.
Set Up the Directory Structure
1. Create the project directories:
$ mkdir -p ~/navidrome/{data,music}
$ cd ~/navidrome
2. Create the environment file:
$ nano .env
TZ=Asia/Kolkata
ND_MUSICFOLDER=/music
ND_DATAFOLDER=/data
ND_LOGLEVEL=info
ND_PORT=4533
DOMAIN=navidrome.example.com
EMAIL=admin@example.com
Deploy with Docker Compose
1. Add your user to the Docker group:
$ sudo usermod -aG docker $USER
$ newgrp docker
2. Create the Compose manifest:
$ nano docker-compose.yml
services:
traefik:
image: traefik:v3.6
container_name: traefik
restart: unless-stopped
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--certificatesresolvers.le.acme.httpchallenge=true"
- "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.le.acme.email=${EMAIL}"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik_letsencrypt:/letsencrypt
navidrome:
image: deluan/navidrome:0.60.3
container_name: navidrome
restart: unless-stopped
environment:
- ND_MUSICFOLDER=${ND_MUSICFOLDER}
- ND_DATAFOLDER=${ND_DATAFOLDER}
- ND_LOGLEVEL=${ND_LOGLEVEL}
- TZ=${TZ}
volumes:
- ./music:${ND_MUSICFOLDER}
- ./data:${ND_DATAFOLDER}
labels:
- "traefik.enable=true"
- "traefik.http.routers.navidrome.rule=Host(`${DOMAIN}`)"
- "traefik.http.routers.navidrome.entrypoints=websecure"
- "traefik.http.routers.navidrome.tls=true"
- "traefik.http.routers.navidrome.tls.certresolver=le"
- "traefik.http.services.navidrome.loadbalancer.server.port=${ND_PORT}"
volumes:
traefik_letsencrypt:
3. Start the services and view logs:
$ docker compose up -d
$ docker compose ps
$ docker compose logs navidrome
Access Navidrome
- Open
https://navidrome.example.comin a browser. - Create the administrator account (username + password).
- The empty dashboard loads — Navidrome is waiting for music.
Add Music and Verify Playback
1. Drop a sample track into the music directory:
$ sudo wget https://archive.org/download/testmp3testfile/mpthreetest.mp3 -P ~/navidrome/music/
$ sudo chmod -R 755 ~/navidrome/music
2. Trigger a rescan from **Settings → Server → Re-scan library (or wait for the scheduled scan).**
3. Click the track and press play — the built-in player streams it from the server.
Next Steps
Navidrome is running and streaming securely over HTTPS. From here you can:
- Add more users with per-user library access from Users → Add
- Point Subsonic-compatible apps (Symfonium, DSub, play:Sub) at
https://navidrome.example.com - Mount external storage (block volume, S3 with
rclone mount) at~/navidrome/musicfor large libraries
For the full guide with additional tips, visit the original article on Vultr Docs.
Top comments (1)
Deploying Navidrome on a fresh Ubuntu instance definitely brings back memories of setting up similar services years ago. It's a solid way to get control over your media, and the appeal of owning your stack is strong, especially for something as personal as a music collection. For anyone diving into this, it’s a great example of how much power you can wield with a basic Linux server.
From an operational standpoint, for any self-hosted service like this that I intend to run reliably for years, I'd lean heavily into containerization right from the start. Docker Compose makes the initial setup and future updates so much cleaner, abstracting away the underlying OS dependencies. It also makes migrations to new hardware or even different cloud providers much less painful down the road. While SQLite is often the default for simplicity, if I were ever considering scaling it up beyond a single user, or wanted more robust backup and restore capabilities, I'd definitely swap that out for PostgreSQL. The overhead is minimal for the added reliability.
It's interesting how often the "build vs. buy" discussion comes up, even for personal projects like this. While the initial setup for Navidrome is fairly quick, the ongoing maintenance – keeping the OS patched, ensuring Navidrome itself is updated, managing backups, and maybe even setting up some basic monitoring – can quickly add up. For someone who values the privacy and control of owning their data stream, it's a worthwhile investment of time. But it's a commitment that sometimes gets overlooked when planning the initial deployment.