Howto install Funkwhale 0.20.1

Triggered by @lclaude in Feature request: Funkwhale, federated music streaming, here are install instructions for Funkwhale, a free and decentralized audio platform.

You need a domain (example.com is used here) pointing to your Nethserver with a valid cert (for instance letsencrypt).

# get nux repo for ffmpeg
rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm

# install dependencies
yum -y install nethserver-postgresql94 nethserver-redis curl gcc python3-pip git unzip ffmpeg make curl file ffmpeg libjpeg-turbo libpqxx python-devel openldap-devel rh-postgresql94-postgresql-contrib python3-devel mod_xsendfile

# add funkwhale service user
useradd -r -s /usr/sbin/nologin -d /srv/funkwhale -m funkwhale
chmod 755 /srv/funkwhale

You may change the password “SECRET” of the postgresql user funkwhale to a more secure one:

# create db, user and extensions
su - postgres -c 'scl enable rh-postgresql94 -- psql -p 55432'
create database funkwhale with template = template0 encoding 'utf8';
create user funkwhale with encrypted password 'SECRET';
grant all privileges on database funkwhale to funkwhale;
\c funkwhale
CREATE EXTENSION unaccent;
CREATE EXTENSION citext;
\q

# get service files
curl -L -o "/etc/systemd/system/funkwhale.target" "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/0.20.1/deploy/funkwhale.target"
curl -L -o "/etc/systemd/system/funkwhale-server.service" "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/0.20.1/deploy/funkwhale-server.service"
curl -L -o "/etc/systemd/system/funkwhale-worker.service" "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/0.20.1/deploy/funkwhale-worker.service"
curl -L -o "/etc/systemd/system/funkwhale-beat.service" "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/0.20.1/deploy/funkwhale-beat.service"

# download funkwhale apache config
curl -L -o /etc/httpd/conf.d/zzz_funkwhale.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/0.20.1/deploy/apache.conf"

Edit example.com to match your domain.

sed -i 's!Define funkwhale-sn funkwhale.yourdomain.com!Define funkwhale-sn example.com!' /etc/httpd/conf.d/zzz_funkwhale.conf

# add letsencrypt exception
sed -i '12 i\
<VirtualHost *:80>\
   ServerName ${funkwhale-sn}\
   RedirectMatch 301 ^(?!/\\.well-known/acme-challenge/).* https://${funkwhale-sn}\
</VirtualHost>\
' /etc/httpd/conf.d/zzz_funkwhale.conf

# comment out wrong log path
sed -i '38,39 s/^ /# /' /etc/httpd/conf.d/zzz_funkwhale.conf

# comment out wrong cert paths
sed -i '49,51 s/^ /# /' /etc/httpd/conf.d/zzz_funkwhale.conf

# work as user funkwhale from now on
sudo -u funkwhale -H bash
cd /srv/funkwhale

# Create dirs
mkdir -p config api data/static data/media data/music front

