Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • funkwhale/funkwhale
  • Luclu7/funkwhale
  • mbothorel/funkwhale
  • EorlBruder/funkwhale
  • tcit/funkwhale
  • JocelynDelalande/funkwhale
  • eneiluj/funkwhale
  • reg/funkwhale
  • ButterflyOfFire/funkwhale
  • m4sk1n/funkwhale
  • wxcafe/funkwhale
  • andybalaam/funkwhale
  • jcgruenhage/funkwhale
  • pblayo/funkwhale
  • joshuaboniface/funkwhale
  • n3ddy/funkwhale
  • gegeweb/funkwhale
  • tohojo/funkwhale
  • emillumine/funkwhale
  • Te-k/funkwhale
  • asaintgenis/funkwhale
  • anoadragon453/funkwhale
  • Sakada/funkwhale
  • ilianaw/funkwhale
  • l4p1n/funkwhale
  • pnizet/funkwhale
  • dante383/funkwhale
  • interfect/funkwhale
  • akhardya/funkwhale
  • svfusion/funkwhale
  • noplanman/funkwhale
  • nykopol/funkwhale
  • roipoussiere/funkwhale
  • Von/funkwhale
  • aurieh/funkwhale
  • icaria36/funkwhale
  • floreal/funkwhale
  • paulwalko/funkwhale
  • comradekingu/funkwhale
  • FurryJulie/funkwhale
  • Legolars99/funkwhale
  • Vierkantor/funkwhale
  • zachhats/funkwhale
  • heyjake/funkwhale
  • sn0w/funkwhale
  • jvoisin/funkwhale
  • gordon/funkwhale
  • Alexander/funkwhale
  • bignose/funkwhale
  • qasim.ali/funkwhale
  • fakegit/funkwhale
  • Kxze/funkwhale
  • stenstad/funkwhale
  • creak/funkwhale
  • Kaze/funkwhale
  • Tixie/funkwhale
  • IISergII/funkwhale
  • lfuelling/funkwhale
  • nhaddag/funkwhale
  • yoasif/funkwhale
  • ifischer/funkwhale
  • keslerm/funkwhale
  • flupe/funkwhale
  • petitminion/funkwhale
  • ariasuni/funkwhale
  • ollie/funkwhale
  • ngaumont/funkwhale
  • techknowlogick/funkwhale
  • Shleeble/funkwhale
  • theflyingfrog/funkwhale
  • jonatron/funkwhale
  • neobrain/funkwhale
  • eorn/funkwhale
  • KokaKiwi/funkwhale
  • u1-liquid/funkwhale
  • marzzzello/funkwhale
  • sirenwatcher/funkwhale
  • newer027/funkwhale
  • codl/funkwhale
  • Zwordi/funkwhale
  • gisforgabriel/funkwhale
  • iuriatan/funkwhale
  • simon/funkwhale
  • bheesham/funkwhale
  • zeoses/funkwhale
  • accraze/funkwhale
  • meliurwen/funkwhale
  • divadsn/funkwhale
  • Etua/funkwhale
  • sdrik/funkwhale
  • Soran/funkwhale
  • kuba-orlik/funkwhale
  • cristianvogel/funkwhale
  • Forceu/funkwhale
  • jeff/funkwhale
  • der_scheibenhacker/funkwhale
  • owlnical/funkwhale
  • jovuit/funkwhale
  • SilverFox15/funkwhale
  • phw/funkwhale
  • mayhem/funkwhale
  • sridhar/funkwhale
  • stromlin/funkwhale
  • rrrnld/funkwhale
  • nitaibezerra/funkwhale
  • jaller94/funkwhale
  • pcouy/funkwhale
  • eduxstad/funkwhale
  • codingHahn/funkwhale
  • captain/funkwhale
  • polyedre/funkwhale
  • leishenailong/funkwhale
  • ccritter/funkwhale
  • lnceballosz/funkwhale
  • fpiesche/funkwhale
  • Fanyx/funkwhale
  • markusblogde/funkwhale
  • Firobe/funkwhale
  • devilcius/funkwhale
  • freaktechnik/funkwhale
  • blopware/funkwhale
  • cone/funkwhale
  • thanksd/funkwhale
  • vachan-maker/funkwhale
  • bbenti/funkwhale
  • tarator/funkwhale
  • prplecake/funkwhale
  • DMarzal/funkwhale
  • lullis/funkwhale
  • hanacgr/funkwhale
  • albjeremias/funkwhale
  • xeruf/funkwhale
  • llelite/funkwhale
  • RoiArthurB/funkwhale
  • cloo/funkwhale
  • nztvar/funkwhale
  • Keunes/funkwhale
  • petitminion/funkwhale-petitminion
  • m-idler/funkwhale
  • SkyLeite/funkwhale
