# Funkwhale 2.0.11: music and podcasts. A channel is an actor of its own that publishes Audio, its files in `url[]`; # libraries follow libraries. The API (gunicorn), a Celery worker with its beat, and the front's nginx (which proxies the # API and serves media) share the pasture-funkwhale-data volume, on the shared Postgres (database funkwhale) and Redis # (dbs 8 and 9). Python's requests trusts the pasture's bundle through REQUESTS_CA_BUNDLE. Its admin is fwuser; a token # is an OAuth access token made in Django's shell. FUNKWHALE_IMAGE=${FUNKWHALE_IMAGE:-docker.io/funkwhale/api:2.0.11} FUNKWHALE_FRONT_IMAGE=${FUNKWHALE_FRONT_IMAGE:-docker.io/funkwhale/front:2.0.11} FUNKWHALE_PASSWORD=Funkwhale-Pasture-1 . "$here/peers/shared.sh" funkwhale_env() { local key="$here/.state/funkwhale/secret" [ -s "$key" ] || { mkdir -p "$here/.state/funkwhale"; head -c 48 /dev/urandom | base64 -w0 > "$key"; } cat < "$here/.state/funkwhale/env" podman volume exists pasture-funkwhale-data || podman volume create --label pasture=1 pasture-funkwhale-data >/dev/null local common=(--network $net --label pasture=1 --env-file "$here/.state/funkwhale/env" -v pasture-funkwhale-data:/srv/funkwhale/data -v "$ca/bundle.pem:/ca/bundle.pem:z,ro") podman run --rm "${common[@]}" "$FUNKWHALE_IMAGE" funkwhale-manage migrate >/dev/null 2>&1 podman run --rm "${common[@]}" "$FUNKWHALE_IMAGE" funkwhale-manage collectstatic --noinput >/dev/null 2>&1 podman run -d --replace --name pasture-funkwhale-api "${common[@]}" "$FUNKWHALE_IMAGE" gunicorn >/dev/null podman run -d --replace --name pasture-funkwhale-celery "${common[@]}" "$FUNKWHALE_IMAGE" \ celery -A funkwhale_api.taskapp worker -B -l info --concurrency=2 -s /tmp/celerybeat-schedule >/dev/null podman run -d --replace --name pasture-funkwhale --network $net --label pasture=1 --env-file "$here/.state/funkwhale/env" \ -v pasture-funkwhale-data:/srv/funkwhale/data "$FUNKWHALE_FRONT_IMAGE" >/dev/null for _ in $(seq 1 90); do site funkwhale.test -s -o /dev/null -w '%{http_code}' https://funkwhale.test:6443/.well-known/nodeinfo 2>/dev/null | grep -q 200 && break sleep 2 done funkwhale_settle echo "funkwhale: https://funkwhale.test:6443" } # fwuser, and an OAuth access token of its own funkwhale_settle() { funkwhale_manage fw users create --username fwuser --email fwuser@funkwhale.test --password "$FUNKWHALE_PASSWORD" --superuser >/dev/null 2>&1 || true podman exec -i pasture-funkwhale-api funkwhale-manage shell >/dev/null 2>&1 <<'PY' from datetime import timedelta from django.utils import timezone from funkwhale_api.users.models import User from funkwhale_api.users.models import Application, AccessToken user = User.objects.get(username="fwuser") app, _ = Application.objects.get_or_create(name="pasture", defaults={"client_type": "confidential", "authorization_grant_type": "authorization-code", "redirect_uris": "urn:ietf:wg:oauth:2.0:oob", "scope": "read write", "user": user}) AccessToken.objects.filter(user=user, application=app).delete() AccessToken.objects.create(user=user, application=app, token="pasture-fwuser-token", scope="read write", expires=timezone.now() + timedelta(days=365)) PY echo "pasture-fwuser-token" > "$here/.state/funkwhale.token" }