Post

Never Thought That Making A Self Hosted Spotify Would Be So Easy

Never Thought That Making A Self Hosted Spotify Would Be So Easy

Never Thought That Making A Self Hosted Spotify Would Be So Easy

Introduction

The modern music streaming landscape presents DevOps engineers with an intriguing challenge: How do we reclaim control of our music libraries while maintaining the convenience of commercial services like Spotify? As professionals who automate infrastructure and optimize systems daily, the idea of self-hosting a music streaming solution might seem daunting at first glance. Yet the reality is strikingly different.

Commercial music platforms come with inherent limitations - recurring subscription costs, algorithmic control over your listening experience, and privacy concerns about your musical preferences. For homelab enthusiasts and infrastructure professionals, these constraints spark legitimate questions: Why can’t we apply our expertise in containerization, networking, and automation to create a superior, personalized music ecosystem?

This comprehensive guide demonstrates how to build a robust self-hosted Spotify alternative using battle-tested open-source tools:

  • Automated music acquisition with yt-dlp/yubal
  • Subsonic-compatible server via Navidrome
  • Mobile client through Symfonium
  • Secure remote access using Tailscale

You’ll learn how these components integrate into a cohesive system that delivers:

  • Complete ownership of your music library
  • Zero recurring costs after initial setup
  • Cross-device synchronization
  • Enterprise-grade security
  • Customizable metadata management

For DevOps engineers, this project provides practical experience with:

  • Container orchestration (Docker)
  • Secure tunnel implementation (Tailscale)
  • Automated workflow design
  • Media server optimization
  • Mobile-device integration

Let’s dismantle the complexity myth surrounding self-hosted music solutions and build an enterprise-grade streaming platform that puts you in control.

Understanding the Components

Architectural Overview

Our self-hosted Spotify alternative combines four specialized components into a cohesive system:

1
2
3
[Music Sources] → [yt-dlp/yubal] → [File Storage] → [Navidrome Server] 
                     ↑                   ↓
[Metadata Services] ←                   → [Symfonium Client] ↔ [Tailscale VPN]

Core Technologies

1. yt-dlp/yubal (Media Acquisition)

  • Purpose: Automated YouTube audio extraction and metadata tagging
  • Key Features:
    • YouTube-to-MP3 conversion
    • ID3 tag population from MusicBrainz
    • File organization using defined schemas
  • Technical Specs:
    • Python-based (3.8+)
    • FFmpeg dependency for audio conversion
    • MusicBrainz API integration

2. Navidrome (Media Server)

  • Purpose: Subsonic-compatible music streaming server
  • Key Features:
    • Multi-user support with granular permissions
    • Transcoding (MP3, AAC, FLAC, OPUS)
    • Last.fm scrobbling integration
    • RESTful API for third-party clients
  • Technical Specs:
    • Go language implementation
    • SQLite/PostgreSQL storage options
    • Docker-friendly deployment

3. Symfonium (Mobile Client)

  • Purpose: Feature-rich Android music player
  • Key Features:
    • Subsonic protocol support
    • Offline caching
    • Material Design UI
    • Chromecast/Auto integration
  • Technical Specs:
    • Android 6.0+ compatible
    • Local/remote library unification

4. Tailscale (Secure Networking)

  • Purpose: Zero-config VPN for secure remote access
  • Key Features:
    • WireGuard-based encryption
    • NAT traversal (STUN)
    • Cross-platform support
    • ACL management
  • Technical Specs:
    • User-space networking stack
    • DERP relay protocol

Addressing the Recommendation Challenge

The Reddit comment regarding recommendation engines highlights a legitimate concern in self-hosted solutions. While Navidrome doesn’t include AI-driven recommendations like Spotify’s Discover Weekly, we can implement alternative approaches:

  1. Last.fm Integration:
    1
    2
    3
    4
    
    # Navidrome configuration snippet
    ND_SCROBBLER_LASTFM_ENABLED=true
    ND_SCROBBLER_LASTFM_APIKEY=your_api_key
    ND_SCROBBLER_LASTFM_SECRET=your_shared_secret
    
  2. MusicBrainz Tagging:
    1
    2
    3
    4
    
    # yubal command with enhanced metadata
    yt-dlp --extract-audio --audio-format mp3 --embed-thumbnail \
           --parse-metadata "title:%(title)s" --add-metadata \
           --exec "beet import -q {}"
    
  3. External Services:
    • ListenBrainz (open-source tracking)
    • Funkwhale (federated discovery)
    • Plex-style “Similar Artists” metadata

Prerequisites

Hardware Requirements

ComponentMinimum SpecsRecommended Specs
CPUDual-coreQuad-core
RAM2GB4GB+
Storage100GB HDD1TB SSD
Network10Mbps100Mbps+

Software Requirements

  1. Operating System:
    • Ubuntu Server 22.04 LTS (recommended)
    • Debian 11+
    • Fedora Server 36+
  2. Core Dependencies:
    1
    2
    3
    
    # Ubuntu/Debian
    sudo apt install -y ffmpeg sqlite3 python3-pip \
                       docker-ce docker-ce-cli containerd.io
    
  3. Containerization:
    • Docker 20.10.17+
    • Docker Compose 2.6.0+
  4. Security:
    • UFW firewall configured
    • SSH key authentication
    • Non-root docker user

Network Considerations

  1. Port Requirements: | Service | Port | Protocol | Exposure | |————–|——-|———-|———-| | Navidrome | 4533 | TCP | Local | | Tailscale | 41641 | UDP | Public | | yt-dlp | None | - | None |

  2. Security Configuration:

    1
    2
    
    sudo ufw allow 41641/udp comment 'Tailscale'
    sudo ufw allow from 10.0.0.0/8 to any port 4533 proto tcp comment 'Navidrome'
    

