Rewrite admin documentation
This commit is contained in:
parent
f0857ae5fd
commit
17f1941b0b
248 changed files with 10920 additions and 10168 deletions
|
|
@ -0,0 +1,88 @@
|
|||
# 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 vhost.
|
||||
- Any references to the old URL in your database.
|
||||
|
||||
To clean the database, the {file}`manage.py` script 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_docs/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.
|
||||
|
||||
````{tabbed} Debian
|
||||
|
||||
```{code} bash
|
||||
poetry run python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Docker
|
||||
|
||||
```{code} bash
|
||||
docker-compose run --rm api python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
Example 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…
|
||||
```
|
||||
|
||||
4. Restart your webserver to pick up the changes.
|
||||
|
||||
````{tabbed} Nginx
|
||||
|
||||
```{code} bash
|
||||
sudo systemctl restart nginx
|
||||
|
||||
```
|
||||
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Apache
|
||||
|
||||
|
||||
```{code} bash
|
||||
sudo systemctl restart apache2
|
||||
|
||||
```
|
||||
|
||||
|
||||
````
|
||||
277
docs/administrator_documentation/configuration_docs/env_file.md
Normal file
277
docs/administrator_documentation/configuration_docs/env_file.md
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
# 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.
|
||||
|
||||
````{tabbed} Debian
|
||||
|
||||
```{code} bash
|
||||
sudo systemctl restart funkwhale.target
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Docker
|
||||
|
||||
```{code} bash
|
||||
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_documentation/configuration_docs/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
|
||||
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
```
|
||||
|
||||
```{dropdown} Standard endpoints
|
||||
|
||||
| Endpoint name | Description | Default rate (per user) |
|
||||
|---------------------------|----------------------------------------------------------|-------------------------|
|
||||
| `anonymous-wildcard` | Anonymous requests not covered by other limits | 1000 per hour |
|
||||
| `authenticated-wildcard` | Authenticated requests not covered by other limits | 2000 per hour |
|
||||
| `authenticated-create` | Authenticated POST requests | 1000 per hour |
|
||||
| `anonymous-create` | Anonymous POST requests | 1000 per day |
|
||||
| `authenticated-list` | Authenticated GET requests | 10000 per hour |
|
||||
| `anonymous-list` | Anonymous GET requests | 10000 per day |
|
||||
| `authenticated-retrieve` | Authenticated GET requests on resource details | 10000 per hour |
|
||||
| `anonymous-retrieve` | Anonymous GET requests on resource details | 10000 per day |
|
||||
| `authenticated-destroy` | Authenticated DELETE requests on resource details | 500 per hour |
|
||||
| `anonymous-destroy` | Anonymous DELETE requests on resource details | 1000 per day |
|
||||
| `authenticated-update` | Authenticated PATCH and PUT requests on resource details | 1000 per hour |
|
||||
| `anonymous-update` | Anonymous PATCH and PUT requests on resource details | 1000 per day |
|
||||
| `subsonic` | All Subsonic API requests | 2000 per hour |
|
||||
|
||||
```
|
||||
|
||||
```{dropdown} User action endpoints
|
||||
|
||||
| Endpoint name | Description | Default rate (per user) |
|
||||
|---------------------------|----------------------------------------------------------|-------------------------|
|
||||
| `login` | User login | 30 per hour |
|
||||
| `signup` | User signup | 10 per day |
|
||||
| `verify-email` | Email address confirmation | 20 per hour |
|
||||
| `password-change` | Password change (when authenticated) | 20 per hour |
|
||||
| `password-reset` | Password reset request | 20 per hour |
|
||||
| `password-reset-confirm` | Password reset confirmation | 20 per hour |
|
||||
| `fetch` | Fetch remote objects | 200 per day |
|
||||
|
||||
```
|
||||
|
||||
```{dropdown} Dangerous endpoints
|
||||
|
||||
| Endpoint name | Description | Default rate (per user) |
|
||||
|---------------------------|----------------------------------------------------------|-------------------------|
|
||||
| `authenticated-reports` | Authenticated report submissions | 100 per day |
|
||||
| `anonymous-reports` | Anonymous report submissions | 10 per day |
|
||||
| `authenticated-oauth-app` | Authenticated OAuth app creation | 10 per hour |
|
||||
| `anonymous-oauth-app` | Anonymous OAuth app creation | 10 per day |
|
||||
| `oauth-authorize` | OAuth app authorization | 100 per hour |
|
||||
| `oauth-token` | OAuth token creation | 100 per hour |
|
||||
| `oauth-revoke-token` | OAuth token deletion | 100 per hour |
|
||||
|
||||
```
|
||||
|
||||
```{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
|
||||
|
||||
```
|
||||
137
docs/administrator_documentation/configuration_docs/frontend.md
Normal file
137
docs/administrator_documentation/configuration_docs/frontend.md
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
# 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} bash
|
||||
cd /srv/funkwhale
|
||||
```
|
||||
|
||||
3. Create a new `custom` directory for your file.
|
||||
|
||||
```{code} bash
|
||||
mkdir custom
|
||||
```
|
||||
|
||||
4. Create a new config file and populate it with placeholder settings.
|
||||
|
||||
```{code} bash
|
||||
cat <<EOF > custom/settings.json
|
||||
{
|
||||
"additionalStylesheets": [],
|
||||
"defaultServerUrl": null
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
```{dropdown} Supported parameters
|
||||
|
||||
| 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.
|
||||
|
||||
````{tabbed} Nginx
|
||||
|
||||
Add the following snippet to your {file}`/etc/nginx/sites-available/funkwhale.conf` config file:
|
||||
|
||||
```
|
||||
location /settings.json {
|
||||
alias /srv/funkwhale/custom;
|
||||
}
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Apache
|
||||
|
||||
Add the following snippet to your vhost configuration:
|
||||
|
||||
```
|
||||
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} bash
|
||||
cd /srv/funkwhale/custom
|
||||
```
|
||||
|
||||
2. Copy your CSS file to this directory, or create a new one.
|
||||
|
||||
```{code} bash
|
||||
# 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} bash
|
||||
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 vhost configuration.
|
||||
|
||||
````{tabbed} Nginx
|
||||
|
||||
Add the following to your {file}`/etc/nginx/sites-available/funkwhale.conf` file:
|
||||
|
||||
```
|
||||
location /custom {
|
||||
alias /srv/funkwhale/custom;
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
````{tabbed} Apache
|
||||
|
||||
Add the following to your vhost file.
|
||||
|
||||
```
|
||||
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.
|
||||
20
docs/administrator_documentation/configuration_docs/index.md
Normal file
20
docs/administrator_documentation/configuration_docs/index.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# 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
|
||||
|
||||
```
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
# 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:
|
||||
|
||||
```{tabbed} 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.
|
||||
```
|
||||
|
||||
```{tabbed} 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_documentation/content/library_visibility`.
|
||||
```
|
||||
|
||||
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_documentation/reports/handle_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.
|
||||
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
```
|
||||
156
docs/administrator_documentation/configuration_docs/ldap.md
Normal file
156
docs/administrator_documentation/configuration_docs/ldap.md
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
# 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
|
||||
---
|
||||
|
||||
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 (Distinguised 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 (Distinguised 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 (Distinguised 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 (Distinguised 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.
|
||||
```
|
||||
182
docs/administrator_documentation/configuration_docs/mrf.md
Normal file
182
docs/administrator_documentation/configuration_docs/mrf.md
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
# 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_documentation/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} 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} bash
|
||||
|
||||
# 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.
|
||||
|
||||
````{tabbed} Debian
|
||||
|
||||
```{code} bash
|
||||
poetry run python manage.py mrf_check --list
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Docker
|
||||
|
||||
```{code} bash
|
||||
docker-compose run --rm api python manage.py mrf_check --list
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
- Check how your MRF policy handles a follow.
|
||||
|
||||
````{tabbed} Debian
|
||||
|
||||
```{code} bash
|
||||
export MRF_MESSAGE='{"actor": "https://normal.domain/@alice", "type": "Create", "object": {"type": "Follow"}}'
|
||||
echo $MRF_MESSAGE | poetry run python manage.py mrf_check inbox - -p blocked_follow_domains
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Docker
|
||||
|
||||
```{code} bash
|
||||
export MRF_MESSAGE='{"actor": "https://normal.domain/@alice", "type": "Create", "object": {"type": "Follow"}}'
|
||||
echo $MRF_MESSAGE | docker-compose run --rm api python manage.py mrf_check inbox - -p blocked_follow_domains
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
- Check how your MRF handles a problematic follow.
|
||||
|
||||
````{tabbed} Debian
|
||||
|
||||
```{code} bash
|
||||
export MRF_MESSAGE='{"actor": "https://botdomain.org/@bob", "type": "Create", "object": {"type": "Follow"}}'
|
||||
echo $MRF_MESSAGE | poetry run python manage.py mrf_check inbox - -p blocked_follow_domains
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Docker
|
||||
|
||||
```{code} bash
|
||||
export MRF_MESSAGE='{"actor": "https://botdomain.org/@bob", "type": "Create", "object": {"type": "Follow"}}'
|
||||
echo $MRF_MESSAGE | docker-compose run --rm api python manage.py 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`.
|
||||
|
||||
````{tabbed} Debian
|
||||
|
||||
```{code} bash
|
||||
export ACTIVITY_UUID="06208aea-c687-4e8b-aefd-22f1c3f76039"
|
||||
echo $MRF_MESSAGE | poetry run python manage.py mrf_check inbox $ACTIVITY_UUID -p blocked_follow_domains
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Docker
|
||||
|
||||
```{code} bash
|
||||
|
||||
export ACTIVITY_UUID="06208aea-c687-4e8b-aefd-22f1c3f76039"
|
||||
|
||||
echo $MRF_MESSAGE | docker-compose run --rm api python manage.py mrf_check inbox $ACTIVITY_UUID -p blocked_follow_domains
|
||||
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
There are extra options for testing MRF policies. Check the command help for more options.
|
||||
|
||||
````{tabbed} Debian
|
||||
|
||||
```{code} bash
|
||||
poetry run python manage.py mrf_check --help
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Docker
|
||||
|
||||
```{code}
|
||||
docker-compose run --rm api python manage.py mrf_check --help
|
||||
```
|
||||
|
||||
````
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
# Store media in an object store
|
||||
|
||||
By default, Funkwhale stores all media data in the `/srv/funkwhale/data/media` directory. If you prefer to use an S3-compatible object store, follow the instructions in this guide.
|
||||
|
||||
```{contents}
|
||||
:local:
|
||||
:depth: 1
|
||||
```
|
||||
|
||||
## Secure your object store
|
||||
|
||||
Before you begin, you need to secure your object store. Many S3-compatible stores list contents in the root by default. This exposes the URLs of your audio files and means that users can bypass authentication.
|
||||
|
||||
To prevent listing content, add the following policy to your S3-compatible object store.
|
||||
|
||||
```{code} json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"s3:GetObject"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
"Resource": [
|
||||
"arn:aws:s3:::<yourbucketname>/*"
|
||||
],
|
||||
"Sid": "Public"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
If you're using `awscli`, you can store this policy in a `/tmp/policy` file and apply it using the following command:
|
||||
|
||||
```{code} bash
|
||||
aws s3api put-bucket-policy --bucket <yourbucketname> --policy file:///tmp/policy
|
||||
```
|
||||
|
||||
## Update your environment file
|
||||
|
||||
To set up S3-compatible storage, fill out the relevant details in the `.env` file. If you want to serve audio files from the bucket, set `PROXY_MEDIA` to `false`.
|
||||
|
||||
````{dropdown} Environment variables
|
||||
|
||||
```{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
|
||||
.. autodata:: config.settings.common.PROXY_MEDIA
|
||||
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
## Set up your reverse proxy
|
||||
|
||||
```{note}
|
||||
Serving files from object storage is not currently supported on Apache deployments.
|
||||
```
|
||||
|
||||
Serving files from an object store requires some changes to the reverse proxy.
|
||||
|
||||
1. Open your Nginx configuration file in an editor.
|
||||
|
||||
````{tabbed} Debian
|
||||
|
||||
```{code} bash
|
||||
sudo nano /etc/nginx/sites-available/funkwhale.template
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Docker
|
||||
|
||||
```{code} bash
|
||||
nano /srv/funkwhale/nginx/funkwhale.template
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
2. Comment out the `location /_protected/media/` block by adding a `#` to the start of each line.
|
||||
|
||||
```{code}
|
||||
# location /_protected/media/ {
|
||||
# internal;
|
||||
# alias ${MEDIA_ROOT};
|
||||
# }
|
||||
```
|
||||
|
||||
3. Uncomment the `location ~ /_protected/media/(.+)` block by removing the `#` from the start of each line.
|
||||
|
||||
```{code}
|
||||
location ~ /_protected/media/(.+) {
|
||||
internal;
|
||||
proxy_set_header Authorization "";
|
||||
proxy_pass $1;
|
||||
}
|
||||
```
|
||||
|
||||
4. Add your S3 store URL to the `img-src` and `media-src` headers.
|
||||
|
||||
```{code}
|
||||
add_header Content-Security-Policy "...img-src 'self' https://<your-s3-URL> data:;...media-src https://<your-s3-URL> 'self' data:";
|
||||
```
|
||||
|
||||
5. Test your Nginx configuration.
|
||||
|
||||
```{code} bash
|
||||
sudo nginx -t
|
||||
```
|
||||
|
||||
6. Restart Funkwhale and Nginx to pick up the changes.
|
||||
|
||||
````{tabbed} Debian
|
||||
|
||||
```{code} bash
|
||||
sudo systemctl restart funkwhale.target
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Docker
|
||||
|
||||
```{code} bash
|
||||
docker-compose restart
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
That's it! Files are now uploaded to and stored from your S3 bucket.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
````{dropdown} No Resolver Found
|
||||
|
||||
You may see the following error when streaming music from your S3-compatible store:
|
||||
|
||||
```{code}
|
||||
[error] 2832#2832: *1 no resolver defined to resolve [address] client: [IP], server: [servername], request: "GET API request", host: "[your_domain]", referrer: "[your_domain/library]"
|
||||
```
|
||||
|
||||
This happens when the Nginx config is unable to use your server’s DNS resolver. We're still looking into this issue. You can work around this by adding a resolver to the `location ~/_protected/media/(.+)` block.
|
||||
|
||||
```{code}
|
||||
location ~ /_protected/media/(.+) {
|
||||
resolver 1.1.1.1;
|
||||
internal;
|
||||
proxy_set_header Authorization "";
|
||||
proxy_pass $1;
|
||||
}
|
||||
```
|
||||
|
||||
````
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
# Optimize memory usage
|
||||
|
||||
Funkwhale has a reasonable memory footprint. If you're running Funkwhale on a limited device, you can use these tweaks to reduce the footprint.
|
||||
|
||||
## Reduce workers concurrency
|
||||
|
||||
Funkwhale uses Celery to handle asynchronous tasks. By default, Celery spawns a worker per CPU core. This can lead to higher memory usage.
|
||||
|
||||
You can set the number of workers using the `CELERYD_CONCURRENCY` variable in your `.env` file. For example, a value of `CELERYD_CONCURRENCY=1` spawns a single worker.
|
||||
|
||||
```{note}
|
||||
Reducing the number of celery workers slows down the handling of asynchronous tasks. On larger instances, this can cause performance problems.
|
||||
```
|
||||
|
||||
## Switch to solo pool execution
|
||||
|
||||
Celery uses a `prefork` pool by default. This enables the server to process many tasks at the same time. You can switch to a `solo` pool which handles tasks one at a time. This reduces memory overhead but removes the ability to process tasks concurrently.
|
||||
|
||||
````{tabbed} Debian
|
||||
|
||||
1. Open your `funkwhale-worker` unit file in an editor.
|
||||
|
||||
```{code} bash
|
||||
sudo nano /etc/systemd/system/funkwhale-worker.service
|
||||
```
|
||||
|
||||
2. Add the `--pool=solo` flag to the `ExecStart` line of your unit file.
|
||||
|
||||
```{code} text
|
||||
ExecStart=/srv/funkwhale/.local/bin/poetry run celery -A --pool=solo funkwhale_api.taskapp worker -l INFO --concurrency=${CELERYD_CONCURRENCY}
|
||||
```
|
||||
|
||||
3. Restart the Celery service.
|
||||
|
||||
```{code} bash
|
||||
sudo systemctl restart funkwhale-worker.service
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tabbed} Docker
|
||||
|
||||
1. Add the `--pool=solo` flag to the `celerybeat` command in `docker-compose.yml`.
|
||||
|
||||
```{code} yaml
|
||||
celerybeat:
|
||||
…
|
||||
command: celery -A --pool=solo funkwhale_api.taskapp beat --pidfile= -l INFO
|
||||
```
|
||||
|
||||
2. Restart Celery.
|
||||
|
||||
```{code} bash
|
||||
docker-compose restart celerybeat
|
||||
```
|
||||
|
||||
````
|
||||
Loading…
Add table
Add a link
Reference in a new issue