docker.recipes

Funkwhale Music Platform

advanced

Social music platform for sharing and discovering music.

Overview

Funkwhale is a self-hosted, federated music server that enables users to build their own Spotify-like platform with social features and ActivityPub federation. Born from the need for a decentralized alternative to proprietary music streaming services, Funkwhale allows individuals and communities to share, discover, and stream music while maintaining full control over their data and privacy. The platform supports multiple audio formats, provides Subsonic API compatibility for mobile apps, and integrates with the broader fediverse through ActivityPub protocol. This deployment stack combines Funkwhale's Django-based API backend with a Vue.js frontend, while leveraging PostgreSQL for robust metadata storage and complex music library relationships, and Redis for high-performance caching and Celery task queue management. The architecture separates concerns effectively: the API handles music metadata, user management, and federation logic, while Celery workers process audio transcoding, library imports, and federation tasks in the background. Redis serves dual purposes as both a cache layer for frequently accessed music metadata and as a message broker for asynchronous task processing. This configuration is ideal for music enthusiasts, podcast creators, radio stations, and organizations wanting to create their own streaming platform without vendor lock-in. The federated nature allows multiple Funkwhale instances to share content and users, creating a decentralized network similar to Mastodon but for audio content. Musicians can distribute their work directly, while communities can build curated collections with fine-grained privacy controls and user permissions.

Key Features

  • ActivityPub federation enabling content sharing across multiple Funkwhale instances and fediverse integration
  • Subsonic API compatibility allowing use of existing mobile music apps like DSub and Ultrasonic
  • Multi-format audio support with automatic transcoding via Celery workers for bandwidth optimization
  • Advanced music library management with artist pages, album collections, and tag-based organization
  • Social features including follow/unfollow, playlist sharing, and content discovery across federated instances
  • Granular privacy controls with public, followers-only, and private content visibility levels
  • Bulk music import from filesystem with automatic metadata extraction and duplicate detection
  • Built-in audio player with queue management, repeat modes, and scrobbling support

Common Use Cases

  • 1Independent musicians distributing music directly to fans with federated reach across multiple instances
  • 2Community radio stations creating curated playlists with listener interaction and content discovery
  • 3Music collectives and labels building private streaming platforms with controlled access and member features
  • 4Podcast networks hosting audio content with RSS feed generation and cross-instance syndication
  • 5Educational institutions providing music streaming for students with copyright-compliant content management
  • 6Personal music servers replacing Spotify with family sharing and mobile app compatibility
  • 7Music archivists preserving rare recordings with metadata preservation and federated backup systems

Prerequisites

  • Minimum 2GB RAM (1GB+ for PostgreSQL, 512MB+ for Redis, plus Funkwhale components and Celery workers)
  • Port 80 available for HTTP access to the Funkwhale web interface
  • Music library accessible at filesystem path with read permissions for Docker containers
  • Domain name or hostname configured for FUNKWHALE_HOST environment variable
  • Understanding of music metadata management and audio format compatibility
  • Basic knowledge of Django admin interface for user and content moderation

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 api:
3 image: funkwhale/api:latest
4 container_name: funkwhale-api
5 environment:
6 - FUNKWHALE_HOSTNAME=${FUNKWHALE_HOST}
7 - FUNKWHALE_PROTOCOL=http
8 - DATABASE_URL=postgresql://funkwhale:${DB_PASSWORD}@db:5432/funkwhale
9 - CACHE_URL=redis://redis:6379/0
10 - DJANGO_SECRET_KEY=${SECRET_KEY}
11 - DJANGO_ALLOWED_HOSTS=*
12 volumes:
13 - funkwhale-data:/srv/funkwhale/data
14 - /path/to/music:/music:ro
15 depends_on:
16 - db
17 - redis
18 networks:
19 - funkwhale-network
20 restart: unless-stopped
21
22 front:
23 image: funkwhale/front:latest
24 container_name: funkwhale-front
25 environment:
26 - FUNKWHALE_API_HOST=api
27 - FUNKWHALE_API_PORT=5000
28 ports:
29 - "80:80"
30 depends_on:
31 - api
32 networks:
33 - funkwhale-network
34 restart: unless-stopped
35
36 celery-worker:
37 image: funkwhale/api:latest
38 container_name: funkwhale-celery-worker
39 command: celery -A funkwhale_api.taskapp worker -l INFO
40 environment:
41 - FUNKWHALE_HOSTNAME=${FUNKWHALE_HOST}
42 - DATABASE_URL=postgresql://funkwhale:${DB_PASSWORD}@db:5432/funkwhale
43 - CACHE_URL=redis://redis:6379/0
44 - DJANGO_SECRET_KEY=${SECRET_KEY}
45 volumes:
46 - funkwhale-data:/srv/funkwhale/data
47 - /path/to/music:/music:ro
48 depends_on:
49 - api
50 networks:
51 - funkwhale-network
52 restart: unless-stopped
53
54 celery-beat:
55 image: funkwhale/api:latest
56 container_name: funkwhale-celery-beat
57 command: celery -A funkwhale_api.taskapp beat -l INFO
58 environment:
59 - FUNKWHALE_HOSTNAME=${FUNKWHALE_HOST}
60 - DATABASE_URL=postgresql://funkwhale:${DB_PASSWORD}@db:5432/funkwhale
61 - CACHE_URL=redis://redis:6379/0
62 - DJANGO_SECRET_KEY=${SECRET_KEY}
63 depends_on:
64 - api
65 networks:
66 - funkwhale-network
67 restart: unless-stopped
68
69 db:
70 image: postgres:15-alpine
71 container_name: funkwhale-db
72 environment:
73 - POSTGRES_USER=funkwhale
74 - POSTGRES_PASSWORD=${DB_PASSWORD}
75 - POSTGRES_DB=funkwhale
76 volumes:
77 - postgres-data:/var/lib/postgresql/data
78 networks:
79 - funkwhale-network
80 restart: unless-stopped
81
82 redis:
83 image: redis:7-alpine
84 container_name: funkwhale-redis
85 volumes:
86 - redis-data:/data
87 networks:
88 - funkwhale-network
89 restart: unless-stopped
90
91volumes:
92 funkwhale-data:
93 postgres-data:
94 redis-data:
95
96networks:
97 funkwhale-network:
98 driver: bridge

