SSD Nodes Learn 🎉 VPS from $5.50/mo
How to do am Matt ConnorBy Matt Connor

How to Run Navidrome Music Streaming for VPS

Run Navidrome for your own music library on any phone. See storage sizing, Subsonic clients, offline sync, TLS, and safe backup advice before you start.

Wetin self-hosted music streaming for VPS dey give you

Self-hosted music streaming for VPS mean say na you dey run the player and provide the music. The server dey hold files wey you already own, and any phone fit reach am through internet with normal login. Make you understand the trade-off before you start: this one replace streaming service player, e no replace the service catalogue. Nothing new go appear for your library until you buy am or rip am, then copy the file go server.

Audio dey easier for server than video. The files small, phones fit decode common formats without help, and one listener dey use less bandwidth than video call. CPU no be the main wahala here. Disk space na the real limit. The other two things wey determine whether this setup go work na the quality of your tags and whether your phone app fit download music for offline use.

Wich music server: Navidrome, Jellyfin, or Funkwhale?

Navidrome na the default choice if na audio you care about. Na one Go binary inside one container, and e dey keep im state for one SQLite database. E dey answer the Subsonic API, na why plenty third-party phone apps dey exist. Version 0.63.2 na the current version for August 2026. The project talk say e dey run well for hardware as small as Raspberry Pi Zero, so server software no be the thing wey go cost you money.

Jellyfin make sense if you already dey run Jellyfin as media server for VPS for video. Im music library dey work, and Finamp na Jellyfin music app for Android and iOS wey fit download tracks for offline listening. The limit na the API. Jellyfin no get built-in Subsonic endpoint, and the community plugin wey add one stop receiving updates for 2022, so Subsonic app ecosystem no open to am. You go use apps wey dey speak Jellyfin own API instead, and those apps no plenty.

Funkwhale na the federated option, and dem release version 2.0 for March 2026. Dem dey call Funkwhale server pod, pods dey federate through ActivityPub (the protocol wey Mastodon dey use), and user for one pod fit follow public library for another one. E dey answer part of Subsonic API too, but one difference dey important: each user go set separate Subsonic password for their own settings, because Subsonic protocol expect password wey server fit read back. Funkwhale installation heavier, because e need PostgreSQL and task queue together with the web app.

Pick Navidrome unless you want federation, or unless Jellyfin already dey run. The rest of this guide go set up Navidrome with Docker.

Why Subsonic API dey decide which phone app you go use

Subsonic na music server wey im HTTP API become common language for self-hosted audio, while OpenSubsonic na community project wey dey continue to extend am. Na this history make your phone get different options. Navidrome no ship with im own mobile app and e no need one, because any Subsonic client fit log in with server address and your account details.

This matter dey important pass for offline sync, wey na the feature wey decide whether the setup go work for everyday use. Phone wey dey inside tunnel no fit reach your server, so the client must don copy the files enter local storage before then. Every client fit stream. Na only some fit download. The client directory for navidrome.org/apps dey show which ones fit do am, and the choice wide for both platforms: Substreamer and Ultrasonic for Android, Amperfy and play:Sub for iOS. Several of the strongest clients na paid apps, and people dey mention Symfonium for Android pass others. Install two before you decide, because na this part of the system you go dey touch every day.

How much storage music library need?

ChartStorage per 1,000 albums by audio format
The data behind this chart
[
  {
    "label": "Opus 128k",
    "kbps": 128,
    "gb_per_1000_albums": 43
  },
  {
    "label": "MP3 320k",
    "kbps": 320,
    "gb_per_1000_albums": 108
  },
  {
    "label": "FLAC 16/44.1",
    "kbps": 900,
    "gb_per_1000_albums": 304
  },
  {
    "label": "FLAC 24/96",
    "kbps": "3,000",
    "gb_per_1000_albums": "1,013"
  }
]

Those figures na rough estimates based on bitrate, no be measurement of real collection, and the calculation simple enough make you check am against your own files. Treat album as 45 minutes, which be 2,700 seconds. Multiply bitrate for kilobits per second by 2,700, then divide by 8,000 to get megabytes. For 320 kbps, that one album go use 108 MB, so one thousand albums go use about 108 GB.

Lossless go change the answer. CD quality FLAC dey average near 900 kbps for ordinary material, so that same one thousand albums go need about 304 GB. 24 bit, 96 kHz library go reach roughly 1,013 GB, which be full terabyte for collection wey you fit list for paper. Phone-friendly Opus copy for 128 kbps fit put that same one thousand albums inside 43 GB. Run du -sh /path/to/music for the library wey you already get, because na your own average bitrate be the only number wey matter when you dey choose plan.