# get funkwhale api
curl -L -o "api-0.20.1.zip" "https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/0.20.1/download?job=build_api"
unzip "api-0.20.1.zip" -d extracted
mv extracted/api/* api/
rm -rf extracted

# Get frontend 
curl -L -o "front-0.20.1.zip" "https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/0.20.1/download?job=build_front"
unzip "front-0.20.1.zip" -d extracted
mv extracted/front/dist front/
rm -rf extracted

# Create virtual environment
python3 -m venv /srv/funkwhale/virtualenv

# Use venv
source /srv/funkwhale/virtualenv/bin/activate

# get python dependencies
pip install wheel service_identity
pip install -r api/requirements.txt

# get environment file
curl -L -o config/.env "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/master/deploy/env.prod.sample"

# secure config file
chmod 600 /srv/funkwhale/config/.env

Again you need to edit example.com:

# edit hostname
sed -i 's!FUNKWHALE_HOSTNAME=yourdomain.funkwhale!FUNKWHALE_HOSTNAME=example.com!' /srv/funkwhale/config/.env

# set proxy type to apache2
sed -i 's!REVERSE_PROXY_TYPE=nginx!REVERSE_PROXY_TYPE=apache2!' /srv/funkwhale/config/.env

# add random django secret key
sed -i 's!DJANGO_SECRET_KEY=$!DJANGO_SECRET_KEY='"$(openssl rand -base64 45)"'!' /srv/funkwhale/config/.env

If you changed the postgresql password you have to edit it here too:

# add postgresql and redis config - the empty line is necessary
cat >> /srv/funkwhale/config/.env <<EOF

DATABASE_URL=postgresql://funkwhale:SECRET@localhost:55432/funkwhale
CACHE_URL=redis://127.0.0.1:6379/0
EOF

# fill DB
python api/manage.py migrate

# create superuser admin
python api/manage.py createsuperuser

Now you are asked for the new superusers name, mail and password:

(virtualenv) [funkwhale@testserver ~]$ python api/manage.py createsuperuser
2019-12-06 21:55:44,866 funkwhale_api.config INFO     Loaded env file at /srv/funkwhale/config/.env
2019-12-06 21:55:44,867 funkwhale_api.config INFO     Running with no plugins
Username: admin
Email address: mail@example.com
Password:
Password (again):
Superuser created successfully.

Now we create the static files and start the services.

# create static files
python api/manage.py collectstatic

# exit as user funkwhale to be root again
exit

# start and enable services
systemctl daemon-reload
systemctl enable funkwhale-server funkwhale-worker funkwhale-beat
systemctl restart httpd funkwhale.target

Browse to https://<USED_DOMAIN> and login with the credentials set before.

Funkwhale supports LDAP too:

Sources:


8 Likes

Very niiice job @mrmarkuz!
Many thanks, i’m on hollydays and i’ll test it in january.

1 Like

Are there any known conflicts with other applications that are available through either nethserver-rpm’s or install howto’s in our wiki? (ports, services etc)

I don’t see anything about passwords… what do you mean?

In the DATABASE_URL:

Not yet but I tried to write a safe howto:
It’s a separate python3 environment used and no system package is touched.
Funkwhale is reverse proxied and uses localhost:5000 that is not in the port list.

1 Like

I think this is not completely clear.
I think both yourdomain.com and example.com need to be replaced by your own domain.tld Am I right?
Or is example.com commented out here? Or must example.com be set as the url where you want funkwhale to be reachable from? (IE funkwhale.domain.tld)

There must be some error in a conf file because I get a bad request (400) when I go to the funkwhale url…

The command is replacing the first text string with another one. I guess funkwhale.yourdomain.com is a hardcoded example from upstream and the only part of the command we are required to edit is example.com. Would be the same editing the file with our preferred text editor.

Yes, but it you ran the command now sed won’t match the search string.

1 Like

I checked the conf file and afaik that line (2nd line in the file) is ok:

Define funkwhale-sn funkwhale.domain.tld

The rewrite to force https seems to work ok because when I go to the non https version, it changes to https automatically

Haven’t tried. Maybe we need to create a server alias for the virtual host.

Yes, replace any example.com with your domain.

Did you setup a valid cert?

I did that, but still no go… as mentioned, I am getting a bad request (400)

I added the subdomain to the letsencrypt cert…

Please check /var/log/messages and /var/log/httpd/*

Did you restart the relevant services? Did you set cert with cockpit? Try old server manager.

I am still on the old servermanager… old habits don’t die easy… :wink:

found this in /var/log/messages:

Dec 7 20:19:17 ns7 gunicorn: 2019-12-07 19:19:17,540 django.security.DisallowedHost ERROR Invalid HTTP_HOST header: ‘funkwhale.domain.tld’. You may need to add 'funkwhale.domain.tld to ALLOWED_HOSTS.

django is a service used with funkwhale… what did I miss in setting up?

It doesn’t state what cfg file this is set…

Did you do the following?

chmod 755 /srv/funkwhale

yes I did, but when I look at permissions in /srv/funkwhale not every dir and file has 755 (rwe-r.e-r.e) permissions

Any idea where I can find the settings.py file?

Could you please share your /etc/httpd/conf.d/zzz_funkwhale.conf and /srv/funkwhale/config/.env ?

It should work without changing python settings.

See PM…

Now you have “Server Error (500)”, is there another error message in the logfile now?

EDIT:

More logs:

Reverse proxy: /var/log/httpd/*.log
API logs: journalctl -xn -u funkwhale-server
Celery logs: journalctl -xn -u funkwhale-worker

Let me check
a LOT of reecurring entries of this in API logs:

– Logs begin at Sat 2019-12-07 17:16:37 CET, end at Sat 2019-12-07 23:15:39 CET. –
Dec 07 23:14:30 ns7.domain.tld gunicorn[12101]: File “/srv/funkwhale/virtualenv/lib64/python3.6/site-packages/requests/api.py”, line 60, in request
Dec 07 23:14:30 ns7.domain.tld gunicorn[12101]: return session.request(method=method, url=url, **kwargs)
Dec 07 23:14:30 ns7.domain.tld gunicorn[12101]: File “/srv/funkwhale/virtualenv/lib64/python3.6/site-packages/requests/sessions.py”, line 533, in request
Dec 07 23:14:30 ns7.domain.tld gunicorn[12101]: resp = self.send(prep, **send_kwargs)
Dec 07 23:14:30 ns7.domain.tld gunicorn[12101]: File “/srv/funkwhale/virtualenv/lib64/python3.6/site-packages/requests/sessions.py”, line 646, in send
Dec 07 23:14:30 ns7.domain.tld gunicorn[12101]: r = adapter.send(request, **kwargs)
Dec 07 23:14:30 ns7.domain.tld gunicorn[12101]: File “/srv/funkwhale/virtualenv/lib64/python3.6/site-packages/requests/adapters.py”, line 516, in send
Dec 07 23:14:30 ns7.domain.tld gunicorn[12101]: raise ConnectionError(e, request=request)
Dec 07 23:14:30 ns7.domain.tld gunicorn[12101]: requests.exceptions.ConnectionError: HTTPSConnectionPool(host=‘funkwhale.domain.tld’, port=443): Max retries exceeded with url: /front/
Dec 07 23:14:30 ns7.domain.tld gunicorn[12101]: 2019-12-07 22:14:30,362 uvicorn.access INFO 213.127.104.224:0 - “GET /favicon.ico HTTP/1.1” 500

hey, thanks for the guide! could complete all steps without any issues, starting the service throws me an error tough. the thing is i was stubborn and changed the funkwhale version to 1.0. so that is totally on me…will try it again tomorrow with 20.1.

systemctl status funkwhale-\*
● funkwhale-worker.service - Funkwhale celery worker
   Loaded: loaded (/etc/systemd/system/funkwhale-worker.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Fri 2020-10-02 00:05:52 CEST; 20s ago
  Process: 10984 ExecStart=/srv/funkwhale/virtualenv/bin/celery -A funkwhale_api.taskapp worker -l INFO --concurrency=${CELERYD_CONCURRENCY-0} (code=exited, status=2)
 Main PID: 10984 (code=exited, status=2)

Oct 02 00:05:52 xxx systemd[1]: Started Funkwhale celery worker.
Oct 02 00:05:52 xxx celery[10984]: usage: celery worker [options]
Oct 02 00:05:52 xxx celery[10984]: celery: error: argument -c/--concurrency: invalid int value: ''
Oct 02 00:05:52 xxx systemd[1]: funkwhale-worker.service: main process exited, code=exited, status=2/INVALIDARGUMENT
Oct 02 00:05:52 xxx systemd[1]: Unit funkwhale-worker.service entered failed state.
Oct 02 00:05:52 xxx systemd[1]: funkwhale-worker.service failed.

● funkwhale-beat.service - Funkwhale celery beat process
   Loaded: loaded (/etc/systemd/system/funkwhale-beat.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2020-10-02 00:05:52 CEST; 21s ago
 Main PID: 10985 (celery)
   CGroup: /system.slice/funkwhale-beat.service
           └─10985 /srv/funkwhale/virtualenv/bin/python3 /srv/funkwhale/virtualenv/bin/celery -A funkwhale_api.taskapp beat -l INFO

Oct 02 00:05:52 xxx systemd[1]: Started Funkwhale celery beat process.
Oct 02 00:05:52 xxx celery[10985]: 2020-10-02 00:05:52,736 funkwhale_api.config INFO     Loaded env file at /srv/funkwhale/config/.env
Oct 02 00:05:52 xxx celery[10985]: 2020-10-02 00:05:52,737 funkwhale_api.config INFO     Running with the following plugins enabled: funkwhale_api.contrib.scrobbler
Oct 02 00:05:54 xxx celery[10985]: [2020-10-01 22:05:54,328: INFO/MainProcess] beat: Starting...

● funkwhale-server.service - Funkwhale application server
   Loaded: loaded (/etc/systemd/system/funkwhale-server.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Fri 2020-10-02 00:05:52 CEST; 20s ago
  Process: 10982 ExecStart=/srv/funkwhale/virtualenv/bin/gunicorn config.asgi:application -w ${FUNKWHALE_WEB_WORKERS} -k uvicorn.workers.UvicornWorker -b ${FUNKWHALE_API_IP}:${FUNKWHALE_API_PORT} (code=exited, status=3)
 Main PID: 10982 (code=exited, status=3)

Oct 02 00:05:52 xxx gunicorn[10982]: File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
Oct 02 00:05:52 xxx gunicorn[10982]: File "/srv/funkwhale/virtualenv/lib64/python3.6/site-packages/uvicorn/loops/uvloop.py", line 3, in <module>
Oct 02 00:05:52 xxx gunicorn[10982]: import uvloop
Oct 02 00:05:52 xxx gunicorn[10982]: ModuleNotFoundError: No module named 'uvloop'
Oct 02 00:05:52 xxx gunicorn[10982]: [2020-10-02 00:05:52 +0200] [10996] [INFO] Worker exiting (pid: 10996)
Oct 02 00:05:52 xxx gunicorn[10982]: [2020-10-02 00:05:52 +0200] [10982] [INFO] Shutting down: Master
Oct 02 00:05:52 xxx gunicorn[10982]: [2020-10-02 00:05:52 +0200] [10982] [INFO] Reason: Worker failed to boot.
Oct 02 00:05:52 xxx systemd[1]: funkwhale-server.service: main process exited, code=exited, status=3/NOTIMPLEMENTED
Oct 02 00:05:52 xxx systemd[1]: Unit funkwhale-server.service entered failed state.
Oct 02 00:05:52 xxx systemd[1]: funkwhale-server.service failed.
1 Like