Funkwhale
Updated 20 January 2022
Introduction
Funkwhale is a community project that allows you to listen to and share music on a distributed, open network.
Preparing an LXC container
We suggest that you install Funkwhale in a separate container, after having set it up according to the manual.
Installing and configuring PostgreSQL
Install and configure PostgreSQL according to the manual. In the example, replace dbtest with funkwhale, and the test user with funkwhale.
Add extensions for the database under postgres:
psql -U postgres funkwhale -c 'CREATE EXTENSION "unaccent";'
psql -U postgres funkwhale -c 'CREATE EXTENSION "citext";'
Installing system packages
Install the necessary software:
emerge -a dev-db/redis app-arch/unzip media-video/ffmpeg media-libs/libjpeg-turbo dev-libs/libpqxx net-nds/openldap sys-devel/gettext
Launching Redis
Launch Redis and add it to autostart:
/etc/init.d/redis start
rc-update add redis
Adding a system user
Add a user named funkwhale:
mkdir -p /var/calculate/www
useradd -r -s /sbin/nologin -d /var/calculate/www/funkwhale -m funkwhale
Log in as funkwhale:
su - -s /bin/bash funkwhale
Create the necessary directories:
mkdir -p config api data/static data/media data/music front
Fetching Funkwhale sources
Download and extract the latest version of the API:
export FUNKWHALE_VERSION="1.2.1"
curl -L -o "api-$FUNKWHALE_VERSION.zip" "https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/$FUNKWHALE_VERSION/download?job=build_api"
unzip "api-$FUNKWHALE_VERSION.zip" -d extracted
mv extracted/api/* api/
rm -rf extracted
rm api-${FUNKWHALE_VERSION}.zip
Download and extract the latest version of the front-end:
curl -L -o "front-$FUNKWHALE_VERSION.zip" "https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/$FUNKWHALE_VERSION/download?job=build_front"
unzip "front-$FUNKWHALE_VERSION.zip" -d extracted
mv extracted/front .
rm -rf extracted
rm front-${FUNKWHALE_VERSION}.zip
Installing Python dependencies
Create a virtual environment:
python3 -m venv virtualenv
echo 'source ~/virtualenv/bin/activate' >> ~/.bashrc
source virtualenv/bin/activate
Install the Python dependencies:
pip install wheel
pip install -r api/requirements.txt
Configuring Funkwhale
Download the configuration file and set the privileges:
curl -L -o ~/config/.env "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/master/deploy/env.prod.sample"
chmod 600 ~/config/.env
Create a private key for Django:
ev5pFTw2gV4TEOeAmCwDZB87qGeFgvsHxUJt5A7c4SNfgP1HEZMxM5hz/mw+
Edit the configuration file for music.example.org:
# Replace this by the definitive, public domain you will use for # your instance FUNKWHALE_HOSTNAME=music.example.org FUNKWHALE_PROTOCOL=https ... EMAIL_CONFIG=smtp://mail.example.org:25 # The email address to use to send system emails. DEFAULT_FROM_EMAIL=support@example.org ... # API/Django configuration # Database configuration # Examples: # DATABASE_URL=postgresql://<user>:<password>@<host>:<port>/<database> # DATABASE_URL=postgresql://funkwhale:passw0rd@localhost:5432/funkwhale_database # Use the next one if you followed Debian installation guide DATABASE_URL=postgresql://funkwhale:secret@localhost:5432/funkwhale # Cache configuration # Examples: # CACHE_URL=redis://<host>:<port>/<database> # CACHE_URL=redis://localhost:6379/0c # With a password: # CACHE_URL=redis://:password@localhost:6379/0 # (the extra semicolon is important) # Use the next one if you followed Debian installation guide # CACHE_URL=redis://127.0.0.1:6379/0 # Where media files (such as album covers or audio tracks) should be stored # on your system? # (Ensure this directory actually exists) MEDIA_ROOT=/var/calculate/www/funkwhale/data/media # Where static files (such as API css or icons) should be compiled # on your system? # (Ensure this directory actually exists) STATIC_ROOT=/var/calculate/www/funkwhale/data/static # Generate one using `openssl rand -base64 45`, for example DJANGO_SECRET_KEY=ev5pFTw2gV4TEOeAmCwDZB87qGeFgvsHxUJt5A7c4SNfgP1HEZMxM5hz/mw+ # In-place import settings # You can safely leave those settings uncommented if you don't plan to use # in place imports. # Typical docker setup: # MUSIC_DIRECTORY_PATH=/music # docker-only # MUSIC_DIRECTORY_SERVE_PATH=/srv/funkwhale/data/music # Typical non-docker setup: # MUSIC_DIRECTORY_PATH=/srv/funkwhale/data/music # # MUSIC_DIRECTORY_SERVE_PATH= # stays commented, not needed MUSIC_DIRECTORY_PATH=/var/calculate/www/funkwhale/data/music MUSIC_DIRECTORY_SERVE_PATH=/var/calculate/www/funkwhale/data/music ... FUNKWHALE_FRONTEND_PATH=/var/calculate/www/funkwhale/front/dist
Initialize the database:
python api/manage.py migrate
Update the static files:
python api/manage.py collectstatic
Create the superuser:
Username: user Email address: user@example.org Password: Password (again): Superuser created successfully.
Quit as funkwhale:
exit
Getting Let's Encrypt certificate
Get the music.example.org domain certificate for Nginx, as described in the manual.
Installing and configuring Nginx
Install and configure the Nginx web server as a reverse proxy according to the manual.
Get the Funkwhale configuration template for Nginx:
export FUNKWHALE_VERSION="1.2.1"
curl -L -o /etc/nginx/funkwhale_proxy.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale_proxy.conf"
curl -L -o /etc/nginx/sites-enabled/funkwhale.template "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/nginx.template"
Use the template to configure Nginx:
set -a && source /var/calculate/www/funkwhale/config/.env && set +a
envsubst "`env | awk -F = '{printf \" $%s\", $$1}'`" \
< /etc/nginx/sites-enabled/funkwhale.template \
> /etc/nginx/sites-enabled/funkwhale.conf
Starting Funkwhale
Create OpenRC scripts to manage services.
Here is the script for running the Funkwhale server:
#!/sbin/openrc-run # Copyright 2019 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 name="Funkwhale application server" description="Funkwhale application server" command_user=funkwhale command=/var/calculate/www/funkwhale/virtualenv/bin/gunicorn FUNKWHALE_API_IP=127.0.0.1 FUNKWHALE_API_PORT=5000 FUNKWHALE_WEB_WORKER=4 command_args="config.asgi:application -w ${FUNKWHALE_WEB_WORKER} -k uvicorn.workers.UvicornWorker -b ${FUNKWHALE_API_IP}:${FUNKWHALE_API_PORT}" directory=/var/calculate/www/funkwhale/api pidfile="/run/funkwhale-server.pid" command_background=true output_log=/var/log/funkwhale-server.log error_log=/var/log/funkwhale-server.log depend() { use net postgresql redis } start_pre() { checkpath -f -o funkwhale -m 0600 /var/log/funkwhale-server.log }
Here is the Funkwhale celery worker script:
#!/sbin/openrc-run # Copyright 2019 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 name="Funkwhale celery worker" description="Funkwhale celery worker" command_user=funkwhale command=/var/calculate/www/funkwhale/virtualenv/bin/celery command_args="-A funkwhale_api.taskapp worker -l INFO" directory=/var/calculate/www/funkwhale/api pidfile="/run/funkwhale-worker.pid" command_background=true output_log=/var/log/funkwhale-worker.log error_log=/var/log/funkwhale-worker.log depend() { use net postgresql redis } start_pre() { checkpath -f -o funkwhale -m 0600 /var/log/funkwhale-worker.log }
Here is the Funkwhale beat script:
#!/sbin/openrc-run # Copyright 2019 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 name="Funkwhale celery beat process" description="Funkwhale celery beat process" command_user=funkwhale command=/var/calculate/www/funkwhale/virtualenv/bin/celery command_args="-A funkwhale_api.taskapp beat -l INFO" directory=/var/calculate/www/funkwhale/api pidfile="/run/funkwhale-beat.pid" command_background=true output_log=/var/log/funkwhale-beat.log error_log=/var/log/funkwhale-beat.log depend() { use net postgresql redis } start_pre() { checkpath -f -o funkwhale -m 0600 /var/log/funkwhale-beat.log }
Set privileges for running Funkwhale services:
chmod 0755 /etc/init.d/funkwhale-*
Launch Funkwhale services:
/etc/init.d/funkwhale-beat start
/etc/init.d/funkwhale-server start
/etc/init.d/funkwhale-worker start
Add the Funkwhale services to autostart:
rc-update add funkwhale-beat
rc-update add funkwhale-server
rc-update add funkwhale-worker
Updating Funkwhale
First the Funkwhale services:
/etc/init.d/funkwhale-beat stop
/etc/init.d/funkwhale-server stop
/etc/init.d/funkwhale-worker stop
If necessary, switch manually between versions:
To move to version 1.1.4, replace the WSGI server name from daphne to gunicron:
sed -i 's/daphne/gunicorn/;s/command_args=.*/FUNKWHALE_WEB_WORKER=4\ncommand_args="config.asgi:application -w ${FUNKWHALE_WEB_WORKER} -k uvicorn.workers.UvicornWorker -b ${FUNKWHALE_API_IP}:${FUNKWHALE_API_PORT}"/' /etc/init.d/funkwhale-server
Updating the front-end
Log in as funkwhale.
su - -s /bin/bash funkwhale
Download the tarball of the latest version of the front-end (1.2.1):
export FUNKWHALE_VERSION="1.2.1"
curl -L -o "front-$FUNKWHALE_VERSION.zip" "https://dev.funkwhale.audio/funkwhale/funkwhale/builds/artifacts/$FUNKWHALE_VERSION/download?job=build_front"
Delete the current front-end and replace it with the new one, to be extracted:
rm -r front
unzip -o front-${FUNKWHALE_VERSION}.zip
rm front-${FUNKWHALE_VERSION}.zip
Updating the API
Download the tarball of the latest version of the API (1.2.1):
curl -L -o "api-$FUNKWHALE_VERSION.zip" "https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/$FUNKWHALE_VERSION/download?job=build_api"
Delete the current API and extract the new one to the project directory:
unzip "api-$FUNKWHALE_VERSION.zip" -d extracted
rm -rf api/ && mv extracted/api .
rm -rf extracted
rm api-${FUNKWHALE_VERSION}.zip
Update the dependencies of Python
virtualenv/bin/pip install -r api/requirements.txt
Update the static files of the project:
virtualenv/bin/python api/manage.py collectstatic --no-input
Perform database migration:
virtualenv/bin/python api/manage.py migrate
If necessary, switch manually between versions:
When updating to 1.0, rescan the thumbnails:
rm -r data/media/__sized__
virtualenv/bin/python api/manage.py fw media generate-thumbnails
Log out as funkwhale and launch the Funkwhale services.
exit
/etc/init.d/funkwhale-beat start
/etc/init.d/funkwhale-server start
/etc/init.d/funkwhale-worker start
Updating Nginx configuration
Get the latest Funkwhale configuration template (1.2.1) for Nginx:
export FUNKWHALE_VERSION="1.2.1"
curl -L -o /etc/nginx/funkwhale_proxy.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/${FUNKWHALE_VERSION}/deploy/funkwhale_proxy.conf"
curl -L -o /etc/nginx/sites-enabled/funkwhale.template "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/${FUNKWHALE_VERSION}/deploy/nginx.template"
Use the template to configure Nginx:
set -a && source /var/calculate/www/funkwhale/config/.env && set +a
envsubst "`env | awk -F = '{printf \" $%s\", $$1}'`" \
< /etc/nginx/sites-enabled/funkwhale.template \
> /etc/nginx/sites-enabled/funkwhale.conf
For certificates from /etc/nginx/ssl, replace /etc/letsencrypt/live with the newly created funkwhale.conf:
sed -i 's,/etc/letsencrypt/live,/etc/nginx/ssl,g' /etc/nginx/sites-enabled/funkwhale.conf
Reload the Nginx parameters for the modifications to take effect:
/etc/init.d/nginx reload
Recovering Python environment after upgrade
Log in as funkwhale:
su - -s /bin/bash funkwhale
Disable the old virtual environment and delete it:
deactivate
rm -rf ~/virtualenv
Create a new virtual environment:
python3 -m venv virtualenv
source virtualenv/bin/activate
Install the Python dependencies:
pip install wheel
pip install -r api/requirements.txt