diff options
-rw-r--r-- | .SRCINFO | 72 | ||||
-rw-r--r-- | PKGBUILD | 149 | ||||
-rw-r--r-- | apache-funkwhale.conf | 18 | ||||
-rw-r--r-- | env-template | 7 | ||||
-rw-r--r-- | funkwhale-beat.service | 3 | ||||
-rw-r--r-- | funkwhale-server.service | 3 | ||||
-rw-r--r-- | funkwhale-worker.service | 3 | ||||
-rw-r--r-- | funkwhale.install | 8 |
8 files changed, 160 insertions, 103 deletions
@@ -1,7 +1,7 @@ pkgbase = funkwhale - pkgdesc = A self-hosted, modern free and open-source music server, heavily inspired by Grooveshark. - pkgver = 0.19.0 - pkgrel = 1 + pkgdesc = A community-driven project that lets you listen and share music and audio within a decentralized, open network. + pkgver = 1.2.1 + pkgrel = 3 url = https://funkwhale.audio/ install = funkwhale.install arch = any @@ -11,9 +11,8 @@ pkgbase = funkwhale depends = libjpeg depends = postgresql depends = python - depends = ipython - depends = mod_xsendfile - depends = python-django>=2 + depends = python-setuptools + depends = python-django depends = python-django-environ depends = python-pillow depends = python-django-allauth @@ -22,62 +21,71 @@ pkgbase = funkwhale depends = python-django-redis depends = python-redis depends = python-kombu - depends = python-celery + depends = python-celery>=5.2 depends = python-django-cors-headers depends = python-musicbrainzngs - depends = python-django-rest-framework>=3.9 - depends = python-django-rest-framework-jwt - depends = python-pendulum + depends = python-django-rest-framework + depends = python-arrow depends = python-persisting-theory depends = python-django-versatile-imagefield depends = python-django-filter depends = python-django-rest-auth + depends = ipython depends = python-mutagen - depends = python-django-taggit depends = python-pymemoize depends = python-django-dynamic-preferences - depends = python-raven depends = python-magic-git depends = python-django-channels - depends = python-django-channels-redis - depends = python-daphne + depends = python-django-channels-redis>=3 + depends = uvicorn + depends = gunicorn depends = python-cryptography depends = python-requests-http-signature depends = python-django-cleanup + depends = python-requests + depends = python-pyopenssl depends = python-ldap depends = python-django-auth-ldap - depends = python-service-identity depends = python-pydub - depends = python-pyld>=1.0.4 + depends = python-pyld depends = python-aiohttp - depends = python-autobahn depends = python-django-oauth-toolkit depends = python-django-storages depends = python-boto3 depends = python-unicode-slugify-git + depends = python-django-cacheops + depends = python-service-identity + depends = python-click + depends = python-markdown + depends = python-bleach + depends = python-feedparser>=6 + depends = python-watchdog + depends = python-asgiref_patch optdepends = apache: to use the Apache web server optdepends = certbot-apache: for the server to be accessible from outside + optdepends = mod_xsendfile: needed if Apache server is used optdepends = nginx: to use nginx web server - source = funkwhale-0.19.0-api.zip::https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/0.19.0/download?job=build_api - source = funkwhale-0.19.0-front.zip::https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/0.19.0/download?job=build_front - source = https://dev.funkwhale.audio/funkwhale/funkwhale/raw/0.19.0/deploy/funkwhale_proxy.conf - source = https://dev.funkwhale.audio/funkwhale/funkwhale/raw/0.19.0/deploy/nginx.template + provides = funkwhale + conflicts = funkwhale-venv + source = funkwhale-1.2.1-api.zip::https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/1.2.1/download?job=build_api + source = funkwhale-1.2.1-front.zip::https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/1.2.1/download?job=build_front + source = https://dev.funkwhale.audio/funkwhale/funkwhale/raw/1.2.1/deploy/funkwhale_proxy.conf + source = https://dev.funkwhale.audio/funkwhale/funkwhale/raw/1.2.1/deploy/nginx.template + source = funkwhale.service source = funkwhale-beat.service - source = funkwhale-worker.service source = funkwhale-server.service + source = funkwhale-worker.service source = apache-funkwhale.conf source = env-template - source = funkwhale.service - sha256sums = 8838f83c1c658a758ef283d22f682820b4866f33d83d7832eb52fa04b4f729c8 - sha256sums = 2a664eb81f46c1f7c9d52d472a2a9958356eb409fed36bb2acba7bde87c7d7c6 + sha256sums = d370dd548102be5477a8d6632ea58e6de42d18bce58078e007c471cb8bb4753f + sha256sums = 3725d2aa8563dd8989042a1ee4a57cac2d396b5ad20820815775ae724aa8ff0c sha256sums = 2906a075b41dcd2375c601482cb5a00e42cb87c613012b176c570d77918afbf2 - sha256sums = ee571b8a30b968849fcf5c7b2588f298a3046609fe9792dd0b59024899dfea3a - sha256sums = a964a7802252d20a3319e2131c27ec307ad4f454921c2db31971c080150d7c9b - sha256sums = 0e6d7c96b7c1ec63794214decb1f2e7dd112a22b02e55555cf98c2a573014af6 - sha256sums = 4a28ddf6a6ba8ec28c10a164f82e3d5e5904d6dfe68ae8852428a589cee210c5 - sha256sums = ee895ecaf5faaa794f161e9df038177497cb5c49510acd3aef088f75eb8b02f1 - sha256sums = c2ee8160e2f4f87a2d4fe46136ffb8ea14422dc599db3eca4341e48db26d72ad + sha256sums = 37fa894055ce94b2d0752c48a89c04d67a2610a3572a788ba7a3cf65e1641c90 sha256sums = 01104122e3df765735b1062aa15e7a73c7949f2d9b7332c0e02e02db66345349 + sha256sums = 812c9a49436725e18768c5eb772c7207c184cdcf3a057432dc998387c481bd8d + sha256sums = 9d5a6f2cae6f18e22c5423247570519e8c772a9447ec2d92bd2fe5d69e519470 + sha256sums = 57c17dbd033fff76b344c90114d3b1f9eae3aaaa49128b61fcd1b5e808561dc3 + sha256sums = f37b1b6257c5b92272f36773041c83fc72276ff4040100fba92db8136cc9177d + sha256sums = cea307055e9f8001a1507c507e1be91352d896cab17260a221f4ab8c298506d8 pkgname = funkwhale - @@ -1,60 +1,74 @@ # Maintainer: getzze <getzze at gmail dot com> pkgname=funkwhale -pkgver=0.19.0 -pkgrel=1 -pkgdesc="A self-hosted, modern free and open-source music server, heavily inspired by Grooveshark." +pkgver=1.2.1 +pkgrel=3 +pkgdesc="A community-driven project that lets you listen and share music and audio within a decentralized, open network." arch=(any) url="https://funkwhale.audio/" license=(GPL3) +provides=('funkwhale') +conflicts=('funkwhale-venv') optdepends=('apache: to use the Apache web server' 'certbot-apache: for the server to be accessible from outside' + 'mod_xsendfile: needed if Apache server is used' 'nginx: to use nginx web server') -depends=('ffmpeg' 'libjpeg' 'postgresql' 'python' - 'ipython' - 'mod_xsendfile' - 'python-django>=2' - 'python-django-environ' - 'python-pillow' - 'python-django-allauth' - 'python-psycopg2' - 'python-pytz' - 'python-django-redis' - 'python-redis' - 'python-kombu' - 'python-celery' - 'python-django-cors-headers' - 'python-musicbrainzngs' - 'python-django-rest-framework>=3.9' - 'python-django-rest-framework-jwt' - 'python-pendulum' - 'python-persisting-theory' - 'python-django-versatile-imagefield' - 'python-django-filter' - 'python-django-rest-auth' - 'python-mutagen' - 'python-django-taggit' - 'python-pymemoize' - 'python-django-dynamic-preferences' - 'python-raven' - 'python-magic-git' - 'python-django-channels' - 'python-django-channels-redis' - 'python-daphne' - 'python-cryptography' - 'python-requests-http-signature' - 'python-django-cleanup' - 'python-ldap' - 'python-django-auth-ldap' - 'python-service-identity' - 'python-pydub' - 'python-pyld>=1.0.4' - 'python-aiohttp' - 'python-autobahn' - 'python-django-oauth-toolkit' - 'python-django-storages' - 'python-boto3' - 'python-unicode-slugify-git' +depends=('ffmpeg' + 'libjpeg' + 'postgresql' + 'python' + 'python-setuptools' # >=57.4 + 'python-django' # ~= 3.2.3 + 'python-django-environ' # ~= 0.4.0 + 'python-pillow' # ~= 8.3.0 + 'python-django-allauth' # ~= 0.42.0 + 'python-psycopg2' # ~= 2.9.1 + 'python-pytz' # ~= 2021.1 + 'python-django-redis' # ~= 5.0.0 + 'python-redis' # ~= 3.5.0 + 'python-kombu' # ~= 5.1.0 + 'python-celery>=5.2' # ~= 5.1.2 + 'python-django-cors-headers' # ~= 3.8.0 + 'python-musicbrainzngs' # ~= 0.7.1 + 'python-django-rest-framework' # ~= 3.12.2 +# 'python-django-rest-framework-jwt' # ~= 1.11.0 + 'python-arrow' # ~= 1.1.0 + 'python-persisting-theory' # ~= 0.2.0 + 'python-django-versatile-imagefield' # ~= 2.2.0 + 'python-django-filter' # ~= 2.4.0 + 'python-django-rest-auth' # ~= 0.9.0 + 'ipython' # ~= 7.27.0 + 'python-mutagen' # ~= 1.45.0 + 'python-pymemoize' # ~= 1.0.0 + 'python-django-dynamic-preferences' # ~= 1.10 +# 'python-raven' # ~= 6.10.0 + 'python-magic-git' # ~= 0.4.0 + 'python-django-channels' # ~= 3.0.3 + 'python-django-channels-redis>=3' # ~= 3.3.0 + 'uvicorn' # ~= 0.14.0 + 'gunicorn' # ~= 20.1.0 + 'python-cryptography' # ~= 3.3.2 + 'python-requests-http-signature' # == 0.0.3 + 'python-django-cleanup' # ~= 5.2.0 + 'python-requests' # ~= 2.26.0 + 'python-pyopenssl' # ~= 20.0.1 + 'python-ldap' # ~= 3.3.0 + 'python-django-auth-ldap' # ~= 3.0.0 + 'python-pydub' # ~= 0.25.1 + 'python-pyld' # ~= 2.0.3 + 'python-aiohttp' # ~= 3.7.4 + 'python-django-oauth-toolkit' # ~= 1.5.0 + 'python-django-storages' # ~= 1.11.1 + 'python-boto3' # ~= 1.17.59 + 'python-unicode-slugify-git' # ~= 0.1.0 + 'python-django-cacheops' # ~= 6.0.0 + 'python-service-identity' # ~= 21.1.0 + 'python-click' # ~= 7.1.0 + 'python-markdown' # ~= 3.3.4 + 'python-bleach' # ~= 3.3.0 + 'python-feedparser>=6' # ~= 6.0.0 + 'python-watchdog' # ~= 2.1.2 + 'python-asgiref_patch' # ~= 3.4.1 patched ) makedepends=(git) _source_api="https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/${pkgver}/download?job=" @@ -63,25 +77,32 @@ source=("${pkgname}-${pkgver}-api.zip::${_source_api}build_api" "${pkgname}-${pkgver}-front.zip::${_source_api}build_front" "${_source_env}funkwhale_proxy.conf" "${_source_env}nginx.template" + "funkwhale.service" "funkwhale-beat.service" - "funkwhale-worker.service" "funkwhale-server.service" + "funkwhale-worker.service" "apache-funkwhale.conf" "env-template" - "funkwhale.service" ) -sha256sums=('8838f83c1c658a758ef283d22f682820b4866f33d83d7832eb52fa04b4f729c8' - '2a664eb81f46c1f7c9d52d472a2a9958356eb409fed36bb2acba7bde87c7d7c6' +sha256sums=('d370dd548102be5477a8d6632ea58e6de42d18bce58078e007c471cb8bb4753f' + '3725d2aa8563dd8989042a1ee4a57cac2d396b5ad20820815775ae724aa8ff0c' '2906a075b41dcd2375c601482cb5a00e42cb87c613012b176c570d77918afbf2' - 'ee571b8a30b968849fcf5c7b2588f298a3046609fe9792dd0b59024899dfea3a' - 'a964a7802252d20a3319e2131c27ec307ad4f454921c2db31971c080150d7c9b' - '0e6d7c96b7c1ec63794214decb1f2e7dd112a22b02e55555cf98c2a573014af6' - '4a28ddf6a6ba8ec28c10a164f82e3d5e5904d6dfe68ae8852428a589cee210c5' - 'ee895ecaf5faaa794f161e9df038177497cb5c49510acd3aef088f75eb8b02f1' - 'c2ee8160e2f4f87a2d4fe46136ffb8ea14422dc599db3eca4341e48db26d72ad' - '01104122e3df765735b1062aa15e7a73c7949f2d9b7332c0e02e02db66345349') + '37fa894055ce94b2d0752c48a89c04d67a2610a3572a788ba7a3cf65e1641c90' + '01104122e3df765735b1062aa15e7a73c7949f2d9b7332c0e02e02db66345349' + '812c9a49436725e18768c5eb772c7207c184cdcf3a057432dc998387c481bd8d' + '9d5a6f2cae6f18e22c5423247570519e8c772a9447ec2d92bd2fe5d69e519470' + '57c17dbd033fff76b344c90114d3b1f9eae3aaaa49128b61fcd1b5e808561dc3' + 'f37b1b6257c5b92272f36773041c83fc72276ff4040100fba92db8136cc9177d' + 'cea307055e9f8001a1507c507e1be91352d896cab17260a221f4ab8c298506d8') install=${pkgname}.install +prepare() { + cd "$srcdir" + ## change path of proxy parameters + sed 's#/etc/nginx/funkwhale_proxy.conf#/etc/webapps/funkwhale/funkwhale_proxy.conf#' nginx.template > nginx.template.patched + ## remove http2, as it is not always working + sed -id 's#443 ssl http2;#443 ssl;#' nginx.template.patched +} build() { cd "$srcdir" @@ -96,17 +117,17 @@ package() { cp -R api "$pkgdir"/usr/share/webapps/${pkgname}/. cp -R front "$pkgdir"/usr/share/webapps/${pkgname}/. chmod 755 -R "$pkgdir"/usr/share/webapps/${pkgname}/api/ + chown root:http -R "$pkgdir"/usr/share/webapps/${pkgname}/api/ + mkdir "$pkgdir"/usr/bin + ln -s /usr/share/webapps/${pkgname}/api/manage.py "$pkgdir"/usr/bin/funkwhale_manage install -d "$pkgdir"/etc/webapps/${pkgname}/config install -Dm644 funkwhale_proxy.conf "$pkgdir"/etc/webapps/${pkgname}/. - install -Dm644 nginx.template "$pkgdir"/etc/webapps/${pkgname}/. + install -Dm644 nginx.template.patched "$pkgdir"/etc/webapps/${pkgname}/nginx.template install -Dm644 apache-funkwhale.conf "$pkgdir"/etc/webapps/${pkgname}/. install -Dm644 env-template "$pkgdir"/etc/webapps/${pkgname}/env.template - install -Dm644 funkwhale.service "$pkgdir/usr/lib/systemd/system/funkwhale.service" - install -Dm644 funkwhale-beat.service "$pkgdir/usr/lib/systemd/system/funkwhale-beat.service" - install -Dm644 funkwhale-worker.service "$pkgdir/usr/lib/systemd/system/funkwhale-worker.service" - install -Dm644 funkwhale-server.service "$pkgdir/usr/lib/systemd/system/funkwhale-server.service" + install -Dm644 funkwhale{,-beat,-worker,-server}.service -t "$pkgdir/usr/lib/systemd/system/" echo -e 'u funkwhale - "Funkwhale music server" /srv/funkwhale\nm funkwhale http' | install -Dm644 /dev/stdin "$pkgdir/usr/lib/sysusers.d/$pkgname.conf" diff --git a/apache-funkwhale.conf b/apache-funkwhale.conf index 9c98ffd063ec..40775f11cd9d 100644 --- a/apache-funkwhale.conf +++ b/apache-funkwhale.conf @@ -5,9 +5,10 @@ Define funkwhale-sn funkwhale.local # use different configuration than what is described in our installation guide. Define funkwhale-api http://localhost:5000 Define funkwhale-api-ws ws://localhost:5000 + Define FUNKWHALE_FRONTEND_PATH /usr/share/webapps/funkwhale/front/dist Define FUNKWHALE_DATA_PATH /srv/funkwhale/data -Define MUSIC_DIRECTORY_PATH ${FUNKWHALE_DATA_PATH}/music +Define APACHE_LOG_DIR /var/log/httpd <IfModule mod_alias.c> Alias /funkwhale ${FUNKWHALE_FRONTEND_PATH} @@ -55,6 +56,10 @@ Define MUSIC_DIRECTORY_PATH ${FUNKWHALE_DATA_PATH}/music # Tell the api that the client is using https RequestHeader set X-Forwarded-Proto "https" + + # Additional security headers +# Header set Referrer-Policy "strict-origin-when-cross-origin" +# Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:" # Configure Proxy settings # ProxyPreserveHost pass the original Host header to the backend server @@ -78,9 +83,13 @@ Define MUSIC_DIRECTORY_PATH ${FUNKWHALE_DATA_PATH}/music # similar to nginx 'client_max_body_size 100M;' LimitRequestBody 104857600 +# Header set X-Frame-Options "sameorigin" +# Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:" +# Header set Referrer-Policy "strict-origin-when-cross-origin" ProxyPass ${funkwhale-api}/ ProxyPassReverse ${funkwhale-api}/ </Location> + <Location "/federation"> ProxyPass ${funkwhale-api}/federation ProxyPassReverse ${funkwhale-api}/federation @@ -97,6 +106,11 @@ Define MUSIC_DIRECTORY_PATH ${FUNKWHALE_DATA_PATH}/music ProxyPassReverse ${funkwhale-api}/.well-known/ </Location> +# <Location "/front/embed.html"> +# Header set X-Frame-Options "allow-from ${funkwhale-sn}" +# </Location> +# Alias /front/embed.html ${FUNKWHALE_FRONTEND_PATH}/embed.html + <Location "/front"> ProxyPass "!" </Location> @@ -144,7 +158,7 @@ Define MUSIC_DIRECTORY_PATH ${FUNKWHALE_DATA_PATH}/music <IfModule mod_xsendfile.c> XSendFile On XSendFilePath ${FUNKWHALE_DATA_PATH}/media - XSendFilePath ${MUSIC_DIRECTORY_PATH} + XSendFilePath ${FUNKWHALE_DATA_PATH}/music SetEnv MOD_X_SENDFILE_ENABLED 1 </IfModule> </VirtualHost> diff --git a/env-template b/env-template index 37e0cbf153d5..3ee084fb3eac 100644 --- a/env-template +++ b/env-template @@ -35,7 +35,9 @@ FUNKWHALE_VERSION=latest # example: FUNKWHALE_API_PORT=5678 FUNKWHALE_API_IP=127.0.0.1 FUNKWHALE_API_PORT=5000 - +# The number of web workers to start in parallel. Higher means you can handle +# more concurrent requests, but also leads to higher CPU/Memory usage +FUNKWHALE_WEB_WORKERS=1 # Replace this by the definitive, public domain you will use for # your instance FUNKWHALE_HOSTNAME=funkwhale.local @@ -108,6 +110,9 @@ DJANGO_SECRET_KEY= RAVEN_ENABLED=false RAVEN_DSN=https://44332e9fdd3d42879c7d35bf8562c6a4:0062dc16a22b41679cd5765e5342f716@sentry.eliotberriot.com/5 +# Denormalized audio permission logic in a separate table to enhance performance +MUSIC_USE_DENORMALIZATION=True + # In-place import settings # You can safely leave those settings uncommented if you don't plan to use # in place imports. diff --git a/funkwhale-beat.service b/funkwhale-beat.service index d9b36b9c3584..6cacc92e1976 100644 --- a/funkwhale-beat.service +++ b/funkwhale-beat.service @@ -5,9 +5,10 @@ PartOf=funkwhale.service [Service] User=funkwhale +WorkingDirectory=/usr/share/webapps/funkwhale/api # adapt this depending on the path of your funkwhale installation EnvironmentFile=/srv/funkwhale/config/env -ExecStart=/usr/bin/celery -A funkwhale_api.taskapp beat -l INFO --workdir=/usr/share/webapps/funkwhale/api --schedule=/srv/funkwhale/api/celerybeat-schedule --pidfile=/srv/funkwhale/api/celerybeat.pid +ExecStart=/usr/bin/celery --workdir=/usr/share/webapps/funkwhale/api -A funkwhale_api.taskapp beat -l INFO --schedule=/srv/funkwhale/api/celerybeat-schedule --pidfile=/srv/funkwhale/api/celerybeat.pid [Install] WantedBy=multi-user.target diff --git a/funkwhale-server.service b/funkwhale-server.service index 30dcc38b4eb0..0bbfb7f695d5 100644 --- a/funkwhale-server.service +++ b/funkwhale-server.service @@ -8,7 +8,8 @@ User=funkwhale # adapt this depending on the path of your funkwhale installation WorkingDirectory=/usr/share/webapps/funkwhale/api EnvironmentFile=/srv/funkwhale/config/env -ExecStart=/usr/bin/daphne -b ${FUNKWHALE_API_IP} -p ${FUNKWHALE_API_PORT} config.asgi:application --proxy-headers +ExecStart=/usr/bin/gunicorn config.asgi:application -w ${FUNKWHALE_WEB_WORKERS} -k uvicorn.workers.UvicornWorker -b ${FUNKWHALE_API_IP}:${FUNKWHALE_API_PORT} +#ExecStart=/usr/bin/daphne -b ${FUNKWHALE_API_IP} -p ${FUNKWHALE_API_PORT} config.asgi:application --proxy-headers [Install] WantedBy=multi-user.target diff --git a/funkwhale-worker.service b/funkwhale-worker.service index 494b52a02b52..a0185ad976fa 100644 --- a/funkwhale-worker.service +++ b/funkwhale-worker.service @@ -7,6 +7,7 @@ PartOf=funkwhale.service User=funkwhale # adapt this depending on the path of your funkwhale installation EnvironmentFile=/srv/funkwhale/config/env +WorkingDirectory=/usr/share/webapps/funkwhale/api # Celery workers handle background tasks (such file imports or federation # messaging). The more processes a worker gets, the more tasks # can be processed in parallel. However, more processes also means @@ -15,7 +16,7 @@ EnvironmentFile=/srv/funkwhale/config/env # of CPUs. You can adjust this, by explicitly setting the --concurrency # flag: # celery -A funkwhale_api.taskapp worker -l INFO --concurrency=4 -ExecStart=/usr/bin/celery -A funkwhale_api.taskapp worker -l INFO --workdir=/usr/share/webapps/funkwhale/api +ExecStart=/usr/bin/celery --workdir=/usr/share/webapps/funkwhale/api -A funkwhale_api.taskapp worker -l INFO [Install] WantedBy=multi-user.target diff --git a/funkwhale.install b/funkwhale.install index 7a5d94c62d57..a06b180599ce 100644 --- a/funkwhale.install +++ b/funkwhale.install @@ -1,10 +1,16 @@ post_install() { + echo "This package is subject to dependency incompatibilities, use `funkwhale-venv` instead." echo "Follow instructions on the upstream page or on the Arch Wiki for setting up the Funkwhale server:" echo "https://wiki.archlinux.org/index.php/Funkwhale" } post_upgrade() { + echo "This package is subject to dependency incompatibilities, use `funkwhale-venv` instead." echo "Follow instructions on the upstream page or on the Arch Wiki for updating" - echo "If updating from v0.18, the apache and nginx configuration files have been changed, make sure to update them from the templates." + #echo "Type the password for the funkwhale user, then environment variables are loaded, static files are collected and the database is migrated." + #sudo -u funkwhale -H bash + #export $(cat /srv/funkwhale/config/env | grep -v ^# | xargs) + #funkwhale_manage collectstatic --no-input + #funkwhale_manage migrate } |