Spotify raised prices again. That album you had saved? Region-locked last month. Your "Discover Weekly" is half ads for podcasts you never asked for. And the artist payout? $0.003 per stream. The math doesn't work for anyone except the platform.
There's another way. A way where you own the files, control the catalog, and discover music through a community that's been sharing tracks since 2001. Soulseek — the original peer-to-peer music network — still runs today. Pair it with a modern streaming server like Navidrome, and you get a Spotify replacement where every byte lives on hardware you control.
I've been running this stack for two years. My library sits at 15,000 tracks, grows every week, and costs nothing beyond the electricity to keep a few containers running. This guide covers the complete pipeline: discovery with Soulseek, automation with slskd and Lidarr, and streaming with Navidrome to every device you own.
What You're Building
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Soulseek │ │ Lidarr │ │ Navidrome │
│ Network │────▶│ (Management) │────▶│ (Streaming) │
│ (slskd) │ │ + slskd │ │ (Docker) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
Downloads Organized Library Your Phone
(NAS/Local) (/music) CarPlay/Web
Four components:
- slskd — Soulseek client running headless in Docker, handles all downloads
- Lidarr — Music management: monitors artists, grabs albums, renames and tags files
- Navidrome — Streaming server, Subsonic-compatible, serves to any client
- Clients — Web UI, DSub (Android), Ultrasonic, or any Subsonic app
Total time to set up: about 45 minutes. Total cost: $0.
Step 1: slskd — The Soulseek Daemon
Soulseek is a peer-to-peer file sharing network built specifically for music. Unlike BitTorrent, it's designed around conversations, wishlists, and direct user-to-user sharing. slskd is a modern, headless Soulseek client that runs in Docker and exposes a clean web UI.
Docker Compose
services:
slskd:
image: slskd/slskd:latest
container_name: slskd
ports:
- "5030:5030"
volumes:
- ./slskd:/app/data
- /mnt/nas/music/downloads:/downloads
environment:
- SLSKD_REMOTE_CONFIGURATION=true
restart: unless-stopped
Key Configuration
After first start, edit data/slskd.yml:
soulseek:
username: your_username
password: your_password
listen_port: 50300
description: "Homelab share | slskd"
directories:
downloads: /downloads
incomplete: /downloads/.incomplete
shares:
directories:
- /mnt/nas/music/library
filters:
- \.ini$
- Thumbs\.db$
- \.DS_Store$
web:
port: 5030
authentication:
disabled: false
username: admin
password: your_secure_password
logging:
level: Information
Port forwarding: Soulseek requires an open listening port for searches and downloads to work properly. Forward TCP port 50300 on your router to your slskd host. Without this, you'll only be able to download from users who can connect to you — severely limiting results.
Account creation: If you don't have a Soulseek account, register at https://www.slsknet.org/news/node/682. Pick a username and use it in the config. The network is small enough that reputation matters — share what you download, and the community reciprocates.
Step 2: Lidarr — Automated Music Management
Lidarr is the *arr equivalent for music. It monitors artists, tracks album releases, and can automate downloads through slskd. While Lidarr doesn't have native Soulseek support, the slskd integration works through a custom script approach or manual grabbing.
Docker Compose (Add to Stack)
lidarr:
image: lscr.io/linuxserver/lidarr:latest
container_name: lidarr
ports:
- "8686:8686"
volumes:
- ./lidarr:/config
- /mnt/nas/music:/music
- /mnt/nas/music/downloads:/downloads
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
restart: unless-stopped
Folder Structure
Lidarr and Navidrome both expect a standard music folder layout:
/music
/Artist Name
/[Year] Album Name [Format]
01 - Track Title.flac
02 - Track Title.flac
cover.jpg
Critical: Set Lidarr's root folder to /music and its download client folder to /downloads. After Lidarr processes a download, it renames, tags, and moves files to the organized library path.
slskd + Lidarr Workflow
Since Lidarr doesn't natively support Soulseek, the typical workflow is:
- Lidarr monitors artists and flags wanted albums
- Manual or scripted search in slskd web UI using the wishlist feature
- slskd downloads to
/downloads - Lidarr import scans
/downloads, processes files, moves to/music - Navidrome rescans and the album appears in your library
For a more automated approach, community tools like soularr bridge Lidarr and slskd. It reads Lidarr's wanted list and automatically searches Soulseek:
soularr:
image: mrusse/soularr:latest
container_name: soularr
volumes:
- ./soularr:/data
- /mnt/nas/music/downloads:/downloads
environment:
- LIDARR_URL=http://lidarr:8686
- LIDARR_API_KEY=your_api_key
- SLSKD_URL=http://slskd:5030
- SLSKD_API_KEY=your_slskd_api_key
restart: unless-stopped
Step 3: Navidrome — Your Streaming Server
Navidrome is a Subsonic-compatible music server that's fast, lightweight, and dead simple. It indexes your library, serves a web player, and works with any Subsonic client.
Docker Compose (Add to Stack)
navidrome:
image: deluan/navidrome:latest
container_name: navidrome
ports:
- "4533:4533"
volumes:
- ./navidrome:/data
- /mnt/nas/music:/music:ro
environment:
- ND_SCANSCHEDULE=1h
- ND_LOGLEVEL=info
- ND_BASEURL=
restart: unless-stopped
Why read-only (:ro): Navidrome never needs to write to your music folder. Mounting it read-only prevents any accidental file changes. All Navidrome data (database, cache, settings) lives in ./navidrome.
Initial Setup
- Open
http://your-server:4533 - Create the first admin account
- Navidrome will scan
/musicautomatically - For large libraries (10,000+ tracks), the first scan takes 5-15 minutes
Transcoding Settings
Navidrome can transcode on the fly for mobile streaming. Default settings work for most, but if you're streaming to mobile over cellular, configure Opus or MP3 transcoding:
In the web UI: Admin → Players → [Your Player] → Transcoding
Recommended for mobile:
- Format: opus
- Bitrate: 128
- Result: ~40% smaller than MP3 320, transparent quality
Step 4: The Complete Docker Compose Stack
Here's everything wired together:
version: "3.8"
services:
slskd:
image: slskd/slskd:latest
container_name: slskd
ports:
- "5030:5030"
- "50300:50300"
volumes:
- ./slskd:/app/data
- /mnt/nas/music/downloads:/downloads
environment:
- SLSKD_REMOTE_CONFIGURATION=true
restart: unless-stopped
lidarr:
image: lscr.io/linuxserver/lidarr:latest
container_name: lidarr
ports:
- "8686:8686"
volumes:
- ./lidarr:/config
- /mnt/nas/music:/music
- /mnt/nas/music/downloads:/downloads
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
restart: unless-stopped
navidrome:
image: deluan/navidrome:latest
container_name: navidrome
ports:
- "4533:4533"
volumes:
- ./navidrome:/data
- /mnt/nas/music:/music:ro
environment:
- ND_SCANSCHEDULE=1h
- ND_LOGLEVEL=info
- ND_BASEURL=
restart: unless-stopped
# Optional: soularr for automated Soulseek searching
# soularr:
# image: mrusse/soularr:latest
# container_name: soularr
# volumes:
# - ./soularr:/data
# - /mnt/nas/music/downloads:/downloads
# environment:
# - LIDARR_URL=http://lidarr:8686
# - LIDARR_API_KEY=your_key
# - SLSKD_URL=http://slskd:5030
# - SLSKD_API_KEY=your_key
# restart: unless-stopped
Step 5: Client Setup — Stream Anywhere
Navidrome speaks the Subsonic API, which means almost any music client works. Here are the best options by platform:
Web (Any Device)
Navidrome's built-in web player is excellent. It supports playlists, gapless playback, and the full library view. Just open your server URL in a browser.
Android
- DSub — The classic Subsonic client. Stable, full-featured, offline sync. Free on F-Droid, paid on Play Store.
- Ultrasonic — Fork of DSub with modern UI. Free, open-source.
- Subtracks — Minimal, fast, Material Design. Good for clean library browsing.
Setup: Server URL = http://your-server:4533, username/password = your Navidrome credentials.
iOS
- play:Sub — The best iOS Subsonic client. Clean UI, CarPlay support, offline sync. One-time purchase (~$5).
- Substreamer — Free with ads, subscription to remove. Good for testing before buying play:Sub.
Desktop
- Sublime Music (Linux) — GTK client with album art and playlist support.
- Sonixd (Windows/Linux/macOS) — Modern Electron client, very polished.
- Web player — Works great in any browser.
CarPlay / Android Auto
- play:Sub (iOS) — Native CarPlay support
- DSub / Ultrasonic (Android) — Android Auto compatible
Step 6: Discovery Workflow
The biggest question people ask: "How do I find new music without Spotify's algorithm?"
Soulseek Discovery
- User browsing: Right-click any user → "Browse shares." See their full library. If someone has 5 albums you love, they probably have 50 more you'll like.
- Room chat: Join genre-specific rooms. Ask for recommendations. The community is small but knowledgeable.
- Wishlist: Add searches to your wishlist. slskd will notify when someone has what you're looking for.
Lidarr Monitoring
- Add artists you already love
- Lidarr tracks new releases automatically
- Use the "Monitor" toggle for specific albums or "Future" to catch everything
External Discovery
- RateYourMusic — Comprehensive user-generated ratings and lists. Export lists and search manually in slskd.
- Last.fm — Still works for scrobbling from Navidrome. Your listening history builds a taste profile.
- Bandcamp — Buy directly from artists, download FLAC, drop into your library. No DRM, ever.
Step 7: Reverse Proxy \u0026 SSL
Don't expose these services directly. Use a reverse proxy with SSL:
nginx:
image: nginx:alpine
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
restart: unless-stopped
Or use Nginx Proxy Manager (if you already run it) with these subdomains:
music.yourdomain.com→ Navidrome (4533)slsk.yourdomain.com→ slskd (5030)lidarr.yourdomain.com→ Lidarr (8686)
File Organization Tips
A clean library is everything. Here's my workflow:
-
slskd downloads to
/downloadswith original filenames -
Lidarr renames using the format:
{Artist}/{Album} ({Year})/{track:00} - {Title} -
Beets (optional but recommended) for extra tagging:
beet import /downloadsBeets uses MusicBrainz to verify tags, fetch album art, and fix metadata.
-
Navidrome rescans every hour automatically
Backups
Your library is irreplaceable. Back it up:
# Rsync to external drive or secondary NAS
rsync -avP /mnt/nas/music/ /mnt/backup/music/
# Or use rclone to cloud storage
rclone sync /mnt/nas/music remote:backup/music
Priority backup order:
- The music files themselves (largest, most irreplaceable)
- Lidarr config (
./lidarr— artist lists, wanted albums) - slskd config (
./slskd— shares, chat history) - Navidrome database (
./navidrome/navidrome.db— playlists, ratings, play counts)
Troubleshooting
"No search results in slskd" → Check port forwarding on 50300. Test with a port checker. Without an open port, Soulseek works in limited mode.
"Lidarr won't import downloads"
→ Check permissions. Lidarr runs as PUID/PGID. Ensure /downloads and /music are writable by that user. Check Lidarr's logs for "Import failed" messages.
"Navidrome shows empty library"
→ Verify the mount path. If Navidrome sees /music but it's empty, the Docker volume mount is wrong. Check with docker exec navidrome ls /music.
"Some files won't play" → Check format support. Navidrome supports FLAC, MP3, Ogg, Opus, AAC, and WMA. Very old or exotic formats (APE, TTA) may need conversion.
The Bottom Line
This stack replaces every streaming service you pay for. The upfront setup takes an evening. The ongoing cost is the electricity to run three containers — roughly $2-4 per month on a modern server.
What you get:
- Permanent ownership of every file
- No DRM, no region locks, no disappearing albums
- Community discovery through Soulseek's user-driven network
- Automated management via Lidarr
- Stream anywhere via Navidrome and Subsonic clients
- No monthly subscription beyond your hardware
The tradeoff is curation over convenience. You'll spend more time finding music than Spotify's algorithm would spend serving it to you. But you'll find music the algorithm never would have shown you — and you'll own it forever.
Start with Navidrome and a small test library. Add slskd when you're ready to grow. Wire in Lidarr when manual management gets tedious. This is a stack that scales with your commitment.
Got questions? The self-hosted music thread on r/selfhosted and the Navidrome Discord are active communities running similar setups.