.env Template

.env
1# Funkwhale
2FUNKWHALE_HOST=funkwhale.localhost
3DB_PASSWORD=secure_funkwhale_password
4
5# Generate with: openssl rand -hex 32
6SECRET_KEY=your_secret_key

Usage Notes

  1. 1Web UI at http://localhost
  2. 2Create admin: manage.py createsuperuser
  3. 3Federation with ActivityPub
  4. 4Import from filesystem
  5. 5Subsonic API compatible

Individual Services(6 services)

Copy individual services to mix and match with your existing compose files.

api
api:
  image: funkwhale/api:latest
  container_name: funkwhale-api
  environment:
    - FUNKWHALE_HOSTNAME=${FUNKWHALE_HOST}
    - FUNKWHALE_PROTOCOL=http
    - DATABASE_URL=postgresql://funkwhale:${DB_PASSWORD}@db:5432/funkwhale
    - CACHE_URL=redis://redis:6379/0
    - DJANGO_SECRET_KEY=${SECRET_KEY}
    - DJANGO_ALLOWED_HOSTS=*
  volumes:
    - funkwhale-data:/srv/funkwhale/data
    - /path/to/music:/music:ro
  depends_on:
    - db
    - redis
  networks:
    - funkwhale-network
  restart: unless-stopped
front
front:
  image: funkwhale/front:latest
  container_name: funkwhale-front
  environment:
    - FUNKWHALE_API_HOST=api
    - FUNKWHALE_API_PORT=5000
  ports:
    - "80:80"
  depends_on:
    - api
  networks:
    - funkwhale-network
  restart: unless-stopped
celery-worker
celery-worker:
  image: funkwhale/api:latest
  container_name: funkwhale-celery-worker
  command: celery -A funkwhale_api.taskapp worker -l INFO
  environment:
    - FUNKWHALE_HOSTNAME=${FUNKWHALE_HOST}
    - DATABASE_URL=postgresql://funkwhale:${DB_PASSWORD}@db:5432/funkwhale
    - CACHE_URL=redis://redis:6379/0
    - DJANGO_SECRET_KEY=${SECRET_KEY}
  volumes:
    - funkwhale-data:/srv/funkwhale/data
    - /path/to/music:/music:ro
  depends_on:
    - api
  networks:
    - funkwhale-network
  restart: unless-stopped
celery-beat
celery-beat:
  image: funkwhale/api:latest
  container_name: funkwhale-celery-beat
  command: celery -A funkwhale_api.taskapp beat -l INFO
  environment:
    - FUNKWHALE_HOSTNAME=${FUNKWHALE_HOST}
    - DATABASE_URL=postgresql://funkwhale:${DB_PASSWORD}@db:5432/funkwhale
    - CACHE_URL=redis://redis:6379/0
    - DJANGO_SECRET_KEY=${SECRET_KEY}
  depends_on:
    - api
  networks:
    - funkwhale-network
  restart: unless-stopped
db
db:
  image: postgres:15-alpine
  container_name: funkwhale-db
  environment:
    - POSTGRES_USER=funkwhale
    - POSTGRES_PASSWORD=${DB_PASSWORD}
    - POSTGRES_DB=funkwhale
  volumes:
    - postgres-data:/var/lib/postgresql/data
  networks:
    - funkwhale-network
  restart: unless-stopped
