How to Self-Host Funkwhale with Docker Compose
What Is Funkwhale?
Funkwhale is a self-hosted, federated music server. It lets you upload your music library, stream it from any device, create playlists, and — uniquely — share music across instances using ActivityPub (the same protocol behind Mastodon). It also supports podcast subscriptions. Think of it as a self-hosted Spotify for your own music collection, with social features built in.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 2 GB of RAM minimum (4 GB recommended)
- A dedicated domain or subdomain (e.g.,
music.example.com) — Funkwhale cannot run in a subdirectory - Ports 80 and 443 accessible (required for federation)
- A domain name with DNS configured
Docker Compose Configuration
Create a project directory:
mkdir -p /opt/funkwhale && cd /opt/funkwhale
Create a .env file:
# REQUIRED: Your Funkwhale domain (no protocol, no trailing slash)
FUNKWHALE_HOSTNAME=music.example.com
# REQUIRED: Secret key for Django (generate with: openssl rand -base64 45)
DJANGO_SECRET_KEY=CHANGE_ME_GENERATE_WITH_OPENSSL
# Database credentials
POSTGRES_USER=funkwhale
POSTGRES_PASSWORD=CHANGE_ME_STRONG_PASSWORD
POSTGRES_DB=funkwhale
# Optional: Federation (enabled by default)
# FUNKWHALE_DISABLE_FEDERATION=false
# Optional: Signup (disabled by default)
# FUNKWHALE_OPEN_REGISTRATIONS=false
Generate the secret key:
openssl rand -base64 45
Create a docker-compose.yml file:
services:
postgres:
image: postgres:16-alpine
container_name: funkwhale-db
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
volumes:
- funkwhale-db:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: funkwhale-redis
volumes:
- funkwhale-redis:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
api:
image: funkwhale/api:1.4.0
container_name: funkwhale-api
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
- FUNKWHALE_HOSTNAME=${FUNKWHALE_HOSTNAME}
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
- CACHE_URL=redis://redis:6379/0
- CELERY_BROKER_URL=redis://redis:6379/0
# Reverse proxy settings
- FUNKWHALE_PROTOCOL=https
- NESTED_PROXY=1
volumes:
# Music library
- /path/to/music:/srv/funkwhale/data/music:ro
# Uploaded content and media
- funkwhale-media:/srv/funkwhale/data/media
# Static files
- funkwhale-static:/srv/funkwhale/data/static
restart: unless-stopped
frontend:
image: funkwhale/frontend:1.4.0
container_name: funkwhale-frontend
depends_on:
- api
environment:
- FUNKWHALE_API_HOST=api
- FUNKWHALE_API_PORT=5000
ports:
# Web UI (put behind a reverse proxy for HTTPS)
- "5000:80"
volumes:
- funkwhale-static:/usr/share/nginx/html/staticfiles:ro
restart: unless-stopped
volumes:
funkwhale-db:
funkwhale-redis:
funkwhale-media:
funkwhale-static:
Replace /path/to/music with the actual path to your music library.
Run database migrations before first start:
docker compose run --rm api funkwhale-manage migrate
Create your admin (superuser) account:
docker compose run --rm api funkwhale-manage fw users create --superuser
Follow the prompts to set username, email, and password.
Start the stack:
docker compose up -d
Initial Setup
- Open
http://your-server-ip:5000(or your domain with HTTPS configured) - Log in with the superuser account you created
- Go to Settings → Libraries → Create a library
- Add a new music folder pointing to
/srv/funkwhale/data/music - Trigger a library scan to import your music
Funkwhale reads ID3 tags from your files for metadata. Ensure your music files are properly tagged before importing.
Configuration
Music Import
Funkwhale imports music by reading ID3/Vorbis tags. It supports:
- MP3, FLAC, OGG, OPUS, AAC, M4A, WAV
- Automatic album art extraction from file tags
- Artist, album, track metadata from tags
Federation
Funkwhale federates with other Funkwhale instances (and technically with Mastodon/Pleroma) via ActivityPub. Users on other instances can follow your libraries, listen to shared tracks, and interact with your content.
To enable federation, ensure ports 80 and 443 are open and your domain has valid HTTPS. Federation is enabled by default.
Podcasts
Funkwhale doubles as a podcast player. Users can subscribe to podcast RSS feeds directly in the web UI. Episodes are streamed, not downloaded.
Advanced Configuration (Optional)
Subsonic API Compatibility
Funkwhale supports the Subsonic API, which means it works with Subsonic-compatible mobile apps like DSub (Android) and play:Sub (iOS). Enable it in your Funkwhale settings — no additional configuration needed.
S3 Storage
For large music libraries, Funkwhale supports S3-compatible storage backends (MinIO, Wasabi, AWS S3) for media files. Set AWS_* environment variables in the API service.
Reverse Proxy
Funkwhale requires HTTPS for federation. Example Nginx Proxy Manager setup:
- Scheme:
http - Forward Hostname:
funkwhale-frontend(or your server IP) - Forward Port:
5000(the frontend’s mapped port) - SSL: Enable Let’s Encrypt
- WebSocket Support: Enable
Important: Funkwhale must run on a dedicated domain or subdomain. It does not support subdirectory installations (e.g., example.com/funkwhale will not work).
For other reverse proxy options, see Reverse Proxy Setup.
Backup
Critical data to back up:
- PostgreSQL database:
docker compose exec postgres pg_dump -U funkwhale funkwhale > funkwhale-db-$(date +%Y%m%d).sql
- Media volume (uploaded content, album art):
docker run --rm -v funkwhale-media:/data -v $(pwd):/backup alpine tar czf /backup/funkwhale-media-$(date +%Y%m%d).tar.gz -C /data .
- Your music library — back up as part of your general storage strategy
See Backup Strategy for a comprehensive approach.
Troubleshooting
Music files not appearing after scan
Symptom: Library scan completes but some or all tracks are missing. Fix: Funkwhale reads ID3 tags, not filenames. Files without proper tags won’t import. Use a tagger like MusicBrainz Picard to fix tags:
# Check if files have tags
docker compose exec api python -c "import mutagen; print(mutagen.File('/srv/funkwhale/data/music/path/to/file.mp3').tags)"
Federation not working
Symptom: Other instances can’t find your server.
Fix: Verify HTTPS is configured correctly and FUNKWHALE_HOSTNAME matches your actual domain. Check that /.well-known/webfinger returns a valid response:
curl https://music.example.com/.well-known/webfinger?resource=acct:[email protected]
High memory usage
Symptom: The API container uses excessive RAM. Fix: Funkwhale’s API (Django + Celery) can use 500 MB-1 GB under load. If memory is tight, limit Celery workers:
environment:
- CELERYD_CONCURRENCY=2
Database connection errors on startup
Symptom: API fails with “could not connect to server.”
Fix: The depends_on with healthcheck should handle this. If it persists, increase the healthcheck retries or add a delay:
api:
depends_on:
postgres:
condition: service_healthy
Resource Requirements
- RAM: 1-2 GB for the full stack (API + PostgreSQL + Redis + Frontend)
- CPU: Low-Medium (transcoding increases CPU usage)
- Disk: Database ~100 MB, plus your music library size
- Network: Ports 80/443 required for federation
Verdict
Funkwhale is the most feature-rich self-hosted music server if you want social/federation features. The ActivityPub integration, podcast support, and Subsonic API compatibility make it uniquely versatile.
The trade-off is complexity. Four containers, a required dedicated domain, and federation configuration make Funkwhale heavier to set up and run than Navidrome, which is a simpler, lighter alternative for pure music streaming. If you just want to play your music collection with a clean UI, Navidrome is the better fit. If you want a social music platform with federation, Funkwhale is the only self-hosted option.
FAQ
How is Funkwhale different from Navidrome?
Navidrome is a lightweight music streamer — it plays your files with a clean UI. Funkwhale adds federation (share music across instances), podcast support, user channels, and social features. Navidrome is simpler; Funkwhale is more ambitious.
Can I use Funkwhale with mobile apps?
Yes. Funkwhale supports the Subsonic API, so it works with DSub (Android), play:Sub (iOS), Ultrasonic, and other Subsonic-compatible apps. The web UI also works well on mobile browsers.
Does Funkwhale transcode music?
Yes. Funkwhale can transcode on-the-fly for streaming at lower bitrates. This uses CPU — if you’re on low-power hardware, consider pre-transcoding your library or streaming at original quality.
Related
Get self-hosting tips in your inbox
New guides, comparisons, and setup tutorials — delivered weekly. No spam.