Bandwidth na the smaller part of the bill. Stream wey be 320 kbps dey use 40 kilobytes per second, so one hour listening go move about 144 MB. One hundred hours for one month na around 14 GB, and VPS transfer allowance no go even notice am. The exception na the first offline sync for phone, wey fit push tens of gigabytes for one evening.

Storage tier or compute tier?

Music server na big pile of cold data wey hardly need computation. When e dey read file at 40 kilobytes per second, any disk fit remain idle, and CPU only dey work during library scan or transcoding, wey you mostly no go do. So, the fast NVMe for compute plan no really give you anything here. Na the price per gigabyte dey stop you from uploading the FLAC copies. This na the situation wey storage VPS better pass regular VPS, because dem dey price those plans per terabyte instead of per core.

Memory need no be much. Navidrome fit serve personal library with few hundred megabytes, and scan na the peak usage, not playback. Give the box 1 GB or 2 GB of RAM, then use the remaining budget for disk.

Install Navidrome with Docker Compose

Create the directories first, and make the user ID wey container go run as own dem. If Compose still new to you, Docker Compose for a VPS explain wetin this file assume.

sudo install -d -m 755 -o 1000 -g 1000 /srv/navidrome /srv/music

Write docker-compose.yml with almost nothing else, inside its own directory:

services:
  navidrome:
    image: deluan/navidrome:0.63.2
    user: "1000:1000"
    ports:
      - "127.0.0.1:4533:4533"
    restart: unless-stopped
    environment:
      ND_LOGLEVEL: "info"
      ND_SESSIONTIMEOUT: "24h"
      ND_SCANNER_SCHEDULE: "@every 24h"
      ND_BACKUP_PATH: "/data/backup"
      ND_BACKUP_SCHEDULE: "0 4 * * *"
      ND_BACKUP_COUNT: "7"
    volumes:
      - /srv/navidrome:/data
      - /srv/music:/music:ro
docker compose up -d
docker compose ps

docker compose ps suppose show say service dey run, instead of say e dey restart. Container wey dey restart continuously almost always get permission problem for /srv/navidrome, and docker compose logs navidrome name the file wey e no fit write.

Four details for that file dey worth explaining. The port publish only for 127.0.0.1, so server dey reachable through reverse proxy and no be through port 4533 from open internet: Docker dey write im own firewall rules, so plain 4533:4533 still dey exposed even for machine wey ufw report say everything dey denied. Music volume na read only, so scanner bug no fit delete your only copy. ND_SCANNER_SCHEDULE disabled by default, and guides wey dem write before Navidrome 0.55 dey call am ND_SCANSCHEDULE, but that name no longer exist. The three backup settings enable the built in database backup wey the backup section below depend on.

Put your music for the server

Use rsync copy the library go the server. If connection drop, e go continue from where e stop instead of starting again.

rsync -av --info=progress2 ~/Music/ user@music.example.com:/srv/music/

The trailing slash for the source path matter. If you no put am, you go get /srv/music/Music. When copy finish, correct the ownership:

sudo chown -R 1000:1000 /srv/music
id -u

The container dey run with user id 1000, and the mount dey read only. So every file must dey readable by that id. If your SSH account no be uid 1000 for the VPS, the copied files go belong to another user. The scan go find zero tracks, while the web interface go remain empty. id -u go show your actual id, and how PUID and PGID dey work for Docker containers explain the mapping completely.

Reverse proxy and TLS wey go make the phone work from anywhere

Point DNS A record go the VPS, then give Caddy three lines:

music.example.com {
    reverse_proxy 127.0.0.1:4533
}
sudo systemctl reload caddy

Caddy go request the certificate for the first request. Ports 80 and 443 both need to dey open, because ACME (automatic certificate management environment) challenge dey answer for port 80. For nginx, add proxy_buffering off; to the location block: Navidrome dey push progress events go the web interface through one long-lived connection, and when buffering dey on, the interface go wait while nginx still dey hold the response. If you serve am under a path like /music instead of e own subdomain, set ND_BASEURL to the same path. Otherwise, the interface go load as blank page. The three common proxies dey compared for Nginx, Caddy and Traefik for VPS.

Open the site and create the first account. No default password dey. The first visitor go get prompt to create the admin user, so do this before you give anybody the address. Then test the exact path wey phone client dey use:

SALT=$(openssl rand -hex 6)
TOKEN=$(printf '%s%s' 'YOUR_PASSWORD' "$SALT" | md5sum | cut -d' ' -f1)
curl -s "https://music.example.com/rest/ping.view?u=YOUR_USER&t=$TOKEN&s=$SALT&v=1.16.1&c=curl&f=json"

