Host Your Own Music Library
I got tired of streaming subscriptions, algorithmic playlists, and losing access to music I'd bought. So I self-hosted my entire music collection—and now I stream it from my homelab to any device. This guide walks you through building your own music library using Navidrome, with lossless audio support, zero licensing restrictions, and complete ownership over your catalog.
Why Self-Host Music?
Spotify, Apple Music, and Tidal are convenient, but they're also rental agreements. Cancel your subscription, and your playlist vanishes. I prefer keeping my music on hardware I control. A self-hosted music server lets you:
- Keep FLAC and lossless formats — streaming services compress audio to MP3 or AAC. If you own high-quality files, self-hosting preserves them.
- Stream anywhere securely — access your library over your home network, VPN, or Tailscale without sharing with a third party.
- Use any client — iOS, Android, web, desktop—there are dozens of compatible apps.
- Escape the algorithm — your collection is exactly what you curate, not what the algorithm suggests.
- Build a permanent archive — years from now, your music is still there, unchanged, under your control.
What You'll Need
I run this on a modest setup: a small VPS with 2GB RAM and 500GB storage. If you're serving local network access only, a Raspberry Pi 4 works fine. For remote streaming, I recommend at least 50 Mbps upload if you're on residential internet, or better yet, a RackNerd KVM VPS with generous bandwidth.
Here's what you need:
- A server or VPS running Linux (Ubuntu 22.04 or newer)
- Docker and Docker Compose (or you can install Navidrome directly)
- At least 200GB free space for your music collection
- A reverse proxy like Caddy for HTTPS (optional but recommended)
- Your music files organized in a standard structure (artist/album/track)
Setting Up Navidrome with Docker Compose
Navidrome is my preferred choice: lightweight, fast, and it speaks the Subsonic API so you can use apps built for Subsonic servers. Here's how I set it up on Docker.
version: '3.8'
services:
navidrome:
image: deluan/navidrome:latest
container_name: navidrome
ports:
- "4533:4533"
environment:
ND_LOGLEVEL: info
ND_BASEURL: https://music.yourdomain.com
ND_ENABLESTARRATING: "true"
ND_ENABLEEXTERNALSERVICES: "false"
ND_MAXOUTPUTBITHRATE: "192"
volumes:
- ./navidrome-data:/data
- /mnt/music:/music:ro
restart: unless-stopped
networks:
- media-net
caddy:
image: caddy:2-alpine
container_name: caddy-music
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./caddy-data:/data
- ./caddy-config:/config
networks:
- media-net
restart: unless-stopped
networks:
media-net:
driver: bridge
Save this as docker-compose.yml in a new directory. Create a Caddyfile in the same directory for reverse proxy configuration:
music.yourdomain.com {
reverse_proxy navidrome:4533
encode gzip
}
Replace yourdomain.com with your actual domain. Then start the services:
docker compose up -d
Navidrome will create a database and admin UI at http://localhost:4533. On first launch, you'll create an admin account.
/music:ro). This prevents accidental deletion of your library from inside the container. Store your actual music files on a separate drive—ideally with backups.Organizing Your Music Files
Navidrome works best with a clean directory structure. I organize mine like this:
/mnt/music/
├── Radiohead/
│ ├── OK Computer/
│ │ ├── 01 - Airbag.flac
│ │ ├── 02 - Paranoid Android.flac
│ │ └── ...
│ └── In Rainbows/
├── Björk/
│ ├── Homogenic/
│ │ └── ...
└── ...
If your library is scattered across folders, use MusicBrainz Picard or a command-line tool like `beets` to organize it automatically:
sudo apt install beets
mkdir -p ~/.config/beets
cat > ~/.config/beets/config.yaml << 'EOF'
directory: /mnt/music
import:
write: yes
resume: ask
autotag: yes
timid: no
plugins: [replaygain, fetchart]
EOF
beets import /path/to/chaotic/music/dump
Beets will match your files against MusicBrainz, embed metadata, and organize them correctly. This takes time but pays off immediately—Navidrome reads tags and displays albums, artists, and genres cleanly.
docker compose logs -f navidromeAccessing Your Library Remotely
For local network streaming, just point your client app to your server's IP on port 4533. For remote access, I use Tailscale. It's simpler and safer than port-forwarding:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Once connected, your Navidrome server is accessible via its Tailscale IP (something like 100.x.x.x:4533
Popular Navidrome clients I use:
- Web: Built-in web UI (Navidrome's own player)
- iOS: Subfeed, Synology DS audio (if you're running Synology), or SubPlayer
- Android: Subtracks, DSub, or Symfonium
- Desktop: Sublime Music (Linux), or web client
All of these speak the Subsonic API, which Navidrome implements. They'll detect your server automatically if you configure them with the base URL.
Tweaking Performance and Quality
By default, Navidrome transcodes on-the-fly for bandwidth savings. That's great for mobile, but for high-quality local streaming, I disable it:
In the environment variables, set:
ND_MAXOUTPUTBITHRATE: "0" # Disable transcoding
ND_ENABLEEXTERNALSERVICES: "false" # No last.fm or listenbrainz (privacy)
ND_ENABLESTARRATING: "true" # Enable 5-star ratings
For a remote setup with limited bandwidth, keep ND_MAXOUTPUTBITHRATE at a reasonable value like 192 kbps (mobile) or 320 kbps (desktop). The client can request lower bitrates if needed.
Monitor memory and CPU:
docker stats navidrome
On my 2GB VPS, Navidrome uses about 300MB RAM and negligible CPU at idle. Serving five simultaneous streams uses maybe 800MB and 15% CPU.
Backing Up Your Library
Your Navidrome data directory contains the database and metadata. Back it up regularly:
docker exec navidrome sqlite3 /data/navidrome.db ".backup /data/backup-$(date +%s).db"
tar -czf ~/navidrome-backup-$(date +%Y%m%d).tar.gz ./navidrome-data/
I run this weekly in a cron job and push to cold storage. Your actual music files should be on redundant storage (RAID 1 or 5) or backed up separately. Never rely on a single copy.
Next Steps
Once your music library is running, consider:
- Add metadata artwork: Use Picard or Navidrome's built-in fetcher to grab album art.
- Set up a VPN: Instead of Tailscale, use WireGuard for more control over your remote access.
- Explore playlists: Create static and dynamic playlists in Navidrome. They sync to compatible clients.
- Mirror to a NAS: If you own a Synology or QNAP, run Navidrome there instead for better hardware efficiency.
A self-hosted music library is one of the most satisfying pieces of a homelab—you get to use your own collection without compromise, and it costs almost nothing to run. Start with a single drive, organize your files, and spin up Navidrome. In an afternoon, you'll have better audio ownership than any subscription ever gave you.
Discussion