Skip to main content

Open-source alternatives guide

How to Self-Host Navidrome 2026

Self-host Navidrome for music streaming in 2026. GPL 3.0, ~11K stars, Go — Subsonic-compatible music server. Stream your music library to any device now.

·OSSAlt Team
Share:

TL;DR

Navidrome (GPL 3.0, ~11K GitHub stars, Go) is a self-hosted music streaming server that turns your local music library into a Spotify-like streaming service. It's Subsonic API compatible, which means it works with every Subsonic client — iOS, Android, desktop, web. Stream FLAC, MP3, AAC, and any audio format to any device. Spotify Premium costs $9.99/month and only has what they license; Navidrome streams your own lossless library for free.

Key Takeaways

  • Navidrome: GPL 3.0, ~11K stars — self-hosted Subsonic music server, all formats
  • Subsonic API compatible: Works with Symfonium, DSub, Feishin, Foobar2000, and more
  • All formats: FLAC, MP3, AAC, OGG, OPUS, ALAC — streams lossless to compatible clients
  • Transcoding: Converts FLAC → MP3 on-the-fly for low-bandwidth connections
  • Smart playlists: Dynamic playlists based on rules
  • Multi-user: Each user has their own play count, favorites, playlists
FeatureNavidromeFunkwhaleSpotify
LicenseGPL 3.0AGPL 3.0Proprietary
CostFreeFree$9.99/mo
Lossless (FLAC)YesYesNo (max 320kbps)
Own libraryYesYesNo (their catalog)
Subsonic APIYesYes (partial)No
Smart playlistsYesNoYes
Social featuresNoYes (federation)Yes
TranscodingYesYes
iOS appsVia SubsonicVia SubsonicOfficial
RAM~50MB~200MB
GitHub Stars~11K~1.5K

Part 1: Docker Setup

# docker-compose.yml
services:
  navidrome:
    image: deluan/navidrome:latest
    container_name: navidrome
    restart: unless-stopped
    user: "1000:1000"
    ports:
      - "4533:4533"
    volumes:
      - navidrome_data:/data
      - /path/to/music:/music:ro    # Your music library (read-only)
    environment:
      ND_SCANSCHEDULE: "1h"          # Scan for new music every hour
      ND_LOGLEVEL: "info"
      ND_SESSIONTIMEOUT: "24h"
      ND_BASEURL: ""
      ND_SPOTIFY_ID: ""              # Optional: Spotify API for artist images
      ND_SPOTIFY_SECRET: ""
      ND_LASTFM_ENABLED: "true"      # Optional: Last.fm scrobbling
      ND_LASTFM_APIKEY: ""
      ND_LASTFM_SECRET: ""
      ND_ENABLEGRAVATAR: "true"      # User avatars from Gravatar
      ND_DEFAULTLANGUAGE: "en"
      ND_DEFAULTTHEME: "Dark"

volumes:
  navidrome_data:
docker compose up -d

Visit http://your-server:4533 → create admin account.

Part 2: HTTPS with Caddy

music.yourdomain.com {
    reverse_proxy localhost:4533
}

Part 3: Music Library Organization

Navidrome follows standard music tagging conventions:

/music/
  Artist Name/
    Album Name (2020)/
      01 - Track Title.flac
      02 - Track Title.flac
      cover.jpg           ← Album art
  Various Artists/
    Compilation (2019)/
      01 - Artist - Track.mp3

Tagging matters: Navidrome reads metadata from ID3 tags (MP3), FLAC tags, etc.

Recommended taggers:

  • beets (command line, automated)
  • MusicBrainz Picard (GUI, accurate)
  • Mp3tag (Windows GUI)

Part 4: Connect Mobile Apps

Symfonium (~$6) is the best Android Navidrome client:

  1. Add media provider → Navidrome / OpenSubsonic
  2. Server URL: https://music.yourdomain.com
  3. Username + password
  4. Downloads for offline, CarPlay support, album art

Android — DSub (Free)

DSub — free, open source:

  1. Server URL: https://music.yourdomain.com
  2. Username + password
  3. Version: Subsonic 1.15 or higher

iOS — Amperfy

Amperfy (free, open source):

  1. Add Navidrome server
  2. URL + credentials
  3. Downloads, queue management, background playback

Desktop — Feishin

Feishin is a beautiful cross-platform desktop app:

# macOS/Linux/Windows:
# Download from GitHub releases

Configure → Navidrome server URL + credentials.

Web Player (Built-in)

Navidrome includes its own web player at https://music.yourdomain.com:

  • Browse by Artist/Album/Genre
  • Create playlists
  • Queue management
  • Last.fm integration

Part 5: Transcoding

For clients that don't support FLAC or for low-bandwidth connections:

environment:
  ND_TRANSCODINGENABLED: "true"
  # Transcoding is configured per-user in Settings or by format

Per-user transcoding settings:

  1. User → Personal Settings → Max Bit Rate
  2. Set to 128/192/320 kbps — Navidrome transcodes FLAC → MP3 on-the-fly