redis
redis:
  image: redis:7-alpine
  container_name: funkwhale-redis
  volumes:
    - redis-data:/data
  networks:
    - funkwhale-network
  restart: unless-stopped

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 api:
5 image: funkwhale/api:latest
6 container_name: funkwhale-api
7 environment:
8 - FUNKWHALE_HOSTNAME=${FUNKWHALE_HOST}
9 - FUNKWHALE_PROTOCOL=http
10 - DATABASE_URL=postgresql://funkwhale:${DB_PASSWORD}@db:5432/funkwhale
11 - CACHE_URL=redis://redis:6379/0
12 - DJANGO_SECRET_KEY=${SECRET_KEY}
13 - DJANGO_ALLOWED_HOSTS=*
14 volumes:
15 - funkwhale-data:/srv/funkwhale/data
16 - /path/to/music:/music:ro
17 depends_on:
18 - db
19 - redis
20 networks:
21 - funkwhale-network
22 restart: unless-stopped
23
24 front:
25 image: funkwhale/front:latest
26 container_name: funkwhale-front
27 environment:
28 - FUNKWHALE_API_HOST=api
29 - FUNKWHALE_API_PORT=5000
30 ports:
31 - "80:80"
32 depends_on:
33 - api
34 networks:
35 - funkwhale-network
36 restart: unless-stopped
37
38 celery-worker:
39 image: funkwhale/api:latest
40 container_name: funkwhale-celery-worker
41 command: celery -A funkwhale_api.taskapp worker -l INFO
42 environment:
43 - FUNKWHALE_HOSTNAME=${FUNKWHALE_HOST}
44 - DATABASE_URL=postgresql://funkwhale:${DB_PASSWORD}@db:5432/funkwhale
45 - CACHE_URL=redis://redis:6379/0
46 - DJANGO_SECRET_KEY=${SECRET_KEY}
47 volumes:
48 - funkwhale-data:/srv/funkwhale/data
49 - /path/to/music:/music:ro
50 depends_on:
51 - api
52 networks:
53 - funkwhale-network
54 restart: unless-stopped
55
56 celery-beat:
57 image: funkwhale/api:latest
58 container_name: funkwhale-celery-beat
59 command: celery -A funkwhale_api.taskapp beat -l INFO
60 environment:
61 - FUNKWHALE_HOSTNAME=${FUNKWHALE_HOST}
62 - DATABASE_URL=postgresql://funkwhale:${DB_PASSWORD}@db:5432/funkwhale
63 - CACHE_URL=redis://redis:6379/0
64 - DJANGO_SECRET_KEY=${SECRET_KEY}
65 depends_on:
66 - api
67 networks:
68 - funkwhale-network
69 restart: unless-stopped
70
71 db:
72 image: postgres:15-alpine
73 container_name: funkwhale-db
74 environment:
75 - POSTGRES_USER=funkwhale
76 - POSTGRES_PASSWORD=${DB_PASSWORD}
77 - POSTGRES_DB=funkwhale
78 volumes:
79 - postgres-data:/var/lib/postgresql/data
80 networks:
81 - funkwhale-network
82 restart: unless-stopped
83
84 redis:
85 image: redis:7-alpine
86 container_name: funkwhale-redis
87 volumes:
88 - redis-data:/data
89 networks:
90 - funkwhale-network
91 restart: unless-stopped
92
93volumes:
94 funkwhale-data:
95 postgres-data:
96 redis-data:
97
98networks:
99 funkwhale-network:
100 driver: bridge
101EOF
102
103# 2. Create the .env file
104cat > .env << 'EOF'
105# Funkwhale
106FUNKWHALE_HOST=funkwhale.localhost
107DB_PASSWORD=secure_funkwhale_password
108
109# Generate with: openssl rand -hex 32
110SECRET_KEY=your_secret_key
111EOF
112
113# 3. Start the services
114docker compose up -d
115
116# 4. View logs
117docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/funkwhale-music/run | bash

Troubleshooting

  • Import tasks failing or stuck: Check Celery worker logs and ensure music directory has proper read permissions and supported audio formats
  • Federation not working with other instances: Verify FUNKWHALE_HOSTNAME matches your actual domain and is accessible externally with proper DNS configuration
  • High memory usage during imports: Limit concurrent Celery workers and increase Redis memory allocation for large music libraries
  • Subsonic API authentication failing: Ensure user accounts are created through Django admin and have proper API permissions enabled
  • Frontend showing API connection errors: Verify FUNKWHALE_API_HOST environment variable matches the actual API service name and port 5000 connectivity
  • Database migration errors on startup: Check PostgreSQL logs for disk space and ensure DATABASE_URL format matches PostgreSQL connection requirements

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space