Navidrome: A Lightweight Self-Hosted Music Streaming Server
Plex and Jellyfin are excellent general-purpose media servers, but they treat music as an afterthought. Library scanning takes forever, the music UI feels bolted on, and you're running a full video transcoding stack just to stream some FLAC files. If music is your primary use case, there's a better tool.
Photo by Lightsaber Collection on Unsplash
Navidrome is a self-hosted music streaming server written in Go that implements the Subsonic API. It's fast, lightweight, and purpose-built for music. It scans a 50,000-track library in seconds, serves a modern web UI, and works with dozens of existing Subsonic-compatible mobile and desktop apps.

Why Navidrome Instead of Plex or Jellyfin for Music
The short answer: Navidrome does one thing and does it well.
Plex's music experience requires Plexamp, which is locked behind a Plex Pass subscription ($5/month or $120 lifetime). Jellyfin's music support is functional but rough — the web player lacks gapless playback, and library scanning for large collections is slow.
Navidrome, by contrast:
- Scans fast — A 10,000-album library indexes in under a minute. Jellyfin can take 30+ minutes for the same collection.
- Uses minimal resources — 50 MB of RAM at idle, no Java, no .NET runtime, no Electron. Just a single Go binary.
- Supports the Subsonic API — This means you get access to 30+ polished music apps across Android, iOS, desktop, and web, built by a community that's been refining them for over a decade.
- Handles multi-user properly — Each user gets their own playlists, favorites, play history, and scrobbling configuration.
- Runs anywhere — Raspberry Pi, NAS, VPS, or a full server. If it runs Linux (or macOS, or Windows), Navidrome runs on it.
Key Features
- Modern web UI — React-based player with album art, artist pages, genres, playlists, and a responsive layout
- Subsonic and OpenSubsonic API — Compatible with DSub, Substreamer, play:Sub, Sonixd, Feishin, Sublime Music, and many more
- On-the-fly transcoding — Streams FLAC as MP3 or Opus to save bandwidth on mobile, powered by ffmpeg
- Multi-user — Each user has independent favorites, playlists, play counts, and Last.fm/ListenBrainz scrobbling
- Smart playlists — Auto-generated playlists based on rules (recently added, most played, random, top rated)
- ReplayGain — Reads ReplayGain tags for consistent volume across tracks
- Gapless playback — In the web UI and supported clients
- Album art and metadata — Reads embedded tags and external artwork, fetches artist images from Spotify (optional)
- Multi-disc albums — Proper disc number support
- Star ratings and favorites — Per-user ratings synced across all clients
Docker Compose Setup
Create a directory for Navidrome and add a docker-compose.yml:
services:
navidrome:
image: deluan/navidrome:0.53.3
ports:
- "4533:4533"
environment:
ND_SCANSCHEDULE: "1h"
ND_LOGLEVEL: "info"
ND_SESSIONTIMEOUT: "24h"
ND_BASEURL: ""
volumes:
- ./data:/data
- /path/to/your/music:/music:ro
restart: unless-stopped
docker compose up -d
Visit http://your-server:4533 and create your admin account on first access. That's it — Navidrome will immediately start scanning the /music directory.
Configuration Options
Navidrome is configured via environment variables. Here are the ones that matter most:
| Variable | Default | Description |
|---|---|---|
ND_SCANSCHEDULE |
@every 1m |
How often to check for new music. 1h is reasonable. |
ND_LOGLEVEL |
info |
Set to debug for troubleshooting |
ND_SESSIONTIMEOUT |
24h |
How long sessions stay active |
ND_TRANSCODINGCACHESIZE |
100MB |
Disk cache for transcoded files |
ND_IMAGECACHESIZE |
100MB |
Cache for cover art thumbnails |
ND_ENABLETRANSCODINGCONFIG |
false |
Allow users to configure transcoding in the UI |
ND_ENABLESHARING |
false |
Enable public sharing links for tracks/albums |
ND_DEFAULTLANGUAGE |
en |
Web UI language |
ND_AUTOIMPORTPLAYLISTS |
true |
Auto-import .m3u playlists from music directory |
ND_ENABLESTARRATING |
true |
Enable 5-star ratings |
For the full list, see the Navidrome configuration docs.
Like what you're reading? Subscribe to Self-Hosted Weekly — free weekly guides in your inbox.
Music Library Organization
Navidrome reads metadata from your audio file tags, not the folder structure. That said, a clean directory layout makes things easier to manage:
/music/
├── Artist Name/
│ ├── Album Name (Year)/
│ │ ├── 01 - Track Title.flac
│ │ ├── 02 - Track Title.flac
│ │ ├── cover.jpg
│ │ └── ...
│ └── Another Album (Year)/
│ └── ...
├── Various Artists/
│ └── Compilation Name (Year)/
│ └── ...
└── ...
Tips for a clean library:
- Use a tagging tool like MusicBrainz Picard to standardize your metadata before importing. Navidrome is only as good as your tags.
- Embed cover art directly in files when possible. Navidrome also reads
cover.jpg,cover.png,folder.jpg, andfront.jpgfrom the album directory. - For multi-disc albums, either use disc number tags (preferred) or subdirectories like
Disc 1/,Disc 2/. - Supported formats: FLAC, MP3, OGG, AAC, WMA, OPUS, M4A, APE, WavPack, and more — anything ffmpeg can decode.
Subsonic API Clients
The Subsonic API has been around since 2004, and a large ecosystem of clients exists. Here are the best options across platforms:
Android
- DSub — The gold standard for Android. Offline caching, gapless playback, Chromecast support, and a mature UI. Available on F-Droid.
- Substreamer — Modern Material Design UI with offline support. Available on Google Play.
- Ultrasonic — Open source, lightweight. Good if you want something simple and free.
- Symfonium — Polished paid app ($5) with excellent audio quality support and a car mode.
iOS
- play:Sub — Full-featured Subsonic client with offline caching, AirPlay, and CarPlay support.
- Substreamer — Also available on iOS with a consistent experience across platforms.
- Amperfy — Open source iOS client with background playback and offline mode.
Desktop
- Sonixd — Cross-platform Electron app that looks like a proper desktop music player. Supports Navidrome's extended API features.
- Feishin — A newer alternative to Sonixd with a more modern UI and active development. Built with Electron, available on Windows, macOS, and Linux.
- Sublime Music — Native GTK client for Linux. Lightweight and integrates well with the GNOME desktop.
- Supersonic — Go-based desktop client with a clean interface, available cross-platform.
Web
Navidrome ships with its own React-based web player. It handles album browsing, playlists, search, and playback without needing any external client. For most casual listening, the built-in UI is sufficient.
Multi-User Setup
Navidrome supports multiple users out of the box. After creating the admin account, add users through the web UI under Settings > Users.
Each user gets:
- Independent playlists — Users can create and manage their own playlists without affecting others
- Personal favorites and ratings — Star ratings and favorited tracks are per-user
- Individual play history — Play counts and "recently played" are tracked separately
- Scrobbling configuration — Each user can configure their own Last.fm or ListenBrainz account
- Transcoding preferences — Users can set their own preferred streaming quality
All users share the same music library. You cannot restrict which artists or albums a user can see — Navidrome is designed for trusted environments (family, close friends), not multi-tenant public hosting.
Last.fm and ListenBrainz Scrobbling
Each user can enable scrobbling independently:
- Go to Settings in the web UI
- Enter your Last.fm API key or ListenBrainz token
- Scrobbles are sent from both the web UI and any connected Subsonic client
This works per-user, so multiple family members can scrobble to their own accounts from the same Navidrome instance.
Transcoding
Navidrome transcodes on the fly using ffmpeg. This is primarily useful for:
- Mobile streaming — Convert FLAC to 192 kbps MP3 or Opus to save cellular data
- Low-bandwidth connections — Reduce bitrate for remote access
- Client compatibility — Some older clients can't decode FLAC natively
To enable user-configurable transcoding, set ND_ENABLETRANSCODINGCONFIG=true. Then users can choose their preferred format and bitrate in settings.
Default transcoding profiles ship with Navidrome:
| Profile | Command | Use Case |
|---|---|---|
| mp3 | ffmpeg -i %s -ab %bk -v 0 -f mp3 - |
Maximum compatibility |
| opus | ffmpeg -i %s -ab %bk -v 0 -c:a libopus -f opus - |
Best quality per bitrate |
If your library is already in MP3 or a format your clients support, transcoding never activates — files are streamed directly.
Cache sizing: The transcoded file cache (ND_TRANSCODINGCACHESIZE) defaults to 100 MB. If you have a large library and many users streaming transcoded audio, bump this to 500MB or 1GB to avoid re-transcoding the same tracks.
Performance: Navidrome vs. Jellyfin vs. Plex for Music
| Metric | Navidrome | Jellyfin | Plex |
|---|---|---|---|
| Idle RAM usage | ~50 MB | ~300-500 MB | ~200-400 MB |
| Library scan (10,000 albums) | ~45 seconds | ~20-40 minutes | ~10-20 minutes |
| Startup time | ~2 seconds | ~15-30 seconds | ~10-20 seconds |
| Docker image size | ~60 MB | ~700 MB | ~300 MB |
| Database | SQLite | SQLite | SQLite |
| Runtime | Go (static binary) | .NET (C#) | C++ / Python |
| API for music apps | Subsonic (30+ clients) | Jellyfin API (limited) | Plex API (Plexamp only) |
| Gapless playback | Yes | Limited | Yes (Plexamp) |
| ReplayGain | Yes | No | Yes (Plexamp) |
| Smart playlists | Yes | Limited | Yes |
| Multi-user | Yes (full) | Yes (full) | Yes (managed users) |
| Cost | Free | Free | Free + Plex Pass for best music |
The difference in scan speed is the most noticeable thing in practice. If you add a new album to your library, Navidrome picks it up almost instantly on the next scheduled scan. Jellyfin's library refresh for music can feel painfully slow with large collections.
For video, Jellyfin and Plex are obviously the right choice. But if you're running a media server primarily for music, Navidrome is purpose-built for the job.
Reverse Proxy Configuration
You'll want a reverse proxy with HTTPS for remote access. Here are configurations for the most common options:
Caddy
music.example.com {
reverse_proxy localhost:4533
}
Caddy handles TLS automatically. This is the simplest option.
Nginx
server {
listen 443 ssl http2;
server_name music.example.com;
ssl_certificate /etc/letsencrypt/live/music.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/music.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:4533;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support for real-time updates
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Traefik (Docker labels)
services:
navidrome:
image: deluan/navidrome:0.53.3
labels:
- "traefik.enable=true"
- "traefik.http.routers.navidrome.rule=Host(`music.example.com`)"
- "traefik.http.routers.navidrome.entrypoints=websecure"
- "traefik.http.routers.navidrome.tls.certresolver=letsencrypt"
- "traefik.http.services.navidrome.loadbalancer.server.port=4533"
volumes:
- ./data:/data
- /path/to/your/music:/music:ro
restart: unless-stopped
If you're using a Cloudflare Tunnel, point it at http://localhost:4533 and you're done — no port forwarding or TLS configuration needed.
Hardware Requirements
Navidrome is remarkably light:
| Library Size | RAM | CPU | Storage (DB) |
|---|---|---|---|
| < 5,000 tracks | 50 MB | Any | ~10 MB |
| 5,000-50,000 tracks | 80 MB | 1 core | ~50 MB |
| 50,000-200,000 tracks | 150 MB | 1 core | ~200 MB |
| 200,000+ tracks | 300 MB | 2 cores | ~500 MB |
This means Navidrome runs comfortably on a Raspberry Pi 3 or 4, a Synology NAS, or any low-powered home server. Transcoding (via ffmpeg) is the only operation that uses significant CPU, and even that is modest since audio transcoding is far less demanding than video.
Backup and Data
Navidrome stores all its state in a single directory:
/data/
├── navidrome.db # SQLite database (users, playlists, play history, ratings)
├── cache/ # Transcoded file cache (can be regenerated)
└── ...
Back up navidrome.db and you've captured everything — user accounts, playlists, favorites, play counts, and scrobble history. The music files themselves are mounted read-only and should be backed up separately as part of your normal media backup strategy.
The Bottom Line
If you self-host a music collection, Navidrome is the best dedicated option available. It's fast, lightweight, and the Subsonic API ecosystem gives you client app options that Jellyfin and Plex can't match for music.
The setup takes five minutes. The resource footprint is negligible. And because it's a single Go binary with a SQLite database, there's almost nothing that can go wrong operationally — no JVM tuning, no database servers, no background workers eating your RAM.
Install it, point it at your music, and use whatever client feels right for your phone and desktop. That's the entire pitch.