Or configure globally:

# navidrome.toml
TranscodingCacheSize = "100MiB"

Part 6: Last.fm Scrobbling

Track what you listen to with Last.fm:

  1. Settings → External Integrations → Last.fm
  2. Get API key from last.fm/api
  3. Enable per-user in Personal Settings → Last.fm link

Or use ListenBrainz (open alternative to Last.fm):

environment:
  ND_LISTENBRAINZ_ENABLED: "true"

Part 7: Multi-User Setup

Add users with different permissions:

  1. Settings → Users → New User
  2. Set: username, password, role
  3. Roles:
    • Admin: Full access including settings
    • Regular: Browse and play only
    • Download: Can download tracks

Each user has their own:

  • Play history and statistics
  • Playlists
  • Favorites (starred tracks)
  • Last.fm/ListenBrainz account

Part 8: Smart Playlists

Create dynamic playlists using the Navidrome query language:

# Recently added albums:
albumDate after -30 days

# 5-star tracks:
starred = true AND rating = 5

# Unplayed music:
playCount = 0

# Jazz released in the 60s:
genre = "Jazz" AND albumDate > 1960 AND albumDate < 1970

# Long tracks (20+ minutes):
duration > 1200

Part 9: Beets Integration (Auto-Tagging)

beets automatically tags and organizes your music from MusicBrainz:

# Install beets:
pip install beets

# config.yaml
directory: /music
library: /data/beets/musiclibrary.db

import:
  copy: yes
  move: no

plugins: fetchart embedart lastgenre
# Import and tag your music collection:
beet import /path/to/untagged/music/

After beets tags everything properly, Navidrome's metadata will be perfect.

Maintenance

# Update Navidrome:
docker compose pull
docker compose up -d

# Trigger manual library scan:
# Admin → Library → Scan Now

# Logs:
docker compose logs -f navidrome

# Backup (SQLite database):
tar -czf navidrome-backup-$(date +%Y%m%d).tar.gz \
  $(docker volume inspect navidrome_navidrome_data --format '{{.Mountpoint}}')

Why Self-Host Navidrome

Spotify Premium costs $9.99/month — $119.88/year — and only includes music Spotify has licensed. If you've spent years ripping CDs, purchasing FLAC downloads from Bandcamp, or collecting music that isn't on streaming platforms, Spotify doesn't serve your library. Navidrome serves your own collection to every device you own with no monthly fee, no catalog limitations, and no quality compression beyond what you choose. Apple Music has a similar catalog limitation — it's their licensed tracks, not your purchased collection.

The audio quality argument is meaningful for audiophiles. Spotify streams at maximum 320kbps MP3 even on its Premium tier, which is good but not lossless. If you have FLAC files — 1,411kbps lossless audio — Spotify discards that fidelity. Navidrome streams FLAC natively to compatible clients (Feishin on desktop, Symfonium on Android, Amperfy on iOS). For lower-bandwidth connections, it transcodes on the fly to whatever bitrate you set. You control the quality. For mobile listening on a metered connection, you can set a per-user maximum bitrate and Navidrome converts on the server side before streaming.

The Subsonic API compatibility is Navidrome's practical superpower. The Subsonic API has been around since 2009 and has a vast ecosystem of clients — desktop apps, mobile apps, Plex integrations, music players, and even physical audio hardware with Subsonic support. By being Subsonic-compatible, Navidrome inherits this entire ecosystem. You're not locked into a single proprietary app. If a better client comes out next year, you switch clients — the server stays the same.

Last.fm and ListenBrainz integration let you track your listening history, discover music based on what you play, and maintain a record of everything you've listened to across all your devices. This is the kind of listening intelligence that streaming platforms keep locked in their ecosystems. With Navidrome, your scrobble history belongs to you.

When NOT to self-host Navidrome. Navidrome only serves music you already own. If you want access to new releases, curated playlists, algorithmic discovery, or a catalog of 100 million tracks, Spotify and Apple Music do things Navidrome can't. Navidrome is for people who have a music library they've collected and want to access it everywhere — not for people who primarily discover and stream from a catalog. If you're starting from scratch with no music files, build the library first.

Prerequisites

Navidrome is written in Go and ships as a single binary with an embedded SQLite database. It is one of the most resource-efficient self-hosted media servers available. At idle it uses around 50MB of RAM. A Hetzner CX11 (2 vCPU, 2GB RAM) at €3.29/month can run Navidrome comfortably for a household of 2–3 simultaneous users. For larger families or higher-quality transcoding under load, a CX22 (4GB RAM) at €4.50/month is more comfortable. See the VPS comparison guide for providers with attached storage options if your music library is large.

Disk space planning is the main consideration. A FLAC rip of a typical album runs 200–400MB. A library of 1,000 albums requires 200GB–400GB. Most entry-level VPS plans include 40–80GB of SSD storage. If your library is large, look at VPS providers that offer additional volumes (Hetzner charges €4.39/month for a 100GB volume) or run Navidrome on a NAS with the library stored locally and the container running on the same machine.

