Host Your Own Music Library

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:

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:

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.

Tip: Point your music volume to a read-only mount (/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.

Watch out: Very large libraries (50,000+ tracks) can make Navidrome's initial scan slow. On first load, it indexes every file. Be patient. Pin the container logs to watch progress: docker compose logs -f navidrome

Accessing 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

```