Healthy response go start with {"subsonic-response":{"status":"ok" and name navidrome as the server type. If body contain "status":"failed" and error code 40, proxy dey work fine but the credentials no correct. Certificate error for this step na the first thing to fix, because most phone clients dey reject bad certificate with message wey no explain anything.

Why your library dey look wrong after the first scan

Navidrome dey browse by tags instead of folders, so na the tags decide wetin you go see. If track no get album artist tag, e go file am under the track artist. Na why one compilation wey get different artist for every track fit turn to twenty albums with one track each. Fix this for the files, no be for Navidrome: MusicBrainz Picard and beets both dey look up album for MusicBrainz database, then write standard tags back.

Navidrome still dey split multi artist tag into separate artists. So if band name get separator, e fit split am by mistake. AC/DC na the example wey everybody dey meet. ND_SCANNER_ARTISTSPLITEXCEPTIONS hold the names wey dem must never split.

New files dey get picked up by file watcher few seconds after dem land. The watcher depend on kernel change notifications. Those notifications no dey arrive for files wey another machine write to network share wey dem mount. So for that kind setup, na the periodic ND_SCANNER_SCHEDULE dey keep the library current. Full rescan dey read tags for every file. This slow down for big library, and na one reason why database below worth protecting.

Users, playlists, and sharing

Admin go create the other accounts for the web interface, and users no get self signup. Each user get separate play counts, playlists, favourites, and ratings, so household no go end up dey share one taste profile.

Playlists dey come from two directions. Playlist wey user make for client dey live inside database. When person drop .m3u file inside library folder, system go import am during scan. This na the easy way to carry playlist from desktop player. Smart playlists na .nsp files. Dem be small JSON rule files wey system import the same way, and dem dey update by themselves as library dey change.

Sharing dey enabled by default from version 0.63.0, wey release for July 2026. E let user create public link for album wey anybody fit open without logging in. For server wey dey hold your complete library, this fit no be wetin you want. Set ND_ENABLESHARING to false to turn am off.

Back up database dem separately from music files

Navidrome own backup dey cover database only. Documentation talk am clearly: backup process dey back up database, meaning users, play counts and the rest, but e no dey back up music or config. Na correct way be to think about this split, because both sides dey fail for different ways. You fit copy music files again from the disk wey you rip dem from. Play counts, ratings, favourites and playlists no dey anywhere else, and rescan no fit bring dem back.

The compose file already dey write one copy every night into /data/backup and dey keep seven copies. Take one manually before upgrade:

sudo docker compose run --rm navidrome backup create

Restore dey wipe the current database and copy the backup enter its place, and you must run am while Navidrome dey stopped. Restore no safe at all for live server.

Those files still dey for the same VPS, so dem no go survive if VPS fail. Push /srv/navidrome go another machine or object storage on schedule. Na the kind work wey restic and BorgBackup dey built for. The whole directory small, usually well below one gigabyte, so one daily encrypted copy off the server cost almost nothing and fit restore everything wey rescan no fit bring back.

FAQ

I need transcode music for a VPS?

Almost never. Phones and browsers fit decode MP3, AAC, Opus and FLAC by demself, so server go send the file as e be and use almost no CPU. Na only one case make sense to enable am: if you dey stream FLAC library through mobile data, converting from about 900 kbps go Opus at 128 kbps fit reduce data usage by roughly seven times. Navidrome fit do am per user and per player, and e go remain off until you turn am on.

Why my phone app no fit download music for offline listening?

Because offline storage na client feature, no be server feature. Subsonic API allow any client fetch complete file, but na the app decide whether e go keep copy for phone. Check client directory for navidrome.org/apps and choose one wey description mention offline downloads or caching. Some clients only cache wetin you don play already. That one no be the same as syncing album before journey.

Why one album split into many albums after the scan?

The album artist tag dey missing or e no match across the tracks. Navidrome dey group by tags, no be folder, so twelve tracks wey get twelve different artist values and no shared album artist value go look like twelve albums. Set album artist tag for every track of the album, usually to Various Artists for compilation, then make e rescan. MusicBrainz Picard or beets fit do this for whole folder at once.

Self-hosted music streaming replace Spotify?

E replace the player and library, no be catalogue. You go get your own collection for every device, with playlists and play counts wey licensing change no fit take away from you. You no go get new releases, and you no go get recommendations based on other people listening habits. Most people wey run this dey buy their music and keep cheap streaming account for discovery.

#navidrome#music#streaming#self-hosting#media-server