Docker Engine 24+ and Docker Compose v2 are required. The compose file mounts your music directory read-only (/music:ro) — Navidrome never modifies your source files. User and group IDs matter: set user: "1000:1000" in the compose configuration to match the owner of your music files.

DNS: create an A record for music.yourdomain.com pointing to your server. Caddy handles HTTPS automatically.

Production Security Hardening

Navidrome exposes your personal music library over the internet. Without proper security, anyone who finds the URL could potentially access your collection.

UFW firewall. Block all ports except what Caddy needs:

ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Navidrome's internal port 4533 should not be publicly accessible.

Strong passwords for all users. The admin account's password is the primary protection for the library. Use a password manager to generate a long random password. Navidrome supports per-user access levels — use Regular or Download roles for family members rather than giving everyone Admin access.

Fail2ban. Protect SSH and limit brute-force attempts:

apt install fail2ban -y

Create /etc/fail2ban/jail.local:

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5

[sshd]
enabled = true
systemctl restart fail2ban

SSH hardening. Key-based authentication only:

# /etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin no
systemctl restart sshd

Secrets management. Navidrome doesn't require application secrets in .env (it uses its own internal auth), but your server's .env files for any co-located services should use chmod 600.

Automatic OS updates:

apt install unattended-upgrades -y
dpkg-reconfigure --priority=low unattended-upgrades

Back up the Navidrome database. The navidrome_data volume contains the SQLite database with all users, playlists, play counts, favorites, and scrobbling history. The music files themselves are read-only mounts from your library directory. Schedule database backups with Restic — the automated backup guide covers encrypted backup workflows. For the music library itself, ensure it has its own backup strategy independent of Navidrome.

For a complete hardening reference, see the self-hosting security checklist.

Troubleshooting Common Issues

Library scan completes but no artists/albums appear. Navidrome requires properly tagged audio files to build its library. If tags are missing or malformed, tracks appear under "Unknown Artist" or aren't grouped correctly. Use MusicBrainz Picard or beets (covered in Part 9) to tag your files correctly before scanning. After fixing tags, trigger a full rescan from Admin → Library → Scan.

Subsonic client apps can't connect. Most Subsonic clients need a "legacy" Subsonic API endpoint. In Navidrome settings, check that the API is enabled. When connecting clients, use your full domain (https://music.yourdomain.com), not just the domain without the protocol. Some older Subsonic clients require the "legacy" password hashing mode — enable this in Navidrome's user settings if your client reports authentication failures.

Transcoding not working for mobile clients. Transcoding requires FFmpeg to be available in the Navidrome container. The official deluan/navidrome Docker image includes FFmpeg. If you're using a custom or minimal image, verify ffmpeg is available: docker exec navidrome ffmpeg -version. If transcoding still fails, check the per-user settings in Navidrome — each user can have their own maximum bitrate configured under Personal Settings.

Container fails to start with "permission denied" on music directory. The user: "1000:1000" setting in the compose file must match the UID/GID of the user that owns your music files on the host. Check the ownership with ls -la /path/to/music. If the music directory is owned by a different UID, either chown -R 1000:1000 /path/to/music or update the compose user: setting to match the actual owner.

Last.fm scrobbling not working. Scrobbling is configured per-user, not globally. Go to Settings → External Integrations → Last.fm in Navidrome, verify the API key and secret are correct, and then have each user link their Last.fm account under Personal Settings. API key errors in the Navidrome logs indicate incorrect credentials.

Library scan is slow on a large collection. Initial scans of large libraries (10,000+ tracks) can take 30–60 minutes as Navidrome reads metadata from every file. Subsequent scans are incremental and much faster. During the initial scan, avoid restarting the container — an interrupted scan may leave the database in an inconsistent state requiring a full rescan from scratch.

Smart playlists not returning expected tracks. Navidrome's smart playlist query language is case-sensitive for genre names and exact for text fields. If genre = "Jazz" returns nothing but you expect results, check the actual genre tag on your files with a tag editor — it might be jazz (lowercase) or Jazz / Fusion. The albumDate field works with four-digit years and comparison operators, so verify the year format in your files matches what Navidrome reads.

Web player shows audio but won't play. If the web player shows a track but playback doesn't start, check your browser's console for mixed content warnings. This happens when Navidrome is accessed over HTTPS but the audio stream URL is HTTP. Ensure your Caddy configuration proxies all paths (including audio stream endpoints) under HTTPS. Also verify your browser's autoplay policy isn't blocking initial playback — click directly on the play button rather than relying on programmatic autoplay.

See all open source music and media tools at OSSAlt.com/categories/media.

The SaaS-to-Self-Hosted Migration Guide (Free PDF)

Step-by-step: infrastructure setup, data migration, backups, and security for 15+ common SaaS replacements. Used by 300+ developers.

Join 300+ self-hosters. Unsubscribe in one click.