sojorn/sojorn_docs/FUNKWHALE_DEPLOYMENT.md
Patrick Britton 4315da74b2 docs: Update TODO and add Funkwhale deployment guide
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-17 16:03:45 -06:00

3.4 KiB

Funkwhale Deployment Guide

Funkwhale provides the audio library for the audio overlay system in Quips.

Server Setup

SSH to the server and run:

ssh -i ~/.ssh/mpls.pem patrick@116.202.231.103

# Create Funkwhale directory
mkdir -p /opt/funkwhale/{data,music,media,static,nginx}
cd /opt/funkwhale

docker-compose.yml

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

version: "3"

services:
  funkwhale:
    image: funkwhale/all-in-one:1.4.0
    container_name: funkwhale
    restart: unless-stopped
    environment:
      - FUNKWHALE_HOSTNAME=audio.sojorn.net
      - FUNKWHALE_PROTOCOL=https
      - NESTED_PROXY=1
      - DJANGO_SECRET_KEY=${FUNKWHALE_SECRET_KEY}
      - DATABASE_URL=postgresql://funkwhale:${FUNKWHALE_DB_PASS}@db/funkwhale
      - CACHE_URL=redis://redis:6379/0
      - EMAIL_CONFIG=smtp+tls://${SMTP_USER}:${SMTP_PASS}@${SMTP_HOST}:${SMTP_PORT}
      - DEFAULT_FROM_EMAIL=no-reply@sojorn.net
    volumes:
      - ./data:/data
      - ./music:/music:ro
      - ./media:/srv/funkwhale/data/media
      - ./static:/srv/funkwhale/data/static
    ports:
      - "127.0.0.1:5000:80"
    depends_on:
      - db
      - redis

  db:
    image: postgres:15-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_USER=funkwhale
      - POSTGRES_PASSWORD=${FUNKWHALE_DB_PASS}
      - POSTGRES_DB=funkwhale
    volumes:
      - ./data/db:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    volumes:
      - ./data/redis:/data

Create /opt/funkwhale/.env:

FUNKWHALE_SECRET_KEY=<generate with: python3 -c "import secrets; print(secrets.token_hex(50))">
FUNKWHALE_DB_PASS=<strong-password>

Start it:

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

# Wait for startup (~60s), then create superuser:
docker compose exec funkwhale manage createsuperuser

Nginx Config

Add a server block to /etc/nginx/sites-available/sojorn (or create a new one):

server {
    listen 443 ssl;
    server_name audio.sojorn.net;

    ssl_certificate     /etc/letsencrypt/live/audio.sojorn.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/audio.sojorn.net/privkey.pem;

    client_max_body_size 500M;

    location / {
        proxy_pass         http://127.0.0.1:5000;
        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;
    }
}

Get the certificate:

sudo certbot --nginx -d audio.sojorn.net
sudo nginx -t && sudo systemctl reload nginx

Wire into Go Backend

Add to /opt/sojorn/.env:

FUNKWHALE_BASE=http://127.0.0.1:5000

Then rebuild and restart:

cd /opt/sojorn/go-backend && go build -o bin/api ./cmd/api/...
echo PASSWORD | sudo -S systemctl restart sojorn-api.service

Seed With Royalty-Free Music

Funkwhale can import from local directories. Drop MP3s into /opt/funkwhale/music/ then:

docker compose exec funkwhale manage import_files \
  "/music/" --recursive --noinput

Good free sources: Free Music Archive, ccMixter.

Verify

curl http://127.0.0.1:5000/api/v1/tracks/?playable=true
# Should return JSON with track list

# Via Go proxy (after adding FUNKWHALE_BASE):
curl https://api.sojorn.net/api/v1/audio/library?q=jazz \
  -H "Authorization: Bearer <your-jwt>"