140 results
Select Git revision
Show changes
Optimizing your Funkwhale instance
==================================
Depending on your requirements, you may want to reduce as much as possible
Funkwhale's memory footprint.
Reduce workers concurrency
--------------------------
Asynchronous tasks are handled by a celery worker, which will by default
spawn a worker process per CPU available. This can lead to a higher
memory usage.
You can control this behavior using the ``--concurrency`` flag.
For instance, setting ``--concurrency=1`` will spawn only one worker.
This flag should be appended after the ``celery -A funkwhale_api.taskapp
worker`` command in your :file:`docker-compose.yml` file if your using Docker,
or in your :file:`/etc/systemd/system/funkwhale-worker.service` otherwise.
.. note::
Reducing concurrency comes at a cost: asynchronous tasks will be processed
more slowly. However, on small instances, this should not be an issue.
Switch from prefork to solo pool
--------------------------------
Using a different pool implementation for Celery tasks may also help.
Using the ``solo`` pool type should reduce your memory consumption.
You can control this behavior using the ``--pool=solo`` flag.
This flag should be appended after the ``celery -A funkwhale_api.taskapp worker``
command in your :file:`docker-compose.yml` file if you're using Docker, or in
your :file:`/etc/systemd/system/funkwhale-worker.service` otherwise.
Troubleshooting
===============
Various errors and issues can arise on your Funkwhale instance, caused by configuration errors,
deployment/environment specific issues, or bugs in the software itself.
On this document, you'll find:
- Tools and commands you can use to better understand the issues
- A list of common pitfalls and errors and how to solve them
- A collection of links and advice to get help from the community and report new issues
Diagnose problems
^^^^^^^^^^^^^^^^^
Funkwhale is made of several components, each one being a potential cause for failure. Having an even basic overview
of Funkwhale's technical architecture can help you understand what is going on. You can refer to :doc:`the technical architecture <../developers/architecture>` for that.
Problems usually fall into one of those categories:
- **Frontend**: Funkwhale's interface is not loading, not behaving as expected, music is not playing
- **API**: the interface do not display any data or show errors
- **Import**: uploaded/imported tracks are not imported correctly or at all
- **Federation**: you cannot contact other Funkwhale servers, access their library, play federated tracks
- **Everything else**
Each category comes with its own set of diagnose tools and/or commands we will detail below. We'll also give you simple
steps for each type of problem. Please try those to see if it fix your issues. If none of those works, please report your issue on our
issue tracker.
.. note::
To get detailed log messages, set the environment variable ``LOGLEVEL=debug``.
If you are using the docker setup you can configure this in the ``.env`` file.
Backend issues
^^^^^^^^^^^^^^
Diagnostic tools:
- Reverse proxy logs:
- Apache logs should be available at :file:`/var/log/apache/access.log` and :file:`/var/log/apache/error.log`
- Nginx logs should be available at :file:`/var/log/nginx/access.log` and :file:`/var/log/nginx/error.log`
- API logs:
- Docker setup: ``docker-compose logs -f --tail=50 api`` (remove the ``--tail`` flag to get the full logs)
- Non-docker setup: ``journalctl -xn -u funkwhale-server``
.. note::
If you edit your .env file to test a new configuration, you have to restart your services to pick up the changes:
- Docker setup: ``docker-compose up -d``
- Non-docker setup: ``systemctl restart funkwhale.target``
Common problems
***************
Instance works properly, but audio files are not served (404 error)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- If you're using docker, ensure the ``MEDIA_ROOT`` variable is commented in your env file
- Ensure the ``_protected/media`` block points toward the path where media files are stored (``/srv/funkwhale/data/media``, by default)
- If you're using in-place import, ensure :data:`MUSIC_DIRECTORY_PATH <config.settings.common.MUSIC_DIRECTORY_PATH>`, :data:`MUSIC_DIRECTORY_SERVE_PATH <config.settings.common.MUSIC_DIRECTORY_SERVE_PATH>` and :data:`REVERSE_PROXY_TYPE <config.settings.common.REVERSE_PROXY_TYPE>` are configured properly, and that the files are readable by the webserver
Weakref error when running ``python manage.py <command>``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
On Python <3.6, you may see this kind of errors when running commands like ``python manage.py migrate``::
Exception ignored in: <function WeakValueDictionary.__init__.<locals>.remove at 0x107e7a6a8>
Traceback (most recent call last):
File "/srv/funkwhale/venv/lib/python3.5/weakref.py", line 117, in remove
TypeError: 'NoneType' object is not callable
This is caused by a bug in Python (cf https://github.com/celery/celery/issues/3818), and is not affecting in any way
the command you execute. You can safely ignore this error.
``Your models have changes that are not yet reflected in a migration`` warning
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When running ``python manage.py migrate`` (both in docker or non-docker), you may end-up with this::
Operations to perform:
Apply all migrations: account, admin, auth, authtoken, common, contenttypes, dynamic_preferences, favorites, federation, history, music, playlists, radios, requests, sessions, sites, socialaccount, taggit, users
Running migrations:
No migrations to apply.
Your models have changes that are not yet reflected in a migration, and so won't be applied.
Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.
This warning can be safely ignored. You should not run the suggested ``manage.py makemigrations`` command.
File import issues
^^^^^^^^^^^^^^^^^^
Unless you are using the CLI to import files, imports are send as tasks in a queue to a celery worker that will process them.
Diagnostic tools:
- Celery worker logs:
- Docker setup: ``docker-compose logs -f --tail=50 celeryworker`` (remove the ``--tail`` flag to get the full logs)
- Non-docker setup: ``journalctl -xn -u funkwhale-worker``
Federation issues
^^^^^^^^^^^^^^^^^
Received federations messages are sent to a dedicated task queue and processed asynchronously by a celery worker.
Diagnostic tools:
- API logs:
- Docker setup: ``docker-compose logs -f --tail=50 api`` (remove the ``--tail`` flag to get the full logs)
- Non-docker setup: ``journalctl -xn -u funkwhale-server``
- Celery worker logs:
- Docker setup: ``docker-compose logs -f --tail=50 celeryworker`` (remove the ``--tail`` flag to get the full logs)
- Non-docker setup: ``journalctl -xn -u funkwhale-worker``
Common problems
***************
I have no access to another instance library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Check if it works with the demo library (library@demo.funkwhale.audio)
- Check if the remote library received your follow request and approved it
- Trigger a scan via the interface
- Have a look in the celery logs for potential errors during the scan
Other problems
^^^^^^^^^^^^^^
It's a bit hard to give targeted advice about problems that do not fit in the previous categories. However, we can recommend to:
- Try to identify the scope of the issue and reproduce it reliably
- Ensure your instance is configured as detailed in the installation documentation, and if you did not use the default
values, to check what you changed
- To read the .env file carefully, as most of the options are described in the comments
Report an issue or get help
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Well be more than happy to help you to debug installation and configuration issues. The main channel
for receiving support about your Funkwhale installation is the `#funkwhale-troubleshooting:matrix.org <https://matrix.to/#/#funkwhale-troubleshooting:matrix.org>`_ Matrix channel.
Before asking for help, we'd really appreciate if you took the time to go through this document and try to diagnose the problem yourself. But if you don't find
anything relevant or don't have the time, we'll be there for you!
Here are a few recommendations on how to structure and what to include in your help requests:
- Give us as much context as possible about your installation (OS, version, Docker/non-docker, reverse-proxy type, relevant logs and errors, etc.)
- Including screenshots or small gifs or videos can help us considerably when debugging front-end issues
You can also open issues on our `issue tracker <https://dev.funkwhale.audio/funkwhale/funkwhale/issues>`_. Please have a quick look for
similar issues before doing that, and use the issue tracker only to report bugs, suggest enhancements (both in the software and the documentation) or new features.
.. warning::
If you ever need to share screenshots or urls with someone else, ensure those do not include your personal token.
This token is binded to your account and can be used to connect and use your account.
Urls that includes your token looks like: ``https://your.instance/api/v1/uploads/42/serve/?jwt=yoursecrettoken``
Improving this documentation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you feel like something should be improved in this document (and in the documentation in general), feel free to :doc:`contribute to the documentation <../documentation/creating>`.
If you're not comfortable contributing or would like to ask somebody else to do it, feel free to :doc:`request a change in documentation <../documentation/identifying>`.
Uninstall Funkwhale
===================
The following instructions helps you remove Funkwhale from your server, for instance after migrating to another server, or if you do not want to use Funkwhale anymore.
.. warning::
The following instructions cannot be undone and might result in loss of data. If necessary, please make a backup of your server following the :doc:`backup instructions<backup>`.
Especially, it must be noted that:
- Remote content hosted on an S3 or S3-compatible server will not be removed.
- In place imports will not be removed, provided they are located outside ``/srv/funkwhale/``
.. note::
These instructions apply only for the manual installation on Debian or Arch Linux. It matches the default setup.
First, stop the all funkwhale related services:
.. code-block:: shell
sudo systemctl stop funkwhale.target
Remove the reverse proxy configuration data and reload the reverse proxy.
If you are using nginx:
.. code-block:: shell
sudo rm /etc/nginx/sites-enabled/funkwhale.conf
sudo rm /etc/nginx/sites-available/funkwhale.conf
sudo rm /etc/nginx/funkwhale_proxy.conf
sudo systemctl reload nginx
If you are using Apache2:
.. code-block:: shell
sudo rm /etc/apache2/sites-enabled/funkwhale.conf
sudo rm /etc/apache2/sites-available/funkwhale.conf
sudo service apache2 restart
Remove the systemd services:
.. code-block:: shell
sudo systemctl disable funkwhale-server
sudo systemctl disable funkwhale-worker
sudo systemctl disable funkwhale-beat
sudo rm /etc/systemd/system/funkwhale-server.service
sudo rm /etc/systemd/system/funkwhale-worker.service
sudo rm /etc/systemd/system/funkwhale-beat.service
sudo rm /etc/systemd/system/funkwhale.target
sudo systemctl daemon-reload
sudo systemctl reset-failed
Then, remove the database:
.. code-block:: shell
sudo -u postgres psql -c 'DROP DATABASE funkwhale;'
sudo -u postgres psql -c 'DROP USER funkwhale;'
Finally, remove the user ``funkwhale`` and all funkwhale related data, including the server and the data:
.. code-block:: shell
sudo userdel -r funkwhale
.. warning::
The last command will remove ``/srv/funkwhale/``. On the default setup, this directory contains all user data. Please proceed cautiously!
However, it must be noted that:
- Remote content hosted on an S3 or S3-compatible server will not be removed.
- In place imports will not be removed, provided they are not located in the directory ``/srv/funkwhale/``
.. note::
If relevant, you might also want to:
- remove the SSL certificates;
- remove the corresponding DNS entries.
\ No newline at end of file
Upgrading your Funkwhale instance to a newer version
====================================================
.. note::
Before upgrading your instance, we strongly advise you to make at least a database backup. Ideally, you should make a full backup, including
the database and the media files.
We're commited to make upgrade as easy and straightforward as possible,
however, Funkwhale is still in development and you'll be safer with a backup.
Reading the release notes
-------------------------
Please take a few minutes to read the :doc:`../changelog`: updates should work
similarly from version to version, but some of them may require additional steps.
Those steps would be described in the version release notes.
Insights about new versions
---------------------------
Some versions may be bigger than usual, and we'll try to detail the changes
when possible.
.. toctree::
:maxdepth: 1
0.17
Docker setup
------------
If you've followed the setup instructions in :doc:`../installation/docker`, upgrade path is
easy:
Mono-container installation
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Basically, you need to pull the new container image, stop and delete your existing container,
and relaunch a new one:
To upgrade your service, change the version number of the image in ``docker-compose.yml`` with the latest release (i.e. |version|).
Pull the new images:
.. code-block:: shell
docker-compose pull
Restart the service:
.. code-block:: shell
docker-compose up -d
Multi-container installation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. parsed-literal::
# this assumes you want to upgrade to version "|version|"
export FUNKWHALE_VERSION="|version|"
.. code-block:: shell
cd /srv/funkwhale
# hardcode the targeted version your env file
# (look for the FUNKWHALE_VERSION variable)
nano .env
# Load your environment variables
source .env
# Download newest nginx configuration file
curl -L -o nginx/funkwhale.template "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/docker.nginx.template"
curl -L -o nginx/funkwhale_proxy.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/docker.funkwhale_proxy.conf"
# Pull the new version containers
docker-compose pull
# Apply the database migrations
docker-compose run --rm api python manage.py migrate
# Relaunch the containers
docker-compose up -d
.. warning::
You may sometimes get the following warning while applying migrations::
"Your models have changes that are not yet reflected in a migration, and so won't be applied."
This is a warning, not an error, and it can be safely ignored.
Never run the ``makemigrations`` command yourself.
Upgrading the Postgres container
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
With some Funkwhale releases, it is recommended to upgrade the version of the
Postgres database server container. For example, Funkwhale 0.17 recommended
Postgres 9.4, but Funkwhale 0.18 recommends Postgres 11. When upgrading
Postgres, it is not sufficient to change the container referenced in
``docker-compose.yml``. New major versions of Postgres cannot read the databases
created by older major versions. The data has to be exported from a running
instance of the old version and imported by the new version.
Thankfully, there is a Docker container available to automate this process. You
can use the following snippet to upgrade your database in ``./postgres``,
keeping a backup of the old version in ``./postgres-old``:
.. code-block:: shell
# Replace "9.4" and "11" with the versions you are migrating between.
export OLD_POSTGRES=9.4
export NEW_POSTGRES=11
docker-compose stop postgres
docker run --rm \
-v $(pwd)/data/postgres:/var/lib/postgresql/${OLD_POSTGRES}/data \
-v $(pwd)/data/postgres-new:/var/lib/postgresql/${NEW_POSTGRES}/data \
tianon/postgres-upgrade:${OLD_POSTGRES}-to-${NEW_POSTGRES}
# Add back the access control rule that doesn't survive the upgrade
echo "host all all all trust" | sudo tee -a ./data/postgres-new/pg_hba.conf
# Swap over to the new database
mv ./data/postgres ./data/postgres-old
mv ./data/postgres-new ./data/postgres
Non-docker setup
----------------
If you installed Funkwhale using the install script, upgrading is done using ``sh -c "$(curl -sSL https://get.funkwhale.audio/upgrade.sh)"``. Make sure to run this command with root permissions.
If you manually installed Funkwhale, please use the following instructions.
Upgrade the static files
^^^^^^^^^^^^^^^^^^^^^^^^
On non-docker setups, the front-end app
is updated separately from the API. This is as simple as downloading
the zip with the static files and extracting it in the correct place.
The following example assume your setup match :ref:`frontend-setup`.
.. parsed-literal::
# this assumes you want to upgrade to version "|version|"
export FUNKWHALE_VERSION="|version|"
cd /srv/funkwhale
sudo -u funkwhale curl -L -o front.zip "https://dev.funkwhale.audio/funkwhale/funkwhale/builds/artifacts/$FUNKWHALE_VERSION/download?job=build_front"
sudo -u funkwhale unzip -o front.zip
sudo -u funkwhale rm front.zip
Upgrading the API
^^^^^^^^^^^^^^^^^
On non-docker, upgrade involves a few more commands. We assume your setup
match what is described in :doc:`/installation/debian`:
.. parsed-literal::
# this assumes you want to upgrade to version "|version|"
export FUNKWHALE_VERSION="|version|"
cd /srv/funkwhale
# download more recent API files
sudo -u funkwhale curl -L -o "api-$FUNKWHALE_VERSION.zip" "https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/$FUNKWHALE_VERSION/download?job=build_api"
sudo -u funkwhale unzip "api-$FUNKWHALE_VERSION.zip" -d extracted
sudo -u funkwhale rm -rf api/ && sudo -u funkwhale mv extracted/api .
sudo -u funkwhale rm -rf extracted
sudo -u funkwhale rm api-$FUNKWHALE_VERSION.zip
# update os dependencies
sudo api/install_os_dependencies.sh install
sudo -u funkwhale -H -E /srv/funkwhale/virtualenv/bin/pip install -r api/requirements.txt
# collect static files
sudo -u funkwhale -H -E /srv/funkwhale/virtualenv/bin/python api/manage.py collectstatic --no-input
# stop the services
sudo systemctl stop funkwhale.target
# apply database migrations
sudo -u funkwhale -H -E /srv/funkwhale/virtualenv/bin/python api/manage.py migrate
# restart the services
sudo systemctl start funkwhale.target
.. note::
If you see a PermissionError when running the ``migrate`` command, try running the following commands by hand, and relaunch the migrations::
sudo -u postgres psql funkwhale -c 'CREATE EXTENSION IF NOT EXISTS "citext";'
sudo -u postgres psql funkwhale -c 'CREATE EXTENSION IF NOT EXISTS "unaccent";'
.. warning::
You may sometimes get the following warning while applying migrations::
"Your models have changes that are not yet reflected in a migration, and so won't be applied."
This is a warning, not an error, and it can be safely ignored.
Never run the ``makemigrations`` command yourself.
Changing Your Instance URL
==========================
.. DANGER::
We highly recommend not to change your instance URL. Members of the community tried to do this and documented their steps here.
This guide might be incomplete or fail for your instance. There is no support for this procedure and likely no way back.
At some point, you may wish to change your instance URL. In order to
do this, you will need to change the following:
- The instance URL in your .env file
- The instance URL in your ``/etc/nginx/sites-enabled/funkwhale.conf`` or ``/etc/apache2/sites-enabled/funkwhale.conf`` depending on your web server setup
- Any references to the old URL in your database
The changes to the database can be achieved with the ``fix_federation_ids`` script in the ``manage.py``
file.
Example output:
.. code-block:: shell
# For Docker setups
docker-compose run --rm api python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
# For non-Docker setups
python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
# Output
Will replace 108 found occurrences of 'https://old-url' by 'https://new-url':
- 20 music.Artist
- 13 music.Album
- 39 music.Track
- 31 music.Upload
- 1 music.Library
- 4 federation.Actor
- 0 federation.Activity
- 0 federation.Follow
- 0 federation.LibraryFollow
Replacing on 20 music.Artist…
Replacing on 13 music.Album…
Replacing on 39 music.Track…
Replacing on 31 music.Upload…
Replacing on 1 music.Library…
Replacing on 4 federation.Actor…
Replacing on 0 federation.Activity…
Replacing on 0 federation.Follow…
Replacing on 0 federation.LibraryFollow…
On Docker Installations
-----------------------
If you have followed the :doc:`Docker installation instructions <../installation/docker>`, you
will need to do the following:
- Edit your .env file to change the ``FUNKWHALE_HOSTNAME`` and ``DJANGO_ALLOWED_HOSTS`` value to your new URL
- Edit your ``/etc/nginx/sites-enabled/funkwhale.conf`` file to change the ``server_name`` values to your new URL
- Run the following command to change all mentions of your old instance URL in the database:
.. code-block:: shell
docker-compose run --rm api python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
- Restart Nginx or Apache to pick up the new changes
.. code-block:: shell
# For Nginx
sudo systemctl restart nginx
# For Apache
sudo systemctl restart apache2
On Non-Docker Installations
---------------------------
If you have followed the :doc:`non-docker setup <../installation/debian>`, you will need to do the following:
- Edit your .env file to change the ``FUNKWHALE_HOSTNAME`` and ``DJANGO_ALLOWED_HOSTS`` value to your new URL
- Edit your ``/etc/nginx/sites-enabled/funkwhale.conf`` file to change the ``server_name`` values to your new URL
- Run the following command to change all mentions of your old instance URL in the database:
.. code-block:: shell
python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
- Restart Nginx or Apache to pick up the new changes
.. code-block:: shell
# For Nginx
sudo systemctl restart nginx
# For Apache
sudo systemctl restart apache2
# Change your instance URL
```{danger}
We recommend you don't change your instance URL. Changing it __will__ cause instability and problems with federation. If you change your URL, the Funkwhale project can't offer support for problems that arise.
```
Your instance URL is your pod's unique identifier in the {term}`fediverse`. If you want to change it, you need to update a lot of information
- The instance URL in your {file}`.env` file.
- The instance URL in your webserver config.
- Any references to the old URL in your database.
To clean the database, the `funkwhale-manage` command line interface contains a `fix_federation_ids` command.
```{warning}
Running `fix_federation_ids` with the `--no-dry-run` flag is irreversible. Make sure you [back up your data](../upgrade/backup.md).
```
## Update your instance URL
1. Change the `FUNKWHALE_HOSTNAME` and `DJANGO_ALLOWED_HOSTS` value in your {file}`.env` file.
2. Change the `server_name` values in your {file}`/etc/nginx/sites-enabled/funkwhale.conf` file.
3. Run the `fix_federation_ids` command to clean up your database.
::::{tab-set}
:::{tab-item} Debian
:sync: debian
```{code-block} sh
venv/bin/funkwhale-manage fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
```
:::
:::{tab-item} Docker
:sync: docker
```{code-block} sh
docker compose run --rm api funkwhale-manage fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
```
:::
::::
Example output:
```{code-block} text
Will replace 108 found occurrences of 'https://old-url' by 'https://new-url':
- 20 music.Artist
- 13 music.Album
- 39 music.Track
- 31 music.Upload
- 1 music.Library
- 4 federation.Actor
- 0 federation.Activity
- 0 federation.Follow
- 0 federation.LibraryFollow
Replacing on 20 music.Artist…
Replacing on 13 music.Album…
Replacing on 39 music.Track…
Replacing on 31 music.Upload…
Replacing on 1 music.Library…
Replacing on 4 federation.Actor…
Replacing on 0 federation.Activity…
Replacing on 0 federation.Follow…
Replacing on 0 federation.LibraryFollow…
```
4. Restart your webserver to pick up the changes.
::::{tab-set}
:::{tab-item} Nginx
:sync: nginx
```{code-block} sh
sudo systemctl restart nginx
```
:::
:::{tab-item} Apache
:sync: apache
```{code-block} sh
sudo systemctl restart apache2
```
:::
::::
# Customize your environment file
Your `.env` (environment) file contains variables you can change to customize your pod. You can change these variables at any time to alter how your pod runs.
You need to restart your Funkwhale services after changing your `.env` file.
::::{tab-set}
:::{tab-item} Debian
:sync: debian
```{code-block} sh
sudo systemctl restart funkwhale.target
```
:::
:::{tab-item} Docker
:sync: docker
```{code-block} sh
docker compose restart
```
:::
::::
## Variables
````{important}
Some environment variables accept a URL as a value. To encode URLs and avoid problems with special characters, use `urllib.parse` on your URL value.
```py
python3 -c 'import urllib.parse; print(urllib.parse.quote_plus("p@ssword"))
```
```{seealso}
The [django-environ documentation](https://github.com/joke2k/django-environ/blob/main/docs/tips.rst#using-unsafe-characters-in-urls).
```
````
### Pod configuration
```{eval-rst}
.. autodata:: config.settings.common.FUNKWHALE_HOSTNAME
:annotation: = mypod.audio
.. autodata:: config.settings.common.FUNKWHALE_PROTOCOL
:annotation: = https
```
### Database and redis configuration
```{eval-rst}
.. autodata:: config.settings.common.DATABASE_URL
:annotation: = postgresql://<user>:<password>@<host>:<port>/<database>
.. autodata:: config.settings.common.DB_CONN_MAX_AGE
.. autodata:: config.settings.common.CACHE_URL
:annotation: = redis://<host>:<port>/<database>
.. autodata:: config.settings.common.CELERY_BROKER_URL
:annotation: = redis://127.0.0.1:6379/0
```
### Accounts and registration
```{eval-rst}
.. autodata:: config.settings.common.ACCOUNT_EMAIL_VERIFICATION_ENFORCE
:annotation: = true
.. autodata:: config.settings.common.USERS_INVITATION_EXPIRATION_DAYS
:annotation: = 7
.. autodata:: config.settings.common.DISABLE_PASSWORD_VALIDATORS
:annotation: = true
.. autodata:: config.settings.common.ACCOUNT_USERNAME_BLACKLIST
:annotation: = test,funkwhale
```
```{py:data} LDAP_ENABLED
---
value: false
---
Whether to enable LDAP authentication.
See {doc}`/administrator/configuration/ldap` for more information.
```
### Media storage and serving configuration
```{eval-rst}
.. autodata:: config.settings.common.MEDIA_URL
:annotation: = https://mypod.audio/media/
.. autodata:: config.settings.common.MEDIA_ROOT
:annotation: = /srv/funkwhale/data/media
.. autodata:: config.settings.common.PROXY_MEDIA
:annotation: = true
.. autodata:: config.settings.common.EXTERNAL_MEDIA_PROXY_ENABLED
:annotation: = false
.. autodata:: config.settings.common.ATTACHMENTS_UNATTACHED_PRUNE_DELAY
:annotation: = true
.. autodata:: config.settings.common.REVERSE_PROXY_TYPE
:annotation: = nginx
.. autodata:: config.settings.common.PROTECT_FILES_PATH
:annotation: = /_protected
.. py:data:: NGINX_MAX_BODY_SIZE
:value: 100M
Controls the maximum size of file that users can upload.
.. note::
You can control how much total storage a user can access with the :term:`Upload Quota` setting.
```
### S3 storage configuration
```{eval-rst}
.. autodata:: config.settings.common.AWS_QUERYSTRING_AUTH
.. autodata:: config.settings.common.AWS_QUERYSTRING_EXPIRE
.. autodata:: config.settings.common.AWS_ACCESS_KEY_ID
.. autodata:: config.settings.common.AWS_SECRET_ACCESS_KEY
.. autodata:: config.settings.common.AWS_STORAGE_BUCKET_NAME
.. autodata:: config.settings.common.AWS_S3_CUSTOM_DOMAIN
.. autodata:: config.settings.common.AWS_S3_ENDPOINT_URL
:annotation: = https://minio.mydomain.com
.. autodata:: config.settings.common.AWS_S3_REGION_NAME
:annotation: = eu-west-2
.. autodata:: config.settings.common.AWS_LOCATION
:annotation: = funkwhale_music
```
### In-place import configuration
```{eval-rst}
.. autodata:: config.settings.common.MUSIC_DIRECTORY_PATH
:annotation: = /srv/funkwhale/data/music
.. autodata:: config.settings.common.MUSIC_DIRECTORY_SERVE_PATH
:annotation: = /srv/funkwhale/data/music
```
### API configuration
```{eval-rst}
.. autodata:: config.settings.common.THROTTLING_ENABLED
.. autodata:: config.settings.common.THROTTLING_RATES
:annotation: = signup=5/d,password-reset=2/d,anonymous-reports=5/d
```
See [Rate limit API endpoints](rate-limiting.md) for a list of available endpoints and their default limits.
```{eval-rst}
.. autodata:: config.settings.common.ADMIN_URL
.. autodata:: config.settings.common.EXTERNAL_REQUESTS_VERIFY_SSL
.. autodata:: config.settings.common.EXTERNAL_REQUESTS_TIMEOUT
```
### Federation configuration
```{eval-rst}
.. autodata:: config.settings.common.FEDERATION_OBJECT_FETCH_DELAY
.. autodata:: config.settings.common.FEDERATION_DUPLICATE_FETCH_DELAY
```
### Metadata configuration
```{eval-rst}
.. autodata:: config.settings.common.TAGS_MAX_BY_OBJ
.. autodata:: config.settings.common.MUSICBRAINZ_HOSTNAME
.. autodata:: config.settings.common.MUSICBRAINZ_CACHE_DURATION
```
### Channels and podcast configuration
```{eval-rst}
.. autodata:: config.settings.common.PODCASTS_RSS_FEED_REFRESH_DELAY
.. autodata:: config.settings.common.PODCASTS_RSS_FEED_MAX_ITEMS
.. autodata:: config.settings.common.PODCASTS_THIRD_PARTY_VISIBILITY
```
### Subsonic configuration
```{eval-rst}
.. autodata:: config.settings.common.SUBSONIC_DEFAULT_TRANSCODING_FORMAT
```
### Email configuration
```{eval-rst}
.. autodata:: config.settings.common.EMAIL_CONFIG
:annotation: = consolemail://
.. autodata:: config.settings.common.DEFAULT_FROM_EMAIL
:annotation: = Funkwhale <noreply@yourdomain>
.. autodata:: config.settings.common.EMAIL_SUBJECT_PREFIX
```
### Plugin configuration
```{eval-rst}
.. autodata:: config.settings.common.FUNKWHALE_PLUGINS_PATH
```
```{py:data} FUNKWHALE_PLUGINS
---
value: "['funkwhale_api.contrib.scrobbler', 'funkwhale_api.contrib.listenbrainz', 'funkwhale_api.contrib.maloja']"
---
List of Funkwhale plugins to load.
```
### Other settings
```{eval-rst}
.. autodata:: config.settings.common.INSTANCE_SUPPORT_MESSAGE_DELAY
.. autodata:: config.settings.common.FUNKWHALE_SUPPORT_MESSAGE_DELAY
.. autodata:: config.settings.common.MIN_DELAY_BETWEEN_DOWNLOADS_COUNT
.. autodata:: config.settings.common.MARKDOWN_EXTENSIONS
.. autodata:: config.settings.common.LINKIFIER_SUPPORTED_TLDS
.. autodata:: config.settings.common.LOGLEVEL
:annotation: = info
```
# Customize the Funkwhale frontend
You can customize the look and behavior of the Funkwhale UI using a JSON configuration file. This file enables you to make very basic changes to the Funkwhale web app.
## Set up your custom configuration
### Create your configuration file
To customize your Funkwhale pod, you need to serve a {file}`settings.json` file at `https://yourinstanceurl/settings.json`. Follow these steps to set up your configuration file:
1. SSH into your Funkwhale server.
2. Navigate to your `/srv/funkwhale` folder
```{code-block} sh
cd /srv/funkwhale
```
3. Create a new `custom` directory for your file.
```{code-block} sh
mkdir custom
```
4. Create a new config file and populate it with placeholder settings.
```{code-block} sh
cat <<EOF > custom/settings.json
{
"additionalStylesheets": [],
"defaultServerUrl": null
}
EOF
```
:::{dropdown} Supported parameters
```{list-table}
:header-rows: 1
* - Parameter
- Data type
- Description
- Example
* - `additionalStylesheets`
- Array<URL>
- A list of URLs (relative or absolute) pointing to stylesheets.
- `["https://test/theme.css"]`
* - `defaultServerUrl`
- URL
- The URL of the API server you want to connect the frontend to. Defaults to the current domain.
- `"https://api.yourdomain.com"`
```
:::
### Configure your reverse proxy
Once you've created your {file}`settings.json` file you need to configure your reverse proxy to serve it.
::::{tab-set}
:::{tab-item} Nginx
:sync: nginx
Add the following snippet to your {file}`/etc/nginx/sites-available/funkwhale.conf` config file:
```{code-block} text
location /settings.json {
alias /srv/funkwhale/custom;
}
```
:::
:::{tab-item} Apache
:sync: apache
Add the following snippet to your webserver configuration:
```{code-block} text
Alias /settings.json /srv/funkwhale/custom/settings.json
```
:::
::::
Reload your webserver. You should be able to see the contents of your configuration file at `https://yourinstanceurl/settings.json`.
## Add a custom theme
You can use a custom stylesheet to theme your Funkwhale pod. To do this:
1. Navigate to your {file}`/srv/funkwhale/custom` directory.
```{code-block} sh
cd /srv/funkwhale/custom
```
2. Copy your CSS file to this directory, or create a new one.
```{code-block} sh
# A basic CSS file. Turns the pod's background red.
cat <<EOF > custom.css
body {
background-color: red;
}
EOF
```
3. Add the location of your CSS file to the `additionalStylesheets` parameter in your {file}`settings.json` file.
```{code-block} sh
nano settings.json
# Add ["/front/custom/custom.css"] to the additionalStylesheets parameter
# The resulting file looks like this:
# {
# "additionalStylesheets": ["/front/custom/custom.css"],
# "defaultServerUrl": null
# }
```
4. Add the whole {file}`custom` dir to your webserver configuration.
::::{tab-set}
:::{tab-item} Nginx
:sync: nginx
Add the following to your {file}`/etc/nginx/sites-available/funkwhale.conf` file:
```{code-block} text
location /custom {
alias /srv/funkwhale/custom;
}
```
:::
:::{tab-item} Apache
:sync: apache
Add the following to your webserver configuration file.
```{code-block} text
Alias /custom /srv/funkwhale/custom
<Directory "/srv/funkwhale/custom">
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
```
:::
::::
5. Restart your webserver.
Refresh your Funkwhale app. The background should now be red.
# Configure your Funkwhale pod
You can customize a lot of settings relating to your Funkwhale pod. These range from server-level settings to user-specific settings. Check out the guides in this section to get started.
```{toctree}
---
caption: Configuration options
maxdepth: 1
---
Environment file <env-file>
Instance settings <instance-settings>
object-storage
Frontend customization <frontend>
optimize
ldap
change-url
mrf
rate-limiting
```
# Instance settings
You can find instance settings on your pod's web interface. These settings control high level pod configuration. You don't need to restart the pod after changing these settings.
To find your instance settings:
::::{tab-set}
:::{tab-item} Desktop
:sync: desktop
1. Log in to your {term}`pod`.
2. Select the wrench icon ({fa}`wrench`) at the top of the sidebar to open the {guilabel}`Administration` menu.
3. Select {guilabel}`Settings`. The {guilabel}`Instance settings` page opens.
:::
:::{tab-item} Mobile
:sync: mobile
1. Log in to your {term}`pod`.
2. Select the wrench icon ({fa}`wrench`) at the top of the page to open the {guilabel}`Administration` menu.
3. Select {guilabel}`Settings`. The {guilabel}`Instance settings` page opens.
:::
::::
## Available settings
### Instance information
```{glossary}
Pod name
The public name of your Funkwhale pod. This is displayed on the "Home" and "About" pages.
Short description
A short description of your pod. Users see this on the pod's "Home" page.
Long description
A longer description of your pod. Users see this on the pod's "About" page. Supports markdown formatting.
Contact email
A contact email address that users and visitors can use to contact the pod administrator.
Rules
A free text field for you to add your pod's rules and code of conduct. This is seen on the pod's "About" page. Supports markdown formatting
Terms of service
A free text field for you to add your pod's terms of service and privacy policy. This is seen on the pod's "About" page. Supports markdown formatting.
Banner image
A large image seen on the pod's "Home" and "About" pages. The image should be at least 600x100px.
Support message
A short message you can display to your pod's users to ask for support or just send a periodic message. Supports markdown.
```
---
### Sign-ups
```{glossary}
Open registration to new users
Enable this setting to allow new users to create an account on your pod.
Enable manual sign-up validation
Enable this setting to require all new registrations to be validated by a moderator.
Sign-up form customization
Use this tool to create a custom sign-up form. New users see this form when creating a new account. Supports markdown
```
---
### Security
````{glossary}
API Requires authentication
Controls whether {term}`unauthenticated users <Anonymous>` can access content on your pod. If __enabled__, users need to have an account on your pod to access content. If __disabled__, users without an account can listen to content stored in public libraries.
```{seealso}
{doc}`../../moderator/content/library`.
```
Default permissions
A list of {term}`permissions` that are added to users by default. If your pod is publicly accessible, you should leave this empty.
Upload quota
The default upload quota for users in MB. You can override this on a per-user basis.
```{seealso}
{doc}`../../moderator/reports/users`
```
````
---
### Music
```{glossary}
Transcoding enabled
Enable this setting to let your server transcode files into a different format if the client requests it. This is useful if a device doesn't support formats like Ogg or FLAC.
Transcoding cache duration
The number of minutes you want to store transcoded files on your server. Funkwhale removes transcoded tracks that haven't been downloaded within this duration to save space.
Only allow MusicBrainz tagged files
If enabled, only files tagged with a [MusicBrainz ID](https://musicbrainz.org/doc/MusicBrainz_Identifier) can be uploaded to the server. Users can use [MusicBrainz Picard](https://picard.musicbrainz.org/) to tag their content with a MBID. Enabling this setting **does not** remove files uploaded before the setting was enabled.
```
### Channels
```{glossary}
Enable channels
Whether user channels can be created and followed on your pod.
Max channels allowed per user
The maximum number of channels each user can create.
```
---
### Playlists
```{glossary}
Max tracks per playlist
The maximum number of tracks a user can add to a playlist.
```
---
### Moderation
```{glossary}
Enable allow-listing
Enable this setting to ensure your pod only communicates with pods you have added to your allow list. When this setting is disabled, your pod will communicate with all other servers not included in your deny list.
Publish your allowed-domains list
Whether to make your list of allowed domains public. Enable this if you want users to check who you are federating with.
Accountless report categories
A list of {term}`categories <Report categories>` that {term}`anonymous` users can submit.
```
---
### Federation
```{glossary}
Federation enabled
Whether to enable federation features on your pod.
Enable public index
Whether to allow other pods and bots to index public content on your pod.
Federation collection page size
The number of items to display in ActivityPub collections.
Music cache duration
The number of minutes you want to store local copies of federated tracks on your server. Funkwhale removes federated tracks that haven't been downloaded within this duration to save space.
Federation actor fetch delay
The number of minutes the server waits before refetching actors on request authentication.
```
---
### Subsonic
```{glossary}
Enabled Subsonic API
Whether to enable the Subsonic API. This controls whether users are able to connect to your pod using Subsonic apps.
```
---
### User Interface
```{glossary}
Custom CSS code
Add CSS rules to control the look and feel of your pod. These rules are added to a `<style>` tag on each page.
Funkwhale Support message
Whether to show a notification to your pod's users to support the Funkwhale project.
```
---
### Statistics
```{glossary}
Enable usage and library stats in nodeinfo endpoint
Whether to share anonymized usage and library statistics in your pod's nodeinfo endpoint.
Private mode in nodeinfo
Enable this setting to indicate you don't want your instance to be tracked by third-party services.
```
# Configure LDAP
{abbr}`LDAP (Lightweight Directory Access Protocol)` is a protocol for providing directory services. It acts as a central authority for user login information. Funkwhale supports LDAP through the [Django LDAP authentication module](https://django-auth-ldap.readthedocs.io/).
```{important}
LDAP users can't change their password in the app.
```
## Dependencies
LDAP support requires extra dependencies. We include these in our requirements files to make it easier to set up. If you aren't using LDAP, you can safely remove these.
:::{dropdown} OS dependencies
- `libldap2-dev`
- `libsasl2-dev`
:::
:::{dropdown} Python dependencies
- `python-ldap`
- `python-django-auth-ldap`
:::
## Environment variables
You can configure LDAP authentication using environment variables in your `.env` file.
### Basic features
```{py:data} LDAP_ENABLED
---
value: True
type: Boolean
noindex: True
---
Set this to `True` to enable LDAP support
```
```{py:data} LDAP_SERVER_URI
---
type: URI
value: ldap://my.host:389
---
The LDAP {abbr}`URI (Uniform Resource Identifier)` of your authentication server.
```
```{py:data} LDAP_BIND_DN
---
type: String
value: cn=admin,dc=domain,dc=com
---
LDAP user {abbr}`DN (Distinguished Name)` to bind on so you can perform searches.
```
```{py:data} LDAP_BIND_PASSWORD
---
type: String
value: bindpassword
---
LDAP user password for bind {abbr}`DN (Distinguished Name)`.
```
```{py:data} LDAP_SEARCH_FILTER
---
type: String
value: (|(cn={0})(mail={0}))
---
The LDAP user filter, using `{0}` as the username placeholder. Uses standard [LDAP search syntax](https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx).
```
```{py:data} LDAP_START_TLS
---
type: Boolean
value: False
---
Set to `True` to enable LDAP StartTLS support.
```
```{py:data} LDAP_ROOT_DN
---
type: String
value: dc=domain,dc=com
---
The LDAP search root {abbr}`DN (Distinguished Name)`. Supports several entries in a comma-delimited list.
```
```{py:data} LDAP_USER_ATTR_MAP
---
type: String
value: first_name:givenName, last_name:sn, username:cn, email:mail
---
A mapping of Django user attributes to LDAP values.
```
```{py:data} AUTH_LDAP_BIND_AS_AUTHENTICATING_USER
---
type: Boolean
value: False
---
Controls whether to use direct binding.
```
### Group features
LDAP provides extra features for working with groups. Group configuration is an advanced feature. Most users don't need to configure these settings.
```{seealso}
[Django's LDAP documentation](https://django-auth-ldap.readthedocs.io/en/latest/groups.html) for groups.
```
```{py:data} LDAP_GROUP_DN
---
type: String
value: ou=groups,dc=domain,dc=com
---
The LDAP group search root {abbr}`DN (Distinguished Name)`. This needs to be set to `True` to enable group features.
```
```{py:data} LDAP_GROUP_FILTER
---
type: String
value: objectClass=groupOfNames
---
The LDAP group filter.
```
```{py:data} LDAP_REQUIRE_GROUP
---
type: String
value: cn=enabled,ou=groups,dc=domain,dc=com
---
The group that users need to be a member of to authenticate.
```
```{py:data} LDAP_DENY_GROUP
---
type: String
value: cn=disabled,ou=groups,dc=domain,dc=com
---
A group whose members can't authenticate.
```
# Message Rewrite Facility (MRF)
Funkwhale includes a feature that mimics [Pleroma’s Message Rewrite Facility (MRF)](https://docs-develop.pleroma.social/backend/configuration/mrf/). The MRF enables instance admins to create custom moderation rules. You can use these rules to complement Funkwhale's [built-in moderation tools](../../moderator/index.md).
## Architecture
The MRF is a pluggable system that processes messages and forwards them to a list of registered policies. Each policy can mutate the message, leave it as is, or discard it.
We implement some of Funkwhale's built-in moderation tools as a MRF policy. For example:
- Allow-list, when checking incoming messages ([code](https://dev.funkwhale.audio/funkwhale/funkwhale/blob/stable/api/funkwhale_api/moderation/mrf_policies.py)).
- Domain and user blocking, when checking incoming messages ([code](https://dev.funkwhale.audio/funkwhale/funkwhale/blob/stable/api/funkwhale_api/federation/mrf_policies.py))
```{note}
Pleroma MRF policies can also affect outgoing messages. This is not currently supported in Funkwhale.
```
## Disclaimer
Writing custom MRF rules can impact the performance and stability of your pod. It can also affect message delivery. Every time your pod receives a message it calls your policy.
The Funkwhale project consider all custom MRF policies to fall under the purview of the AGPL. This means you're required to release the source of your custom MRF policy modules publicly.
## Write your first MRF policy
MRF policies are written as Python 3 functions that take at least one `payload` parameter. This payload is the raw ActivityPub message, received via HTTP, following the HTTP signature check.
In the example below we write a policy that discards all Follow requests from listed domains:
```{code-block} py
import urllib.parse
from funkwhale_api.moderation import mrf
BLOCKED_FOLLOW_DOMAINS = ['domain1.com', 'botdomain.org']
# You need to register the policy to apply it.
# The name can be anything you want. It will appear in the mrf logs
@mrf.inbox.register(name='blocked_follow_domains')
def blocked_follow_domains_policy(payload, **kwargs):
actor_id = payload.get('actor')
domain = urllib.parse.urlparse(actor_id).hostname
if domain not in BLOCKED_FOLLOW_DOMAINS:
# Raising mrf.Skip isn't necessary but it provides
# info in the debug logs. Otherwise, you can return:
raise mrf.Skip("This domain isn't blocked")
activity_type = payload.get('type')
object_type = payload.get('object', {}).get('type')
if object_type == 'Follow' and activity_type == 'Create':
raise mrf.Discard('Follow from blocked domain')
```
You need to store this code in a Funkwhale plugin. To create one, execute the following:
```{code-block} sh
# Plugin names can only contain ASCII letters, numbers and underscores.
export PLUGIN_NAME="myplugin"
# This is the default path where Funkwhale will look for plugins.
# If you want to use another path, update this path and ensure
# your PLUGINS_PATH is also included in your .env file.
export PLUGINS_PATH="/srv/funkwhale/plugins/"
mkdir -p $PLUGINS_PATH/$PLUGIN_NAME
cd $PLUGINS_PATH/$PLUGIN_NAME
touch __init__.py # required to make the plugin a valid Python package
# Create the required apps.py file to register our plugin in Funkwhale.
cat > apps.py <<EOF
from django.apps import AppConfig
class Plugin(AppConfig):
name = "$PLUGIN_NAME"
EOF
```
Once you've created the plugin, put your code in an `mrf_policies.py` file. Place this file inside the plugin directory. Next, enable the plugin in your {file}`.env` file by adding its name to the {attr}`FUNKWHALE_PLUGINS` list. Add this variable if it's not there.
## Test your MRF policy
To make the job of writing and debugging MRF policies easier, we provide a management command.
- List registered MRF policies.
::::{tab-set}
:::{tab-item} Debian
:sync: debian
```{code-block} sh
venv/bin/funkwhale-manage mrf_check --list
```
:::
:::{tab-item} Docker
:sync: docker
```{code-block} sh
docker compose run --rm api funkwhale-manage mrf_check --list
```
:::
::::
- Check how your MRF policy handles a follow.
::::{tab-set}
:::{tab-item} Debian
:sync: debian
```{code-block} sh
export MRF_MESSAGE='{"actor": "https://normal.domain/@alice", "type": "Create", "object": {"type": "Follow"}}'
echo $MRF_MESSAGE | venv/bin/funkwhale-manage mrf_check inbox - -p blocked_follow_domains
```
:::
:::{tab-item} Docker
:sync: docker
```{code-block} sh
export MRF_MESSAGE='{"actor": "https://normal.domain/@alice", "type": "Create", "object": {"type": "Follow"}}'
echo $MRF_MESSAGE | docker compose run --rm api funkwhale-manage mrf_check inbox - -p blocked_follow_domains
```
::::
- Check how your MRF handles a problematic follow.
::::{tab-set}
:::{tab-item} Debian
:sync: debian
```{code-block} sh
export MRF_MESSAGE='{"actor": "https://botdomain.org/@bob", "type": "Create", "object": {"type": "Follow"}}'
echo $MRF_MESSAGE | venv/bin/funkwhale-manage mrf_check inbox - -p blocked_follow_domains
```
:::
:::{tab-item} Docker
:sync: docker
```{code-block} sh
export MRF_MESSAGE='{"actor": "https://botdomain.org/@bob", "type": "Create", "object": {"type": "Follow"}}'
echo $MRF_MESSAGE | docker compose run --rm api funkwhale-manage mrf_check inbox - -p blocked_follow_domains
```
:::
::::
- Check a payload against activity already present in the database. You can find the UUID of an activity by visiting `/api/admin/federation/activity`.
::::{tab-set}
:::{tab-item} Debian
:sync: debian
```{code-block} sh
export ACTIVITY_UUID="06208aea-c687-4e8b-aefd-22f1c3f76039"
echo $MRF_MESSAGE | venv/bin/funkwhale-manage mrf_check inbox $ACTIVITY_UUID -p blocked_follow_domains
```
:::
:::{tab-item} Docker
:sync: docker
```{code-block} sh
export ACTIVITY_UUID="06208aea-c687-4e8b-aefd-22f1c3f76039"
echo $MRF_MESSAGE | docker compose run --rm api funkwhale-manage mrf_check inbox $ACTIVITY_UUID -p blocked_follow_domains
```
:::
::::
There are extra options for testing MRF policies. Check the command help for more options.
::::{tab-set}
:::{tab-item} Debian
:sync: debian
```{code-block} sh
venv/bin/funkwhale-manage mrf_check --help
```
:::
:::{tab-item} Docker
:sync: docker
```{code-block} sh
docker compose run --rm api funkwhale-manage mrf_check --help
```
:::
::::