Installation & Setup

1. Tailscale Deployment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Add Docker Compose service
services:
  tailscale:
    image: tailscale/tailscale:v1.44.0
    container_name: tailscale
    volumes:
      - "./tailscale:/var/lib/tailscale"
      - "/dev/net/tun:/dev/net/tun"
    environment:
      - TS_USERSPACE=true
      - TS_STATE_DIR=/var/lib/tailscale
    cap_add:
      - net_admin
      - sys_module
    network_mode: host
    restart: unless-stopped

Initialize Tailscale:

1
docker exec -it tailscale tailscale up --login-server https://controlplane.tailscale.com

2. Navidrome Installation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# docker-compose.yaml
services:
  navidrome:
    image: deluan/navidrome:0.50.2
    container_name: navidrome
    environment:
      - ND_LOGLEVEL=info
      - ND_SESSIONTIMEOUT=24h
      - ND_BASEURL=/music
    volumes:
      - "/music:/music"
      - "./navidrome:/data"
    ports:
      - "4533:4533"
    restart: unless-stopped

Verify installation:

1
docker ps --filter name=navidrome --format "table $CONTAINER_ID\t$CONTAINER_NAMES\t$CONTAINER_STATUS\t$CONTAINER_PORTS"

3. yt-dlp/yubal Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Python virtual environment setup
python3 -m venv ytdlp_env
source ytdlp_env/bin/activate
pip install yt-dlp beets python-magic

# Example download script
#!/bin/bash
yt-dlp --format bestaudio --extract-audio \
       --audio-format mp3 --audio-quality 0 \
       --embed-thumbnail --add-metadata \
       --parse-metadata "title:%(title)s" \
       --output "/music/Downloads/%(title)s.%(ext)s" \
       $1

# Automated tagging with beets
beet -vv import -q /music/Downloads/*

4. Symfonium Mobile Setup

  1. Install Symfonium from F-Droid or Play Store
  2. Configure connection:
    • Server URL: https://[Tailscale IP]:4533
    • Connection Type: Subsonic
    • Username/Password: (Navidrome credentials)

Configuration & Optimization

1
2
3
4
5
6
# Advanced environment variables
ND_ENABLETRANSCODINGCONFIG=true
ND_TRANSCODINGCACHESIZE=1000MB
ND_IMAGECACHESIZE=2000MB
ND_SESSIONTIMEOUT=720h
ND_SCROBBLER_LASTFM_ENABLED=true

Security Hardening

  1. Tailscale ACLs:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    // tailscale.acl.json
    {
      "acls": [
        {
          "action": "accept",
          "src": ["autogroup:members"],
          "dst": ["*:4533"]
        }
      ]
    }
    
  2. Navidrome Authentication:
    1
    2
    3
    
    # Enable secure cookies
    ND_SESSIONCOOKIE_SECURE=true
    ND_SESSIONCOOKIE_HTTPONLY=true
    

Performance Optimization

  1. Transcoding Settings:
    1
    2
    3
    4
    5
    6
    
    <!-- navidrome.xml -->
    <Transcoding>
      <MaxBitrate>320</MaxBitrate>
      <PreferredFormat>mp3</PreferredFormat>
      <ThreadCount>4</ThreadCount>
    </Transcoding>
    
  2. Database Optimization:
    1
    
    docker exec -it navidrome sqlite3 /data/navidrome.db "PRAGMA journal_mode=WAL;"
    

Usage & Operations

Daily Workflow

  1. Adding New Music:
    1
    
    ./add_music.sh "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    
  2. Library Rescan:
    1
    
    curl -X POST -u "admin:password" http://localhost:4533/api/startScan
    

Backup Strategy

1
2
3
4
5
6
# Database backup script
#!/bin/bash
sqlite3 /data/navidrome.db ".backup /backups/navidrome-$(date +%F).db"

# Music archive with borg
borg create --stats /backups/music::music-{now} /music

Monitoring

1
2
3
4
5
# Systemd service monitoring
systemctl status docker-navridrome

# Log inspection
docker logs --tail 50 --follow --timestamps navidrome

Troubleshooting

Common Issues

Problem: Symfonium connection failures
Solution:

1
2
3
4
5
# Verify Tailscale status
tailscale status

# Check Navidrome accessibility
curl -v http://localhost:4533/ping

Problem: Metadata mismatches
Solution:

1
2
# Manual beet correction
beet modify -y artist="Correct Artist" title="Proper Title" path=/music/IncorrectFile.mp3

Problem: Transcoding failures
Solution:

1
2
3
4
5
# Verify FFmpeg in container
docker exec -it navidrome ffmpeg -version

# Check supported formats
ffmpeg -formats | grep mp3

Conclusion

Building a self-hosted Spotify alternative provides more than just music independence - it’s a masterclass in modern DevOps practices. Through this implementation, we’ve achieved:

  1. Infrastructure Control: Complete ownership of our media stack
  2. Security: Zero-trust networking via Tailscale
  3. Automation: Hands-free music acquisition pipeline
  4. Performance: Optimized streaming architecture
  5. Cost Efficiency: Elimination of recurring subscriptions

While recommendation engines remain an area for improvement, the combination of Last.fm integration and MusicBrainz tagging provides a solid foundation for discovery. For those seeking advanced functionality, consider exploring:

The true value lies not just in music freedom, but in the infrastructure expertise gained through implementing a production-grade media streaming platform. Your self-hosted music solution now stands as a testament to modern DevOps principles - secure, automated, and entirely under your control.

This post is licensed under CC BY 4.0 by the author.