How to Self-Host Mopidy with Docker Compose

Unlike Most Music Servers, Mopidy Is a Backend

Mopidy doesn’t ship with a fancy web UI or mobile app. It’s a music server daemon that speaks the MPD (Music Player Daemon) protocol and exposes an HTTP API. You choose your own frontend — dozens of MPD clients, web UIs, and mobile apps work with it.

This modular design is Mopidy’s strength and its weakness. You get exactly the features you want through extensions, but you assemble the stack yourself. If you want a batteries-included experience, look at Navidrome. If you want a customizable audio backend that aggregates multiple music sources into a single interface, Mopidy is the tool.

FeatureDetails
LicenseApache-2.0
ProtocolMPD compatible
ArchitecturePlugin-based (extensions)
Local filesYes (via Mopidy-Local)
SpotifyYes (via Mopidy-Spotify, requires Premium)
SoundCloudYes (via Mopidy-SoundCloud)
YouTubeYes (via Mopidy-YouTube)
Web UIVia extensions (Iris, Mopidy-Muse, Moped)
Mobile clientsAny MPD client (M.A.L.P., MPDroid)
Audio outputALSA, PulseAudio, GStreamer sinks, Snapcast

Prerequisites

  • A Linux server (Ubuntu 22.04+ or Debian 12+ recommended)
  • Docker and Docker Compose installed (Docker Compose Basics)
  • 256 MB of free RAM
  • Your music library accessible on the host filesystem (for local playback)
  • Audio hardware connected to the server (for direct playback) or a Snapcast setup (for network playback)

Docker Compose Configuration

Create a directory for Mopidy:

mkdir -p /opt/mopidy/{config,data,music}

Create /opt/mopidy/docker-compose.yml:

services:
  mopidy:
    image: giof71/mopidy:0.4.23
    container_name: mopidy
    restart: unless-stopped
    ports:
      - "6600:6600"   # MPD protocol
      - "6680:6680"   # HTTP / Web UI
    volumes:
      - ./config:/config
      - ./data:/var/lib/mopidy
      - ./music:/music:ro
    environment:
      PUID: 1000
      PGID: 1000
      TZ: "America/New_York"
    # For direct audio output (ALSA), uncomment:
    # devices:
    #   - /dev/snd:/dev/snd
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:6680"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 20s

Create the configuration file /opt/mopidy/config/mopidy.conf:

[core]
# Cache and data directories (inside container)
cache_dir = /var/lib/mopidy/cache
config_dir = /config
data_dir = /var/lib/mopidy/data

[logging]
verbosity = 0

[audio]
# Default: software mixer
# For ALSA direct output, change to:
# output = alsasink device=default
output = autoaudiosink

[file]
enabled = true
media_dirs = /music
show_dotfiles = false
excluded_file_extensions =
  .cue
  .directory
  .html
  .jpeg
  .jpg
  .log
  .nfo
  .pdf
  .png
  .txt
  .zip

[http]
enabled = true
hostname = 0.0.0.0
port = 6680
# Allowed origins for CORS (add your domain)
allowed_origins =

[mpd]
enabled = true
hostname = 0.0.0.0
port = 6600

[local]
enabled = true
media_dir = /music

Start the stack:

cd /opt/mopidy && docker compose up -d

After starting, trigger a local library scan:

docker exec mopidy mopidy local scan

Initial Setup

  1. Open http://your-server-ip:6680 in your browser
  2. You’ll see the Mopidy HTTP interface — a list of installed web extensions
  3. If no web extensions are installed, you’ll see a basic JSON API listing
  4. Install a web client extension (see Configuration below)

The MPD interface is available on port 6600. Any MPD client can connect immediately.

Configuration

Web UI: Install Iris

Mopidy’s most popular web frontend is Iris — a modern, responsive web UI for browsing and playing music:

To add Iris, build a custom Docker image or use a pre-configured image. With the giof71/mopidy image, set the following environment variable:

environment:
  MOPIDY_IRIS: "yes"

After restarting, access Iris at http://your-server-ip:6680/iris/.

Spotify Integration

Requires a Spotify Premium account and a Spotify Developer application:

  1. Create an app at developer.spotify.com
  2. Note the Client ID and Client Secret
  3. Add to mopidy.conf:
[spotify]
enabled = true
username = your_spotify_username
password = your_spotify_password
client_id = your_client_id
client_secret = your_client_secret
bitrate = 320

Note: Mopidy-Spotify uses libspotify, which Spotify deprecated in 2022. The extension still works as of early 2026 but may break without notice. For reliable Spotify integration, consider using Spotifyd alongside Mopidy.

SoundCloud Integration

Add to mopidy.conf:

[soundcloud]
enabled = true
auth_token = your_soundcloud_auth_token

Get your auth token from Mopidy-SoundCloud’s authentication page.

Audio Output Options

OutputUse CaseConfiguration
ALSA (direct)Server connected to speakersoutput = alsasink device=default
PulseAudioDesktop Linux integrationoutput = pulsesink
SnapcastMulti-room audiooutput = audioresample ! audio/x-raw,rate=48000 ! audioconvert ! wavenc ! filesink location=/tmp/snapfifo
HTTP streamStream to any browserUse Mopidy-Stream extension

For multi-room audio with Snapcast, pipe Mopidy’s output to a Snapcast FIFO:

volumes:
  - /tmp/snapfifo:/tmp/snapfifo

