← All articles
a bunch of wires that are connected to a server

Navidrome: A Lightweight Self-Hosted Music Streaming Server

Media 2026-02-15 · 8 min read navidrome music streaming subsonic media-server
By Selfhosted Guides Editorial TeamSelf-hosting practitioners covering open source software, home lab infrastructure, and data sovereignty.

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.

Navidrome self-hosted music streaming server logo

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:

Key Features

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:

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

iOS

Desktop

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:

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:

  1. Go to Settings in the web UI
  2. Enter your Last.fm API key or ListenBrainz token
  3. 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:

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.

Get free weekly tips in your inbox. Subscribe to Self-Hosted Weekly