I Cancelled Spotify and Built My Own on a Raspberry Pi 5
Full walkthrough of building a self-hosted music server with Navidrome on a Pi 5. Stream your own library to any device — beautiful UI, real mobile apps, no subscription.
I Cancelled Spotify and Built My Own on a Raspberry Pi 5
My Spotify Wrapped last December was a kick in the teeth. Not because of the music — because of the receipt. I'd paid $143 that year to rent songs I already owned. On FLAC. Sitting on a dusty external drive in my closet.
So I built the replacement in a weekend. One Raspberry Pi 5, one USB SSD, one piece of software called Navidrome, and now I stream my own library to my phone, laptop, and car. Same UX as Spotify. Better sound. Zero subscription. The mobile app is genuinely beautiful — more on that below, because the app I landed on surprised me.
Here's the whole build. Every step I actually did, including the two hours I wasted on a permissions bug so you don't have to.
What you'll have at the end
A music server that costs ~$100 in hardware, draws 4 watts at idle, hosts your entire library, and streams to every device you own through a polished Spotify-style interface. Local network access works out of the box. Remote streaming — your music on a train in another country — takes 10 extra minutes.
Total setup time: about 90 minutes if your music is already tagged. A weekend if it isn't.
The hardware that actually matters
Skip the random Amazon Pi kits. Here's what I bought, with the parts that aren't negotiable marked:
→ Raspberry Pi 5, 4 GB — 8 GB is overkill for music. Save the $20. → Official 27 W USB-C power supply — non-negotiable. I tried a generic 65 W brick first. The Pi threw undervoltage warnings within an hour and corrupted a transcode cache. Use. The. Official. PSU. → microSD card, 32 GB, A2-rated — SanDisk Extreme or Samsung EVO Select. Cheap cards will brick within 6 months under server workloads. → Active cooler — Pi 5 throttles aggressively without one. The official $5 active cooler is fine. → USB 3.0 SSD enclosure + a 1 TB SSD — this holds your music. I used a Samsung T7 because I had one lying around. Any USB 3.0 SSD works. → Ethernet cable — Wi-Fi for a server is a bad idea. I'll die on this hill.
Total bill: about $110 if you already have the SSD, ~$190 if you don't. One time. Forever.
Step 1 → Flash Raspberry Pi OS Lite (headless)
Grab Raspberry Pi Imager from raspberrypi.com/software. Insert your microSD card. Pick Raspberry Pi OS Lite (64-bit) — no desktop, no bloat, runs cooler.
Before you click Write, hit the gear icon to set:
- Hostname:
navidrome - Your username and a real password (not
pi, neverpi) - Wi-Fi credentials only if you can't use Ethernet
- Enable SSH under Services
- Your timezone and locale
This headless config is the move. I used to plug a monitor and keyboard into every fresh Pi like a chump. Never again.
Eject, insert into Pi, plug in Ethernet, plug in power, wait two minutes.
Step 2 → SSH in and update
From your laptop:
ssh [email protected]
If .local doesn't resolve, your router's admin page will show the Pi's IP. Use that instead.
Update everything before doing anything else:
sudo apt update && sudo apt full-upgrade -y
sudo apt install -y curl ca-certificates
sudo reboot
Reconnect after the reboot. Now you've got a clean foundation.
Step 3 → Mount your music drive properly
Plug the SSD into one of the blue USB 3.0 ports on the Pi 5. The black ones are USB 2.0 and you'll cap out around 35 MB/s — fine for streaming, terrible for the initial library copy.
Find the drive:
lsblk
You'll see something like sda with a partition sda1. If it's a fresh drive, format it (this wipes everything — triple-check the device name):
sudo mkfs.ext4 -L music /dev/sda1
Already have your music on the drive? Don't reformat. If it's exFAT or NTFS, install the right helpers:
sudo apt install -y exfatprogs ntfs-3g
Now make it mount automatically on every boot, because if your Pi reboots at 3 AM and the music drive doesn't come back up, you've got a problem:
sudo mkdir -p /mnt/music
sudo blkid /dev/sda1
Copy the UUID from the output. Open fstab:
sudo nano /etc/fstab
Add this line at the bottom — swap in your actual UUID and use exfat or ntfs-3g instead of ext4 if you didn't reformat:
UUID=YOUR-UUID-HERE /mnt/music ext4 defaults,nofail,noatime 0 2
The nofail flag is the part most tutorials skip. Without it, your Pi refuses to boot if the drive is ever unplugged. With it, the Pi boots regardless and you can fix the drive at your leisure. Hard-earned lesson, that one.
Save and run:
sudo mount -a
ls /mnt/music
If you see your files or an empty lost+found, you're done with storage.
Step 4 → Install Docker
I run Navidrome in Docker for one reason: updates are a single command. No dependency hell, no broken Go installs after an OS upgrade.
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
Now log out and back in — exit, then SSH again — so the group change takes effect. Verify:
docker run --rm hello-world
If you see the "Hello from Docker!" banner, you're good.
Step 5 → Spin up Navidrome
Create a folder for the config and database:
mkdir -p ~/navidrome/data
cd ~/navidrome
nano docker-compose.yml
Paste this. It's the exact config I run on my Pi today:
services:
navidrome:
image: deluan/navidrome:latest
container_name: navidrome
restart: unless-stopped
user: "1000:1000"
ports:
- "4533:4533"
environment:
ND_LOGLEVEL: info
ND_SCANSCHEDULE: 1h
ND_TRANSCODINGCACHESIZE: 1024M
ND_SESSIONTIMEOUT: 24h
ND_ENABLESHARING: "true"
ND_LASTFM_ENABLED: "true"
volumes:
- ./data:/data
- /mnt/music:/music:ro
A few things to call out in there. The :ro on the music volume mounts your library read-only inside the container — Navidrome never needs to write to your music files, and this stops bad config from ever scrambling them. The user: "1000:1000" line runs the container as your normal Pi user, which avoids the permissions bug that ate two hours of my life the first time I did this. If you don't pin the UID, Docker runs as root inside the container and writes files to ./data that your user can't read later when you want to back them up.
Fire it up:
docker compose up -d
docker compose logs -f
When you see Navidrome server is accepting requests, hit Ctrl+C. The server keeps running in the background.
Step 6 → Log into the web UI
In a browser on the same network:
http://navidrome.local:4533
You'll create the admin account on first load. Pick a real password. Once you're in, Navidrome immediately starts indexing whatever's at /mnt/music. Empty drive = empty dashboard. Time to fill it.
How to load your music without losing your mind
Navidrome reads ID3 tags, not filenames. This trips up everyone. Your perfectly named folders mean nothing if the tags inside the files are garbage.
Before you copy a single MP3 to the Pi, run your library through MusicBrainz Picard on your laptop. It's free, cross-platform, and pulls correct metadata from the MusicBrainz database. One evening with Picard will save you weeks of "why is Radiohead listed three times" frustration later.
Once tags are clean, push the files over with rsync:
rsync -avh --progress /path/to/local/music/ [email protected]:/mnt/music/
A 200 GB library takes maybe two hours over gigabit Ethernet. Walk away, drink a coffee.
Prefer drag-and-drop? Install Samba on the Pi:
sudo apt install -y samba
sudo nano /etc/samba/smb.conf
Append:
[music]
path = /mnt/music
browseable = yes
writable = yes
guest ok = no
valid users = yourusername
Then:
sudo smbpasswd -a yourusername
sudo systemctl restart smbd
Now smb://navidrome.local/music mounts as a network drive on Mac/Windows and you can drag folders straight in.
The mobile app situation — and why Symfonium changed my mind
Navidrome speaks the Subsonic API, which means dozens of clients work with it. I tested six of them. Here's what's actually worth your time:
Android — Symfonium ($5, one-time). I was deeply skeptical of paying for a music app. I bought it after two days of struggling with the free options. Worth every cent. The UI is gorgeous, gapless playback works perfectly, offline caching is set-and-forget, Android Auto integration is flawless. This is the one app that made me stop missing Spotify.
Android — Tempo (free, open source). If $5 is a hard no, Tempo is the best free option. Material You design, looks great, doesn't have Symfonium's polish but it's genuinely good.
iOS — Amperfy (free, open source). Clean, fast, gapless, offline downloads. The default iOS recommendation. I use this on my iPad.
Desktop — Feishin. Cross-platform desktop client that feels like a real music app. The web UI is also excellent though, so try it before installing anything.
To connect any of them, the settings are identical:
- Server:
http://navidrome.local:4533 - Username: your admin login
- Password: your admin password
That's it. No accounts, no signups, no algorithm trying to push you toward whatever the label paid for this week.
Stream from anywhere with Tailscale
You will absolutely want this. Music at home is nice. Music in the car, at the gym, on a plane — that's the whole point.
Do not port-forward 4533. Do not expose Navidrome to the public internet. Use Tailscale instead, which builds a private encrypted network between your devices. Free for personal use, takes 10 minutes.
On the Pi:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
It prints a URL. Open it on your laptop, log in with Google or email, and the Pi joins your tailnet. Install the Tailscale app on your phone, log in with the same account, and now Symfonium can reach the Pi at its Tailscale IP (a 100.x.x.x address) from anywhere on Earth.
Enable MagicDNS in the Tailscale admin console and you can use http://navidrome:4533 instead of an IP. Cleaner.
I tested this on a flight last month. LTE on the runway, Symfonium connected, Opus 96 kbps transcoding used about 40 MB an hour. Played my entire flight without a hiccup.
Backups, because hard drives die
Two things need backing up:
- The music files themselves — these are irreplaceable if you ripped your own CDs. Mirror to a second drive.
- The
~/navidrome/datadirectory — holds your database, play counts, ratings, playlists, user accounts. Tiny but precious.
Set a nightly cron job:
crontab -e
Append:
0 3 * * * rsync -avh --delete /home/yourusername/navidrome/data/ /mnt/backup/navidrome-data/
Every month, run the update:
cd ~/navidrome
docker compose pull
docker compose up -d
docker image prune -f
That's it for maintenance. I check on mine maybe twice a year.
What to do right now
Order the parts tonight. They arrive in two days. By Saturday afternoon you'll have your own music server, and Sunday morning you'll cancel Spotify with a smug little smile.
If you're already past the "should I do this" phase, the one decision that matters is tag your library with Picard before you copy anything to the Pi. Skip that step and you'll spend three weekends fixing metadata in the Navidrome UI. Do it once on your laptop and you'll never think about it again.
The whole thing pays for itself in 9 months versus Spotify Premium. After that, it's free streaming of your own music, forever, on hardware you own. The only thing I miss is Discover Weekly, and frankly — my library has 4,000 albums in it. I have plenty to discover.
POST TITLE
I Cancelled Spotify and Built My Own on a Raspberry Pi 5
SHORT DESCRIPTION (Excerpt)
Full walkthrough of building a self-hosted music server with Navidrome on a Pi 5. Stream your own library to any device — beautiful UI, real mobile apps, no subscription.
CATEGORY
Guide
TAGS (comma separated)
raspberry pi 5, navidrome, self-hosted, music server, spotify alternative, docker, subsonic, symfonium, tailscale, homelab
SEO SETTINGS
SEO TITLE (max 60 chars)
Navidrome on Raspberry Pi 5: Self-Hosted Spotify Guide
Character count: 53/60
META DESCRIPTION (max 160 chars)
Build a self-hosted Spotify on a Raspberry Pi 5 with Navidrome. Step-by-step setup, best mobile apps, and remote streaming via Tailscale.
Character count: 137/160