Advanced Configuration

Multiple Music Sources

Mopidy’s architecture lets you aggregate multiple sources into a single library:

[file]
enabled = true
media_dirs =
  /music|Local Music
  /podcasts|Podcasts
  /audiobooks|Audiobooks

Each source appears as a separate browse category in the UI.

Scrobbling (Last.fm)

Track your listening history with Last.fm:

[scrobbler]
enabled = true
username = your_lastfm_username
password = your_lastfm_password

Alternatively, use Maloja for self-hosted scrobbling.

Snapcast Multi-Room Setup

For synchronized multi-room audio, add Snapcast alongside Mopidy:

services:
  mopidy:
    image: giof71/mopidy:0.4.23
    container_name: mopidy
    restart: unless-stopped
    ports:
      - "6600:6600"
      - "6680:6680"
    volumes:
      - ./config:/config
      - ./data:/var/lib/mopidy
      - ./music:/music:ro
      - snapfifo:/tmp
    environment:
      PUID: 1000
      PGID: 1000

  snapserver:
    image: ghcr.io/badaix/snapcast:0.28.0
    container_name: snapserver
    restart: unless-stopped
    ports:
      - "1704:1704"   # Snapcast stream
      - "1705:1705"   # Snapcast control
      - "1780:1780"   # Snapcast web UI
    volumes:
      - snapfifo:/tmp

volumes:
  snapfifo:

Set Mopidy’s audio output to the Snapcast FIFO pipe in mopidy.conf.

Reverse Proxy

Configure your reverse proxy to forward to port 6680 for the web UI:

location / {
    proxy_pass http://localhost:6680;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

WebSocket support is required for Iris and other web frontends. See our Reverse Proxy Setup guide.

Backup

Back up the /config and /data directories:

  • /config/mopidy.conf — all your settings, credentials, extensions
  • /data — local library database, playlists, play history
tar czf mopidy-backup-$(date +%Y%m%d).tar.gz /opt/mopidy/config /opt/mopidy/data

Your music files (/music) should be backed up separately. See our Backup Strategy guide.

Troubleshooting

No audio output

Symptom: Tracks play (progress bar moves) but no sound.

Fix: Check your audio output configuration:

  1. For ALSA: ensure /dev/snd is passed to the container and the output setting is alsasink
  2. For PulseAudio: mount the PulseAudio socket into the container
  3. For Snapcast: verify the FIFO pipe exists at /tmp/snapfifo
# Test audio inside the container
docker exec mopidy gst-launch-1.0 audiotestsrc ! autoaudiosink

Local library scan finds no tracks

Symptom: mopidy local scan completes but reports 0 tracks.

Fix: Verify:

  1. Music directory is mounted correctly: docker exec mopidy ls /music
  2. File extensions are supported (MP3, FLAC, OGG, M4A)
  3. The media_dir in mopidy.conf matches the volume mount path
  4. File permissions allow the container user to read the files

MPD clients can’t connect

Symptom: MPD clients (ncmpcpp, M.A.L.P.) fail to connect on port 6600.

Fix: Ensure the MPD section in mopidy.conf binds to 0.0.0.0:

[mpd]
hostname = 0.0.0.0
port = 6600

And port 6600 is mapped in Docker Compose. Restart after changes.

Spotify extension not loading

Symptom: Spotify sources don’t appear in the library.

Fix: Check container logs for Spotify-related errors:

docker logs mopidy 2>&1 | grep -i spotify

Common causes: expired credentials, libspotify compatibility issues, missing client_id/client_secret. Regenerate your Spotify Developer app credentials if expired.

Resource Requirements

MetricIdlePlaying (1 stream)Scanning library
RAM80-150 MB100-200 MB200-400 MB
CPUMinimalLowMedium (during scan)
Disk30 MB (app)+ music library+ library database

Mopidy is extremely lightweight. It runs comfortably on a Raspberry Pi 4, an N100 mini PC, or alongside other services on any Docker host.

Verdict

If you want a customizable music backend that speaks MPD, plays local files, and optionally aggregates Spotify, SoundCloud, and YouTube into a single interface, Mopidy is the right tool. The extension ecosystem lets you build exactly the music server you want — no more, no less.

The trade-off is assembly. Navidrome gives you a working music server in one docker compose up. Mopidy gives you a foundation that you configure through extensions, config files, and client selection. Choose Mopidy if you already use MPD clients, want multi-room audio with Snapcast, or need to aggregate multiple streaming sources. Choose Navidrome if you want a simple, self-contained music streaming server.

FAQ

Is Mopidy the same as MPD? No. MPD (Music Player Daemon) is a separate project. Mopidy implements the MPD protocol, so MPD clients work with both, but Mopidy is written in Python and supports extensions for streaming services. MPD is C-based and focused on local playback.

Can I use Mopidy without Spotify? Yes. Mopidy-Spotify is an optional extension. Mopidy works with local files only, SoundCloud, YouTube, or any combination of its 100+ available extensions.

Does Mopidy support gapless playback? Yes, through GStreamer. Gapless playback works with local files and most streaming sources. Enable it in the audio configuration if not working by default.

How does Mopidy compare to Navidrome? Navidrome is a standalone Subsonic-compatible music server with a polished web UI. Mopidy is an extensible backend that requires choosing your own frontend. Navidrome is easier to set up; Mopidy is more flexible. See our Navidrome vs Jellyfin comparison for streaming server options.

Comments