Merge branch 'config-docs' into 'develop'
Documentation for .env variables See merge request funkwhale/funkwhale!1095
This commit is contained in:
		
						commit
						e812de28c8
					
				| 
						 | 
					@ -71,7 +71,7 @@ review_docs:
 | 
				
			||||||
    - cd docs
 | 
					    - cd docs
 | 
				
			||||||
    - apt-get update
 | 
					    - apt-get update
 | 
				
			||||||
    - apt-get install -y graphviz
 | 
					    - apt-get install -y graphviz
 | 
				
			||||||
    - pip install sphinx sphinx_rtd_theme
 | 
					    - pip install sphinx sphinx_rtd_theme django-environ django
 | 
				
			||||||
  script:
 | 
					  script:
 | 
				
			||||||
    - ./build_docs.sh
 | 
					    - ./build_docs.sh
 | 
				
			||||||
  cache:
 | 
					  cache:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,4 @@
 | 
				
			||||||
# -*- coding: utf-8 -*-
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
Django settings for funkwhale_api project.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
For more information on this file, see
 | 
					 | 
				
			||||||
https://docs.djangoproject.com/en/dev/topics/settings/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
For the full list of settings and their values, see
 | 
					 | 
				
			||||||
https://docs.djangoproject.com/en/dev/ref/settings/
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
from __future__ import absolute_import, unicode_literals
 | 
					from __future__ import absolute_import, unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import datetime
 | 
					import datetime
 | 
				
			||||||
| 
						 | 
					@ -29,6 +20,9 @@ APPS_DIR = ROOT_DIR.path("funkwhale_api")
 | 
				
			||||||
env = environ.Env()
 | 
					env = environ.Env()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOGLEVEL = env("LOGLEVEL", default="info").upper()
 | 
					LOGLEVEL = env("LOGLEVEL", default="info").upper()
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Default logging level for the Funkwhale processes"""  # pylint: disable=W0105
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOGGING_CONFIG = None
 | 
					LOGGING_CONFIG = None
 | 
				
			||||||
logging.config.dictConfig(
 | 
					logging.config.dictConfig(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -57,7 +51,10 @@ logging.config.dictConfig(
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
env_file = env("ENV_FILE", default=None)
 | 
					ENV_FILE = env_file = env("ENV_FILE", default=None)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Path to a .env file to load
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
if env_file:
 | 
					if env_file:
 | 
				
			||||||
    logger.info("Loading specified env file at %s", env_file)
 | 
					    logger.info("Loading specified env file at %s", env_file)
 | 
				
			||||||
    # we have an explicitely specified env file
 | 
					    # we have an explicitely specified env file
 | 
				
			||||||
| 
						 | 
					@ -85,6 +82,9 @@ else:
 | 
				
			||||||
FUNKWHALE_PLUGINS_PATH = env(
 | 
					FUNKWHALE_PLUGINS_PATH = env(
 | 
				
			||||||
    "FUNKWHALE_PLUGINS_PATH", default="/srv/funkwhale/plugins/"
 | 
					    "FUNKWHALE_PLUGINS_PATH", default="/srv/funkwhale/plugins/"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Path to a directory containing Funkwhale plugins. These will be imported at runtime.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
sys.path.append(FUNKWHALE_PLUGINS_PATH)
 | 
					sys.path.append(FUNKWHALE_PLUGINS_PATH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FUNKWHALE_HOSTNAME = None
 | 
					FUNKWHALE_HOSTNAME = None
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,14 @@ if FUNKWHALE_HOSTNAME_PREFIX and FUNKWHALE_HOSTNAME_SUFFIX:
 | 
				
			||||||
else:
 | 
					else:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        FUNKWHALE_HOSTNAME = env("FUNKWHALE_HOSTNAME")
 | 
					        FUNKWHALE_HOSTNAME = env("FUNKWHALE_HOSTNAME")
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Hostname of your Funkwhale pod, e.g ``mypod.audio``
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        FUNKWHALE_PROTOCOL = env("FUNKWHALE_PROTOCOL", default="https")
 | 
					        FUNKWHALE_PROTOCOL = env("FUNKWHALE_PROTOCOL", default="https")
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Protocol end users will use to access your pod, either ``http`` or ``https``.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
    except Exception:
 | 
					    except Exception:
 | 
				
			||||||
        FUNKWHALE_URL = env("FUNKWHALE_URL")
 | 
					        FUNKWHALE_URL = env("FUNKWHALE_URL")
 | 
				
			||||||
        _parsed = urlsplit(FUNKWHALE_URL)
 | 
					        _parsed = urlsplit(FUNKWHALE_URL)
 | 
				
			||||||
| 
						 | 
					@ -112,6 +119,16 @@ FUNKWHALE_URL = "{}://{}".format(FUNKWHALE_PROTOCOL, FUNKWHALE_HOSTNAME)
 | 
				
			||||||
FUNKWHALE_SPA_HTML_ROOT = env(
 | 
					FUNKWHALE_SPA_HTML_ROOT = env(
 | 
				
			||||||
    "FUNKWHALE_SPA_HTML_ROOT", default=FUNKWHALE_URL + "/front/"
 | 
					    "FUNKWHALE_SPA_HTML_ROOT", default=FUNKWHALE_URL + "/front/"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					URL or path to the Web Application files. Funkwhale needs access to it so that
 | 
				
			||||||
 | 
					it can inject <meta> tags relevant to the given page (e.g page title, cover, etc.).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If a URL is specified, the index.html file will be fetched through HTTP. If a path is provided,
 | 
				
			||||||
 | 
					it will be accessed from disk.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use something like ``/srv/funkwhale/front/dist/`` if the web processes shows request errors related to this.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FUNKWHALE_SPA_HTML_CACHE_DURATION = env.int(
 | 
					FUNKWHALE_SPA_HTML_CACHE_DURATION = env.int(
 | 
				
			||||||
    "FUNKWHALE_SPA_HTML_CACHE_DURATION", default=60 * 15
 | 
					    "FUNKWHALE_SPA_HTML_CACHE_DURATION", default=60 * 15
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -148,7 +165,16 @@ FEDERATION_SERVICE_ACTOR_USERNAME = env(
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
# How many pages to fetch when crawling outboxes and third-party collections
 | 
					# How many pages to fetch when crawling outboxes and third-party collections
 | 
				
			||||||
FEDERATION_COLLECTION_MAX_PAGES = env.int("FEDERATION_COLLECTION_MAX_PAGES", default=5)
 | 
					FEDERATION_COLLECTION_MAX_PAGES = env.int("FEDERATION_COLLECTION_MAX_PAGES", default=5)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Number of existing pages of content to fetch when discovering/refreshing an actor or channel.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More pages means more content will be loaded, but will require more resources.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=[]) + [FUNKWHALE_HOSTNAME]
 | 
					ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=[]) + [FUNKWHALE_HOSTNAME]
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					List of allowed hostnames for which the Funkwhale server will answer.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# APP CONFIGURATION
 | 
					# APP CONFIGURATION
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					@ -223,12 +249,18 @@ LOCAL_APPS = (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PLUGINS = [p for p in env.list("FUNKWHALE_PLUGINS", default=[]) if p]
 | 
					PLUGINS = [p for p in env.list("FUNKWHALE_PLUGINS", default=[]) if p]
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					List of Funkwhale plugins to load.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
if PLUGINS:
 | 
					if PLUGINS:
 | 
				
			||||||
    logger.info("Running with the following plugins enabled: %s", ", ".join(PLUGINS))
 | 
					    logger.info("Running with the following plugins enabled: %s", ", ".join(PLUGINS))
 | 
				
			||||||
else:
 | 
					else:
 | 
				
			||||||
    logger.info("Running with no plugins")
 | 
					    logger.info("Running with no plugins")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ADDITIONAL_APPS = env.list("ADDITIONAL_APPS", default=[])
 | 
					ADDITIONAL_APPS = env.list("ADDITIONAL_APPS", default=[])
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					List of Django apps to load in addition to Funkwhale plugins and apps.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
INSTALLED_APPS = (
 | 
					INSTALLED_APPS = (
 | 
				
			||||||
    DJANGO_APPS
 | 
					    DJANGO_APPS
 | 
				
			||||||
    + THIRD_PARTY_APPS
 | 
					    + THIRD_PARTY_APPS
 | 
				
			||||||
| 
						 | 
					@ -257,8 +289,11 @@ MIDDLEWARE = tuple(ADDITIONAL_MIDDLEWARES_BEFORE) + (
 | 
				
			||||||
# DEBUG
 | 
					# DEBUG
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug
 | 
					# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug
 | 
				
			||||||
DEBUG = env.bool("DJANGO_DEBUG", False)
 | 
					DJANGO_DEBUG = DEBUG = env.bool("DJANGO_DEBUG", False)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Whether to enable debugging info and pages. Never enable this on a production server,
 | 
				
			||||||
 | 
					as it can leak very sensitive information.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# FIXTURE CONFIGURATION
 | 
					# FIXTURE CONFIGURATION
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS
 | 
					# See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS
 | 
				
			||||||
| 
						 | 
					@ -272,25 +307,70 @@ FIXTURE_DIRS = (str(APPS_DIR.path("fixtures")),)
 | 
				
			||||||
DEFAULT_FROM_EMAIL = env(
 | 
					DEFAULT_FROM_EMAIL = env(
 | 
				
			||||||
    "DEFAULT_FROM_EMAIL", default="Funkwhale <noreply@{}>".format(FUNKWHALE_HOSTNAME)
 | 
					    "DEFAULT_FROM_EMAIL", default="Funkwhale <noreply@{}>".format(FUNKWHALE_HOSTNAME)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Name and email address used to send system emails.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Default: ``Funkwhale <noreply@yourdomain>``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. note::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Both the forms ``Funkwhale <noreply@yourdomain>`` and
 | 
				
			||||||
 | 
					    ``noreply@yourdomain`` work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
EMAIL_SUBJECT_PREFIX = env("EMAIL_SUBJECT_PREFIX", default="[Funkwhale] ")
 | 
					EMAIL_SUBJECT_PREFIX = env("EMAIL_SUBJECT_PREFIX", default="[Funkwhale] ")
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Subject prefix for system emails.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
SERVER_EMAIL = env("SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
 | 
					SERVER_EMAIL = env("SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EMAIL_CONFIG = env.email_url("EMAIL_CONFIG", default="consolemail://")
 | 
					EMAIL_CONFIG = env.email_url("EMAIL_CONFIG", default="consolemail://")
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					SMTP configuration for sending emails. Possible values:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- ``EMAIL_CONFIG=consolemail://``: output emails to console (the default)
 | 
				
			||||||
 | 
					- ``EMAIL_CONFIG=dummymail://``: disable email sending completely
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					On a production instance, you'll usually want to use an external SMTP server:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- ``EMAIL_CONFIG=smtp://user@:password@youremail.host:25``
 | 
				
			||||||
 | 
					- ``EMAIL_CONFIG=smtp+ssl://user@:password@youremail.host:465``
 | 
				
			||||||
 | 
					- ``EMAIL_CONFIG=smtp+tls://user@:password@youremail.host:587``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. note::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    If ``user`` or ``password`` contain special characters (eg.
 | 
				
			||||||
 | 
					    ``noreply@youremail.host`` as ``user``), be sure to urlencode them, using
 | 
				
			||||||
 | 
					    for example the command:
 | 
				
			||||||
 | 
					    ``python3 -c 'import urllib.parse; print(urllib.parse.quote_plus("noreply@youremail.host"))'``
 | 
				
			||||||
 | 
					    (returns ``noreply%40youremail.host``)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
vars().update(EMAIL_CONFIG)
 | 
					vars().update(EMAIL_CONFIG)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# DATABASE CONFIGURATION
 | 
					# DATABASE CONFIGURATION
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
 | 
					# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
 | 
				
			||||||
 | 
					DATABASE_URL = env.db("DATABASE_URL")
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					URL to connect to the PostgreSQL database. Examples:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- ``postgresql://funkwhale@:5432/funkwhale``
 | 
				
			||||||
 | 
					- ``postgresql://<user>:<password>@<host>:<port>/<database>``
 | 
				
			||||||
 | 
					- ``postgresql://funkwhale:passw0rd@localhost:5432/funkwhale_database``
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
DATABASES = {
 | 
					DATABASES = {
 | 
				
			||||||
    # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
 | 
					    # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
 | 
				
			||||||
    "default": env.db("DATABASE_URL")
 | 
					    "default": DATABASE_URL
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
DATABASES["default"]["ATOMIC_REQUESTS"] = True
 | 
					DATABASES["default"]["ATOMIC_REQUESTS"] = True
 | 
				
			||||||
DATABASES["default"]["CONN_MAX_AGE"] = env("DB_CONN_MAX_AGE", default=60 * 5)
 | 
					DB_CONN_MAX_AGE = DATABASES["default"]["CONN_MAX_AGE"] = env(
 | 
				
			||||||
 | 
					    "DB_CONN_MAX_AGE", default=60 * 5
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Max time, in seconds, before database connections are closed.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
MIGRATION_MODULES = {
 | 
					MIGRATION_MODULES = {
 | 
				
			||||||
    # see https://github.com/jazzband/django-oauth-toolkit/issues/634
 | 
					    # see https://github.com/jazzband/django-oauth-toolkit/issues/634
 | 
				
			||||||
    # swappable models are badly designed in oauth2_provider
 | 
					    # swappable models are badly designed in oauth2_provider
 | 
				
			||||||
| 
						 | 
					@ -299,13 +379,6 @@ MIGRATION_MODULES = {
 | 
				
			||||||
    "sites": "funkwhale_api.contrib.sites.migrations",
 | 
					    "sites": "funkwhale_api.contrib.sites.migrations",
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# DATABASES = {
 | 
					 | 
				
			||||||
#     'default': {
 | 
					 | 
				
			||||||
#         'ENGINE': 'django.db.backends.sqlite3',
 | 
					 | 
				
			||||||
#         'NAME': 'db.sqlite3',
 | 
					 | 
				
			||||||
#     }
 | 
					 | 
				
			||||||
# }
 | 
					 | 
				
			||||||
# GENERAL CONFIGURATION
 | 
					# GENERAL CONFIGURATION
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
# Local time zone for this installation. Choices can be found here:
 | 
					# Local time zone for this installation. Choices can be found here:
 | 
				
			||||||
| 
						 | 
					@ -370,31 +443,79 @@ CRISPY_TEMPLATE_PACK = "bootstrap3"
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
 | 
					# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
 | 
				
			||||||
STATIC_ROOT = env("STATIC_ROOT", default=str(ROOT_DIR("staticfiles")))
 | 
					STATIC_ROOT = env("STATIC_ROOT", default=str(ROOT_DIR("staticfiles")))
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Path were static files should be collected.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
 | 
					# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
 | 
				
			||||||
STATIC_URL = env("STATIC_URL", default=FUNKWHALE_URL + "/staticfiles/")
 | 
					STATIC_URL = env("STATIC_URL", default=FUNKWHALE_URL + "/staticfiles/")
 | 
				
			||||||
DEFAULT_FILE_STORAGE = "funkwhale_api.common.storage.ASCIIFileSystemStorage"
 | 
					DEFAULT_FILE_STORAGE = "funkwhale_api.common.storage.ASCIIFileSystemStorage"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PROXY_MEDIA = env.bool("PROXY_MEDIA", default=True)
 | 
					PROXY_MEDIA = env.bool("PROXY_MEDIA", default=True)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Wether to proxy audio files through your reverse proxy. It's recommended to keep this on,
 | 
				
			||||||
 | 
					as a way to enforce access control, however, if you're using S3 storage with :attr:`AWS_QUERYSTRING_AUTH`,
 | 
				
			||||||
 | 
					it's safe to disable it.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
AWS_DEFAULT_ACL = None
 | 
					AWS_DEFAULT_ACL = None
 | 
				
			||||||
AWS_QUERYSTRING_AUTH = env.bool("AWS_QUERYSTRING_AUTH", default=not PROXY_MEDIA)
 | 
					AWS_QUERYSTRING_AUTH = env.bool("AWS_QUERYSTRING_AUTH", default=not PROXY_MEDIA)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Whether to include signatures in S3 urls, as a way to enforce access-control.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Defaults to the inverse of :attr:`PROXY_MEDIA`.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AWS_S3_MAX_MEMORY_SIZE = env.int(
 | 
					AWS_S3_MAX_MEMORY_SIZE = env.int(
 | 
				
			||||||
    "AWS_S3_MAX_MEMORY_SIZE", default=1000 * 1000 * 1000 * 20
 | 
					    "AWS_S3_MAX_MEMORY_SIZE", default=1000 * 1000 * 1000 * 20
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AWS_QUERYSTRING_EXPIRE = env.int("AWS_QUERYSTRING_EXPIRE", default=3600)
 | 
					AWS_QUERYSTRING_EXPIRE = env.int("AWS_QUERYSTRING_EXPIRE", default=3600)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Expiration delay, in seconds, of signatures generated when :attr:`AWS_QUERYSTRING_AUTH` is enabled.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AWS_ACCESS_KEY_ID = env("AWS_ACCESS_KEY_ID", default=None)
 | 
					AWS_ACCESS_KEY_ID = env("AWS_ACCESS_KEY_ID", default=None)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Access-key ID for your S3 storage.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if AWS_ACCESS_KEY_ID:
 | 
					if AWS_ACCESS_KEY_ID:
 | 
				
			||||||
    AWS_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID
 | 
					    AWS_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID
 | 
				
			||||||
    AWS_SECRET_ACCESS_KEY = env("AWS_SECRET_ACCESS_KEY")
 | 
					    AWS_SECRET_ACCESS_KEY = env("AWS_SECRET_ACCESS_KEY")
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Secret access key for your S3 storage.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    AWS_STORAGE_BUCKET_NAME = env("AWS_STORAGE_BUCKET_NAME")
 | 
					    AWS_STORAGE_BUCKET_NAME = env("AWS_STORAGE_BUCKET_NAME")
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Bucket name of your S3 storage.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    AWS_S3_CUSTOM_DOMAIN = env("AWS_S3_CUSTOM_DOMAIN", default=None)
 | 
					    AWS_S3_CUSTOM_DOMAIN = env("AWS_S3_CUSTOM_DOMAIN", default=None)
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Custom domain to use for your S3 storage.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    AWS_S3_ENDPOINT_URL = env("AWS_S3_ENDPOINT_URL", default=None)
 | 
					    AWS_S3_ENDPOINT_URL = env("AWS_S3_ENDPOINT_URL", default=None)
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    If you use a S3-compatible storage such as minio, set the following variable to
 | 
				
			||||||
 | 
					    the full URL to the storage server. Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - ``https://minio.mydomain.com``
 | 
				
			||||||
 | 
					    - ``https://s3.wasabisys.com``
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    AWS_S3_REGION_NAME = env("AWS_S3_REGION_NAME", default=None)
 | 
					    AWS_S3_REGION_NAME = env("AWS_S3_REGION_NAME", default=None)
 | 
				
			||||||
 | 
					    """If you are using Amazon S3 to serve media directly, you will need to specify your region
 | 
				
			||||||
 | 
					    name in order to access files. Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - ``eu-west-2``
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AWS_S3_SIGNATURE_VERSION = "s3v4"
 | 
					    AWS_S3_SIGNATURE_VERSION = "s3v4"
 | 
				
			||||||
    AWS_LOCATION = env("AWS_LOCATION", default="")
 | 
					    AWS_LOCATION = env("AWS_LOCATION", default="")
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    An optional bucket subdirectory were you want to store the files. This is especially useful
 | 
				
			||||||
 | 
					    if you plan to use share the bucket with other services
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    DEFAULT_FILE_STORAGE = "funkwhale_api.common.storage.ASCIIS3Boto3Storage"
 | 
					    DEFAULT_FILE_STORAGE = "funkwhale_api.common.storage.ASCIIS3Boto3Storage"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
 | 
					# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
 | 
				
			||||||
STATICFILES_DIRS = (str(APPS_DIR.path("static")),)
 | 
					STATICFILES_DIRS = (str(APPS_DIR.path("static")),)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -408,14 +529,25 @@ STATICFILES_FINDERS = (
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root
 | 
					# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root
 | 
				
			||||||
MEDIA_ROOT = env("MEDIA_ROOT", default=str(APPS_DIR("media")))
 | 
					MEDIA_ROOT = env("MEDIA_ROOT", default=str(APPS_DIR("media")))
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Where media files (such as album covers or audio tracks) should be stored
 | 
				
			||||||
 | 
					on your system? (Ensure this directory actually exists)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url
 | 
					# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url
 | 
				
			||||||
MEDIA_URL = env("MEDIA_URL", default=FUNKWHALE_URL + "/media/")
 | 
					MEDIA_URL = env("MEDIA_URL", default=FUNKWHALE_URL + "/media/")
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					URL where media files are served. The default value should work fine on most
 | 
				
			||||||
 | 
					configurations, but could can tweak this if you are hosting media files on a separate
 | 
				
			||||||
 | 
					domain, or if you host Funkwhale on a non-standard port.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
FILE_UPLOAD_PERMISSIONS = 0o644
 | 
					FILE_UPLOAD_PERMISSIONS = 0o644
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ATTACHMENTS_UNATTACHED_PRUNE_DELAY = env.int(
 | 
					ATTACHMENTS_UNATTACHED_PRUNE_DELAY = env.int(
 | 
				
			||||||
    "ATTACHMENTS_UNATTACHED_PRUNE_DELAY", default=3600 * 24
 | 
					    "ATTACHMENTS_UNATTACHED_PRUNE_DELAY", default=3600 * 24
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Delay in seconds before uploaded but unattached attachements are pruned from the system.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# URL Configuration
 | 
					# URL Configuration
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					@ -441,6 +573,14 @@ ACCOUNT_EMAIL_REQUIRED = True
 | 
				
			||||||
ACCOUNT_EMAIL_VERIFICATION_ENFORCE = env.bool(
 | 
					ACCOUNT_EMAIL_VERIFICATION_ENFORCE = env.bool(
 | 
				
			||||||
    "ACCOUNT_EMAIL_VERIFICATION_ENFORCE", default=False
 | 
					    "ACCOUNT_EMAIL_VERIFICATION_ENFORCE", default=False
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Determine wether users need to verify their email address before using the service. Enabling this can be useful
 | 
				
			||||||
 | 
					to reduce spam or bots accounts, however, you'll need to configure a mail server so that your users can receive the
 | 
				
			||||||
 | 
					verification emails, using :attr:`EMAIL_CONFIG`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that regardless of the setting value, superusers created through the command line will never require verification.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
ACCOUNT_EMAIL_VERIFICATION = (
 | 
					ACCOUNT_EMAIL_VERIFICATION = (
 | 
				
			||||||
    "mandatory" if ACCOUNT_EMAIL_VERIFICATION_ENFORCE else "optional"
 | 
					    "mandatory" if ACCOUNT_EMAIL_VERIFICATION_ENFORCE else "optional"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -472,6 +612,10 @@ OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = "users.RefreshToken"
 | 
				
			||||||
# LDAP AUTHENTICATION CONFIGURATION
 | 
					# LDAP AUTHENTICATION CONFIGURATION
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
AUTH_LDAP_ENABLED = env.bool("LDAP_ENABLED", default=False)
 | 
					AUTH_LDAP_ENABLED = env.bool("LDAP_ENABLED", default=False)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Wether to enable LDAP authentication. See :doc:`/installation/ldap` for more information.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if AUTH_LDAP_ENABLED:
 | 
					if AUTH_LDAP_ENABLED:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Import the LDAP modules here; this way, we don't need the dependency unless someone
 | 
					    # Import the LDAP modules here; this way, we don't need the dependency unless someone
 | 
				
			||||||
| 
						 | 
					@ -541,8 +685,22 @@ if AUTH_LDAP_ENABLED:
 | 
				
			||||||
AUTOSLUG_SLUGIFY_FUNCTION = "slugify.slugify"
 | 
					AUTOSLUG_SLUGIFY_FUNCTION = "slugify.slugify"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CACHE_DEFAULT = "redis://127.0.0.1:6379/0"
 | 
					CACHE_DEFAULT = "redis://127.0.0.1:6379/0"
 | 
				
			||||||
 | 
					CACHE_URL = env.cache_url("CACHE_URL", default=CACHE_DEFAULT)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					URL to your redis server. Examples:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `redis://<host>:<port>/<database>`
 | 
				
			||||||
 | 
					- `redis://127.0.0.1:6379/0`
 | 
				
			||||||
 | 
					- `redis://:password@localhost:6379/0` for password auth (the extra semicolon is important)
 | 
				
			||||||
 | 
					- `redis:///run/redis/redis.sock?db=0` over unix sockets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. note::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    If you want to use Redis over unix sockets, you'll also need to update :attr:`CELERY_BROKER_URL`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
CACHES = {
 | 
					CACHES = {
 | 
				
			||||||
    "default": env.cache_url("CACHE_URL", default=CACHE_DEFAULT),
 | 
					    "default": CACHE_URL,
 | 
				
			||||||
    "local": {
 | 
					    "local": {
 | 
				
			||||||
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
 | 
					        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
 | 
				
			||||||
        "LOCATION": "local-cache",
 | 
					        "LOCATION": "local-cache",
 | 
				
			||||||
| 
						 | 
					@ -567,7 +725,7 @@ CACHEOPS_ENABLED = bool(CACHEOPS_DURATION)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if CACHEOPS_ENABLED:
 | 
					if CACHEOPS_ENABLED:
 | 
				
			||||||
    INSTALLED_APPS += ("cacheops",)
 | 
					    INSTALLED_APPS += ("cacheops",)
 | 
				
			||||||
    CACHEOPS_REDIS = env("CACHE_URL", default=CACHE_DEFAULT)
 | 
					    CACHEOPS_REDIS = CACHE_URL
 | 
				
			||||||
    CACHEOPS_PREFIX = lambda _: "cacheops"  # noqa
 | 
					    CACHEOPS_PREFIX = lambda _: "cacheops"  # noqa
 | 
				
			||||||
    CACHEOPS_DEFAULTS = {"timeout": CACHEOPS_DURATION}
 | 
					    CACHEOPS_DEFAULTS = {"timeout": CACHEOPS_DURATION}
 | 
				
			||||||
    CACHEOPS = {
 | 
					    CACHEOPS = {
 | 
				
			||||||
| 
						 | 
					@ -581,6 +739,15 @@ INSTALLED_APPS += ("funkwhale_api.taskapp.celery.CeleryConfig",)
 | 
				
			||||||
CELERY_BROKER_URL = env(
 | 
					CELERY_BROKER_URL = env(
 | 
				
			||||||
    "CELERY_BROKER_URL", default=env("CACHE_URL", default=CACHE_DEFAULT)
 | 
					    "CELERY_BROKER_URL", default=env("CACHE_URL", default=CACHE_DEFAULT)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					URL to celery's task broker. Defaults to :attr:`CACHE_URL`, so you shouldn't have to tweak this, unless you want
 | 
				
			||||||
 | 
					to use a different one, or use Redis sockets to connect.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Exemple:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `redis://127.0.0.1:6379/0`
 | 
				
			||||||
 | 
					- `redis+socket:///run/redis/redis.sock?virtual_host=0`
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# END CELERY
 | 
					# END CELERY
 | 
				
			||||||
# Location of root django.contrib.admin URL, use {% url 'admin:index' %}
 | 
					# Location of root django.contrib.admin URL, use {% url 'admin:index' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -667,7 +834,11 @@ AUTH_PASSWORD_VALIDATORS = [
 | 
				
			||||||
    {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
 | 
					    {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
 | 
				
			||||||
    {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
 | 
					    {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
if env.bool("DISABLE_PASSWORD_VALIDATORS", default=False):
 | 
					DISABLE_PASSWORD_VALIDATORS = env.bool("DISABLE_PASSWORD_VALIDATORS", default=False)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Wether to disable password validators (length, common words, similarity with username…) used during regitration.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					if DISABLE_PASSWORD_VALIDATORS:
 | 
				
			||||||
    AUTH_PASSWORD_VALIDATORS = []
 | 
					    AUTH_PASSWORD_VALIDATORS = []
 | 
				
			||||||
ACCOUNT_ADAPTER = "funkwhale_api.users.adapters.FunkwhaleAccountAdapter"
 | 
					ACCOUNT_ADAPTER = "funkwhale_api.users.adapters.FunkwhaleAccountAdapter"
 | 
				
			||||||
CORS_ORIGIN_ALLOW_ALL = True
 | 
					CORS_ORIGIN_ALLOW_ALL = True
 | 
				
			||||||
| 
						 | 
					@ -705,6 +876,11 @@ REST_FRAMEWORK = {
 | 
				
			||||||
    "NUM_PROXIES": env.int("NUM_PROXIES", default=1),
 | 
					    "NUM_PROXIES": env.int("NUM_PROXIES", default=1),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
THROTTLING_ENABLED = env.bool("THROTTLING_ENABLED", default=True)
 | 
					THROTTLING_ENABLED = env.bool("THROTTLING_ENABLED", default=True)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Wether to enable throttling (also known as rate-limiting). Leaving this enabled is recommended
 | 
				
			||||||
 | 
					especially on public pods, to improve the quality of service.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if THROTTLING_ENABLED:
 | 
					if THROTTLING_ENABLED:
 | 
				
			||||||
    REST_FRAMEWORK["DEFAULT_THROTTLE_CLASSES"] = env.list(
 | 
					    REST_FRAMEWORK["DEFAULT_THROTTLE_CLASSES"] = env.list(
 | 
				
			||||||
        "THROTTLE_CLASSES",
 | 
					        "THROTTLE_CLASSES",
 | 
				
			||||||
| 
						 | 
					@ -853,7 +1029,16 @@ THROTTLING_RATES = {
 | 
				
			||||||
        "description": "Fetch remote objects",
 | 
					        "description": "Fetch remote objects",
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					THROTTLING_RATES = THROTTLING_RATES
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Throttling rates for specific endpoints and features of the app. You can tweak this if you are
 | 
				
			||||||
 | 
					encountering to severe rate limiting issues or, on the contrary, if you want to reduce
 | 
				
			||||||
 | 
					the consumption on some endpoints.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- ``signup=5/d,password-reset=2/d,anonymous-reports=5/d``
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BROWSABLE_API_ENABLED = env.bool("BROWSABLE_API_ENABLED", default=False)
 | 
					BROWSABLE_API_ENABLED = env.bool("BROWSABLE_API_ENABLED", default=False)
 | 
				
			||||||
if BROWSABLE_API_ENABLED:
 | 
					if BROWSABLE_API_ENABLED:
 | 
				
			||||||
| 
						 | 
					@ -874,24 +1059,48 @@ USE_X_FORWARDED_PORT = True
 | 
				
			||||||
# Wether we should use Apache, Nginx (or other) headers when serving audio files
 | 
					# Wether we should use Apache, Nginx (or other) headers when serving audio files
 | 
				
			||||||
# Default to Nginx
 | 
					# Default to Nginx
 | 
				
			||||||
REVERSE_PROXY_TYPE = env("REVERSE_PROXY_TYPE", default="nginx")
 | 
					REVERSE_PROXY_TYPE = env("REVERSE_PROXY_TYPE", default="nginx")
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Depending on the reverse proxy used in front of your funkwhale instance,
 | 
				
			||||||
 | 
					the API will use different kind of headers to serve audio files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Allowed values: ``nginx``, ``apache2``
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
assert REVERSE_PROXY_TYPE in ["apache2", "nginx"], "Unsupported REVERSE_PROXY_TYPE"
 | 
					assert REVERSE_PROXY_TYPE in ["apache2", "nginx"], "Unsupported REVERSE_PROXY_TYPE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Which path will be used to process the internal redirection
 | 
					 | 
				
			||||||
# **DO NOT** put a slash at the end
 | 
					 | 
				
			||||||
PROTECT_FILES_PATH = env("PROTECT_FILES_PATH", default="/_protected")
 | 
					PROTECT_FILES_PATH = env("PROTECT_FILES_PATH", default="/_protected")
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Which path will be used to process the internal redirection to the reverse proxy
 | 
				
			||||||
 | 
					**DO NOT** put a slash at the end.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You shouldn't have to tweak this.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# use this setting to tweak for how long you want to cache
 | 
					 | 
				
			||||||
# musicbrainz results. (value is in seconds)
 | 
					 | 
				
			||||||
MUSICBRAINZ_CACHE_DURATION = env.int("MUSICBRAINZ_CACHE_DURATION", default=300)
 | 
					MUSICBRAINZ_CACHE_DURATION = env.int("MUSICBRAINZ_CACHE_DURATION", default=300)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# Use this setting to change the musicbrainz hostname, for instance to
 | 
					How long to cache MusicBrainz results, in seconds
 | 
				
			||||||
# use a mirror. The hostname can also contain a port number (so, e.g.,
 | 
					"""
 | 
				
			||||||
# "localhost:5000" is a valid name to set).
 | 
					 | 
				
			||||||
MUSICBRAINZ_HOSTNAME = env("MUSICBRAINZ_HOSTNAME", default="musicbrainz.org")
 | 
					MUSICBRAINZ_HOSTNAME = env("MUSICBRAINZ_HOSTNAME", default="musicbrainz.org")
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Use this setting to change the musicbrainz hostname, for instance to
 | 
				
			||||||
 | 
					use a mirror. The hostname can also contain a port number.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- ``mymusicbrainz.mirror``
 | 
				
			||||||
 | 
					- ``localhost:5000``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# Custom Admin URL, use {% url 'admin:index' %}
 | 
					# Custom Admin URL, use {% url 'admin:index' %}
 | 
				
			||||||
ADMIN_URL = env("DJANGO_ADMIN_URL", default="^api/admin/")
 | 
					ADMIN_URL = env("DJANGO_ADMIN_URL", default="^api/admin/")
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Path to the Django admin area.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Exemples:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `^api/admin/`
 | 
				
			||||||
 | 
					- `^api/mycustompath/`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
CSRF_USE_SESSIONS = True
 | 
					CSRF_USE_SESSIONS = True
 | 
				
			||||||
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
 | 
					SESSION_ENGINE = "django.contrib.sessions.backends.cache"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -899,6 +1108,7 @@ SESSION_ENGINE = "django.contrib.sessions.backends.cache"
 | 
				
			||||||
# XXX: deprecated, see #186
 | 
					# XXX: deprecated, see #186
 | 
				
			||||||
PLAYLISTS_MAX_TRACKS = env.int("PLAYLISTS_MAX_TRACKS", default=250)
 | 
					PLAYLISTS_MAX_TRACKS = env.int("PLAYLISTS_MAX_TRACKS", default=250)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ACCOUNT_USERNAME_BLACKLIST = [
 | 
					ACCOUNT_USERNAME_BLACKLIST = [
 | 
				
			||||||
    "funkwhale",
 | 
					    "funkwhale",
 | 
				
			||||||
    "library",
 | 
					    "library",
 | 
				
			||||||
| 
						 | 
					@ -923,24 +1133,71 @@ ACCOUNT_USERNAME_BLACKLIST = [
 | 
				
			||||||
    "shared_inbox",
 | 
					    "shared_inbox",
 | 
				
			||||||
    "actor",
 | 
					    "actor",
 | 
				
			||||||
] + env.list("ACCOUNT_USERNAME_BLACKLIST", default=[])
 | 
					] + env.list("ACCOUNT_USERNAME_BLACKLIST", default=[])
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					List of usernames that will be unavailable during registration.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
EXTERNAL_REQUESTS_VERIFY_SSL = env.bool("EXTERNAL_REQUESTS_VERIFY_SSL", default=True)
 | 
					EXTERNAL_REQUESTS_VERIFY_SSL = env.bool("EXTERNAL_REQUESTS_VERIFY_SSL", default=True)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Wether to enforce HTTPS certificates verification when doing outgoing HTTP requests (typically with federation).
 | 
				
			||||||
 | 
					Disabling this is not recommended.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
EXTERNAL_REQUESTS_TIMEOUT = env.int("EXTERNAL_REQUESTS_TIMEOUT", default=10)
 | 
					EXTERNAL_REQUESTS_TIMEOUT = env.int("EXTERNAL_REQUESTS_TIMEOUT", default=10)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Default timeout for external requests.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# XXX: deprecated, see #186
 | 
					# XXX: deprecated, see #186
 | 
				
			||||||
API_AUTHENTICATION_REQUIRED = env.bool("API_AUTHENTICATION_REQUIRED", True)
 | 
					API_AUTHENTICATION_REQUIRED = env.bool("API_AUTHENTICATION_REQUIRED", True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MUSIC_DIRECTORY_PATH = env("MUSIC_DIRECTORY_PATH", default=None)
 | 
					MUSIC_DIRECTORY_PATH = env("MUSIC_DIRECTORY_PATH", default=None)
 | 
				
			||||||
# on Docker setup, the music directory may not match the host path,
 | 
					"""
 | 
				
			||||||
# and we need to know it for it to serve stuff properly
 | 
					The path on your server where Funkwhale can import files using :ref:`in-place import
 | 
				
			||||||
 | 
					<in-place-import>`. It must be readable by the webserver and Funkwhale
 | 
				
			||||||
 | 
					api and worker processes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					On docker installations, we recommend you use the default of ``/music``
 | 
				
			||||||
 | 
					for this value. For non-docker installation, you can use any absolute path.
 | 
				
			||||||
 | 
					``/srv/funkwhale/data/music`` is a safe choice if you don't know what to use.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. note:: This path should not include any trailing slash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. warning::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   You need to adapt your :ref:`reverse-proxy configuration<reverse-proxy-setup>` to
 | 
				
			||||||
 | 
					   serve the directory pointed by ``MUSIC_DIRECTORY_PATH`` on
 | 
				
			||||||
 | 
					   ``/_protected/music`` URL.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
MUSIC_DIRECTORY_SERVE_PATH = env(
 | 
					MUSIC_DIRECTORY_SERVE_PATH = env(
 | 
				
			||||||
    "MUSIC_DIRECTORY_SERVE_PATH", default=MUSIC_DIRECTORY_PATH
 | 
					    "MUSIC_DIRECTORY_SERVE_PATH", default=MUSIC_DIRECTORY_PATH
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Default: :attr:`MUSIC_DIRECTORY_PATH`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When using Docker, the value of :attr:`MUSIC_DIRECTORY_PATH` in your containers
 | 
				
			||||||
 | 
					may differ from the real path on your host. Assuming you have the following directive
 | 
				
			||||||
 | 
					in your :file:`docker-compose.yml` file::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - /srv/funkwhale/data/music:/music:ro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Then, the value of :attr:`MUSIC_DIRECTORY_SERVE_PATH` should be
 | 
				
			||||||
 | 
					``/srv/funkwhale/data/music``. This must be readable by the webserver.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					On non-docker setup, you don't need to configure this setting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. note:: This path should not include any trailing slash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# When this is set to default=True, we need to reenable migration music/0042
 | 
					# When this is set to default=True, we need to reenable migration music/0042
 | 
				
			||||||
# to ensure data is populated correctly on existing pods
 | 
					# to ensure data is populated correctly on existing pods
 | 
				
			||||||
MUSIC_USE_DENORMALIZATION = env.bool("MUSIC_USE_DENORMALIZATION", default=False)
 | 
					MUSIC_USE_DENORMALIZATION = env.bool("MUSIC_USE_DENORMALIZATION", default=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
USERS_INVITATION_EXPIRATION_DAYS = env.int(
 | 
					USERS_INVITATION_EXPIRATION_DAYS = env.int(
 | 
				
			||||||
    "USERS_INVITATION_EXPIRATION_DAYS", default=14
 | 
					    "USERS_INVITATION_EXPIRATION_DAYS", default=14
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Expiration delay in days, for user invitations.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VERSATILEIMAGEFIELD_RENDITION_KEY_SETS = {
 | 
					VERSATILEIMAGEFIELD_RENDITION_KEY_SETS = {
 | 
				
			||||||
    "square": [
 | 
					    "square": [
 | 
				
			||||||
| 
						 | 
					@ -964,40 +1221,84 @@ ACTOR_KEY_ROTATION_DELAY = env.int("ACTOR_KEY_ROTATION_DELAY", default=3600 * 48
 | 
				
			||||||
SUBSONIC_DEFAULT_TRANSCODING_FORMAT = (
 | 
					SUBSONIC_DEFAULT_TRANSCODING_FORMAT = (
 | 
				
			||||||
    env("SUBSONIC_DEFAULT_TRANSCODING_FORMAT", default="mp3") or None
 | 
					    env("SUBSONIC_DEFAULT_TRANSCODING_FORMAT", default="mp3") or None
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Default format for transcoding when using Subsonic API.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# extra tags will be ignored
 | 
					# extra tags will be ignored
 | 
				
			||||||
TAGS_MAX_BY_OBJ = env.int("TAGS_MAX_BY_OBJ", default=30)
 | 
					TAGS_MAX_BY_OBJ = env.int("TAGS_MAX_BY_OBJ", default=30)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Maximum number of tags that can be associated with an object. Extra tags will be ignored.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
FEDERATION_OBJECT_FETCH_DELAY = env.int(
 | 
					FEDERATION_OBJECT_FETCH_DELAY = env.int(
 | 
				
			||||||
    "FEDERATION_OBJECT_FETCH_DELAY", default=60 * 24 * 3
 | 
					    "FEDERATION_OBJECT_FETCH_DELAY", default=60 * 24 * 3
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Number of minutes before a remote object will be automatically refetched when accessed in the UI.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
MODERATION_EMAIL_NOTIFICATIONS_ENABLED = env.bool(
 | 
					MODERATION_EMAIL_NOTIFICATIONS_ENABLED = env.bool(
 | 
				
			||||||
    "MODERATION_EMAIL_NOTIFICATIONS_ENABLED", default=True
 | 
					    "MODERATION_EMAIL_NOTIFICATIONS_ENABLED", default=True
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Whether to enable email notifications to moderators and pods admins.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
FEDERATION_AUTHENTIFY_FETCHES = True
 | 
					FEDERATION_AUTHENTIFY_FETCHES = True
 | 
				
			||||||
FEDERATION_SYNCHRONOUS_FETCH = env.bool("FEDERATION_SYNCHRONOUS_FETCH", default=True)
 | 
					FEDERATION_SYNCHRONOUS_FETCH = env.bool("FEDERATION_SYNCHRONOUS_FETCH", default=True)
 | 
				
			||||||
FEDERATION_DUPLICATE_FETCH_DELAY = env.int(
 | 
					FEDERATION_DUPLICATE_FETCH_DELAY = env.int(
 | 
				
			||||||
    "FEDERATION_DUPLICATE_FETCH_DELAY", default=60 * 50
 | 
					    "FEDERATION_DUPLICATE_FETCH_DELAY", default=60 * 50
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
# Delay in days after signup before we show the "support us" messages
 | 
					"""
 | 
				
			||||||
 | 
					Delay, in seconds, between two manual fetch of the same remote object.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
INSTANCE_SUPPORT_MESSAGE_DELAY = env.int("INSTANCE_SUPPORT_MESSAGE_DELAY", default=15)
 | 
					INSTANCE_SUPPORT_MESSAGE_DELAY = env.int("INSTANCE_SUPPORT_MESSAGE_DELAY", default=15)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Delay in days after signup before we show the "support your pod" message
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
FUNKWHALE_SUPPORT_MESSAGE_DELAY = env.int("FUNKWHALE_SUPPORT_MESSAGE_DELAY", default=15)
 | 
					FUNKWHALE_SUPPORT_MESSAGE_DELAY = env.int("FUNKWHALE_SUPPORT_MESSAGE_DELAY", default=15)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Delay in days after signup before we show the "support Funkwhale" message
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# XXX Stable release: remove
 | 
					# XXX Stable release: remove
 | 
				
			||||||
USE_FULL_TEXT_SEARCH = env.bool("USE_FULL_TEXT_SEARCH", default=True)
 | 
					USE_FULL_TEXT_SEARCH = env.bool("USE_FULL_TEXT_SEARCH", default=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MIN_DELAY_BETWEEN_DOWNLOADS_COUNT = env.int(
 | 
					MIN_DELAY_BETWEEN_DOWNLOADS_COUNT = env.int(
 | 
				
			||||||
    "MIN_DELAY_BETWEEN_DOWNLOADS_COUNT", default=60 * 60 * 6
 | 
					    "MIN_DELAY_BETWEEN_DOWNLOADS_COUNT", default=60 * 60 * 6
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Minimum required period, in seconds, for two downloads of the same track by the same IP
 | 
				
			||||||
 | 
					or user to be recorded in statistics.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
MARKDOWN_EXTENSIONS = env.list("MARKDOWN_EXTENSIONS", default=["nl2br", "extra"])
 | 
					MARKDOWN_EXTENSIONS = env.list("MARKDOWN_EXTENSIONS", default=["nl2br", "extra"])
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					List of markdown extensions to enable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Cf `<https://python-markdown.github.io/extensions/>`_
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
LINKIFIER_SUPPORTED_TLDS = ["audio"] + env.list("LINKINFIER_SUPPORTED_TLDS", default=[])
 | 
					LINKIFIER_SUPPORTED_TLDS = ["audio"] + env.list("LINKINFIER_SUPPORTED_TLDS", default=[])
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Additional TLDs to support with our markdown linkifier.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
EXTERNAL_MEDIA_PROXY_ENABLED = env.bool("EXTERNAL_MEDIA_PROXY_ENABLED", default=True)
 | 
					EXTERNAL_MEDIA_PROXY_ENABLED = env.bool("EXTERNAL_MEDIA_PROXY_ENABLED", default=True)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# By default, only people who subscribe to a podcast RSS will have access to it
 | 
					Wether to proxy attachment files hosted on third party pods and and servers. Keeping
 | 
				
			||||||
# switch to "instance" or "everyone" to change that
 | 
					this to true is recommended, to reduce leaking browsing information of your users, and
 | 
				
			||||||
 | 
					reduce the bandwidth used on remote pods.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
PODCASTS_THIRD_PARTY_VISIBILITY = env("PODCASTS_THIRD_PARTY_VISIBILITY", default="me")
 | 
					PODCASTS_THIRD_PARTY_VISIBILITY = env("PODCASTS_THIRD_PARTY_VISIBILITY", default="me")
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					By default, only people who subscribe to a podcast RSS will have access to their episodes.
 | 
				
			||||||
 | 
					switch to "instance" or "everyone" to change that.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Changing it only affect new podcasts.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
PODCASTS_RSS_FEED_REFRESH_DELAY = env.int(
 | 
					PODCASTS_RSS_FEED_REFRESH_DELAY = env.int(
 | 
				
			||||||
    "PODCASTS_RSS_FEED_REFRESH_DELAY", default=60 * 60 * 24
 | 
					    "PODCASTS_RSS_FEED_REFRESH_DELAY", default=60 * 60 * 24
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Delay in seconds between to fetch of RSS feeds. Reducing this mean you'll receive new episodes faster,
 | 
				
			||||||
 | 
					but will require more resources.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
# maximum items loaded through XML feed
 | 
					# maximum items loaded through XML feed
 | 
				
			||||||
PODCASTS_RSS_FEED_MAX_ITEMS = env.int("PODCASTS_RSS_FEED_MAX_ITEMS", default=250)
 | 
					PODCASTS_RSS_FEED_MAX_ITEMS = env.int("PODCASTS_RSS_FEED_MAX_ITEMS", default=250)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Maximum number of RSS items to load in each podcast feed.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
FROM python:3.6
 | 
					FROM python:3.6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RUN apt-get update && apt-get install -y graphviz
 | 
					RUN apt-get update && apt-get install -y graphviz
 | 
				
			||||||
RUN pip install sphinx livereload sphinx_rtd_theme
 | 
					RUN pip install sphinx livereload sphinx_rtd_theme django-environ django
 | 
				
			||||||
WORKDIR /app/docs
 | 
					WORKDIR /app/docs
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,18 @@
 | 
				
			||||||
Instance configuration
 | 
					Instance configuration
 | 
				
			||||||
======================
 | 
					======================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
General configuration is achieved using two type of settings.
 | 
					General configuration is achieved using two type of settings:
 | 
				
			||||||
 | 
					:ref:`environment variables <environment-variables>` and
 | 
				
			||||||
 | 
					:ref:`instance settings <instance-settings>`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. _environment-variables:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Environment variables
 | 
					Environment variables
 | 
				
			||||||
---------------------
 | 
					---------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Those are located in your ``.env`` file, which you should have created
 | 
					Those are located in your ``.env`` file, which you should have created
 | 
				
			||||||
during installation.
 | 
					during installation. A full list of available variables can be seen
 | 
				
			||||||
 | 
					:ref:`below <environment-variables>`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Options from this file are heavily commented, and usually target lower level
 | 
					Options from this file are heavily commented, and usually target lower level
 | 
				
			||||||
and technical aspects of your instance, such as database credentials.
 | 
					and technical aspects of your instance, such as database credentials.
 | 
				
			||||||
| 
						 | 
					@ -33,7 +38,7 @@ and technical aspects of your instance, such as database credentials.
 | 
				
			||||||
Instance settings
 | 
					Instance settings
 | 
				
			||||||
-----------------
 | 
					-----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Those settings are stored in database and do not require a restart of your
 | 
					These settings are stored in the database and do not require a restart of your
 | 
				
			||||||
instance after modification. They typically relate to higher level configuration,
 | 
					instance after modification. They typically relate to higher level configuration,
 | 
				
			||||||
such your instance description, signup policy and so on.
 | 
					such your instance description, signup policy and so on.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +47,7 @@ you have the required permissions. The URL is ``/manage/settings``, and
 | 
				
			||||||
you will also find a link to this page in the sidebar.
 | 
					you will also find a link to this page in the sidebar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you plan to use acoustid and external imports
 | 
					If you plan to use acoustid and external imports
 | 
				
			||||||
(e.g. with the youtube backends), you should edit the corresponding
 | 
					(e.g. with the YouTube backends), you should edit the corresponding
 | 
				
			||||||
settings in this interface.
 | 
					settings in this interface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. note::
 | 
					.. note::
 | 
				
			||||||
| 
						 | 
					@ -58,113 +63,114 @@ settings in this interface.
 | 
				
			||||||
Configuration reference
 | 
					Configuration reference
 | 
				
			||||||
-----------------------
 | 
					-----------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. _setting-ACCOUNT_EMAIL_VERIFICATION_ENFORCE:
 | 
					Pod
 | 
				
			||||||
 | 
					^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
``ACCOUNT_EMAIL_VERIFICATION_ENFORCE``
 | 
					.. autodata:: config.settings.common.FUNKWHALE_HOSTNAME
 | 
				
			||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
					    :annotation:
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.FUNKWHALE_PROTOCOL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Determine wether users need to verify their email address before using the service. Enabling this can be useful
 | 
					Database and redis
 | 
				
			||||||
to reduce spam or bots accounts, however, you'll need to configure a SMTP server so that your users can receive the
 | 
					^^^^^^^^^^^^^^^^^^
 | 
				
			||||||
verification emails.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Note that regardless of the setting value, superusers created through the command line will never require verification.
 | 
					.. autodata:: config.settings.common.DATABASE_URL
 | 
				
			||||||
 | 
					    :annotation:
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.DB_CONN_MAX_AGE
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.CACHE_URL
 | 
				
			||||||
 | 
					    :annotation:
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.CELERY_BROKER_URL
 | 
				
			||||||
 | 
					    :annotation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Default: ``false``
 | 
					Accounts and registration
 | 
				
			||||||
 | 
					^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. _setting-EMAIL_CONFIG:
 | 
					.. autodata:: config.settings.common.ACCOUNT_EMAIL_VERIFICATION_ENFORCE
 | 
				
			||||||
 | 
					    :annotation:
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.USERS_INVITATION_EXPIRATION_DAYS
 | 
				
			||||||
 | 
					    :annotation:
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.DISABLE_PASSWORD_VALIDATORS
 | 
				
			||||||
 | 
					    :annotation:
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.ACCOUNT_USERNAME_BLACKLIST
 | 
				
			||||||
 | 
					    :annotation:
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.AUTH_LDAP_ENABLED
 | 
				
			||||||
 | 
					    :annotation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
``EMAIL_CONFIG``
 | 
					Media storage and serving
 | 
				
			||||||
^^^^^^^^^^^^^^^^
 | 
					^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Determine how emails are sent.
 | 
					.. 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
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.ATTACHMENTS_UNATTACHED_PRUNE_DELAY
 | 
				
			||||||
 | 
					    :annotation: = true
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.REVERSE_PROXY_TYPE
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.PROTECT_FILES_PATH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Default: ``consolemail://``
 | 
					Audio acquisition
 | 
				
			||||||
 | 
					^^^^^^^^^^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Possible values:
 | 
					.. autodata:: config.settings.common.MUSIC_DIRECTORY_PATH
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.MUSIC_DIRECTORY_SERVE_PATH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- ``consolemail://``: Output sent emails to stdout
 | 
					S3 Storage
 | 
				
			||||||
- ``dummymail://``: Completely discard sent emails
 | 
					^^^^^^^^^^
 | 
				
			||||||
- ``smtp://user:password@youremail.host:25``: Send emails via SMTP via youremail.host on port 25, without encryption, authenticating as user "user" with password "password"
 | 
					 | 
				
			||||||
- ``smtp+ssl://user:password@youremail.host:465``: Send emails via SMTP via youremail.host on port 465, using SSL encryption, authenticating as user "user" with password "password"
 | 
					 | 
				
			||||||
- ``smtp+tls://user:password@youremail.host:587``: Send emails via SMTP via youremail.host on port 587, using TLS encryption, authenticating as user "user" with password "password"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. note::
 | 
					.. 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
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.AWS_S3_REGION_NAME
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.AWS_LOCATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    If ``user`` or ``password`` contain special characters (eg.
 | 
					API configuration
 | 
				
			||||||
    ``noreply@youremail.host`` as ``user``), be sure to urlencode them, using
 | 
					^^^^^^^^^^^^^^^^^
 | 
				
			||||||
    for example the command:
 | 
					 | 
				
			||||||
    ``python3 -c 'import urllib.parse; print(urllib.parse.quote_plus("noreply@youremail.host"))'``
 | 
					 | 
				
			||||||
    (returns ``noreply%40youremail.host``)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.THROTTLING_ENABLED
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.THROTTLING_RATES
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.ADMIN_URL
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.EXTERNAL_REQUESTS_VERIFY_SSL
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.EXTERNAL_REQUESTS_TIMEOUT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. _setting-DEFAULT_FROM_EMAIL:
 | 
					Federation
 | 
				
			||||||
 | 
					^^^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
``DEFAULT_FROM_EMAIL``
 | 
					.. autodata:: config.settings.common.FEDERATION_OBJECT_FETCH_DELAY
 | 
				
			||||||
^^^^^^^^^^^^^^^^^^^^^^
 | 
					.. autodata:: config.settings.common.FEDERATION_DUPLICATE_FETCH_DELAY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The email address to use to send email.
 | 
					Metadata
 | 
				
			||||||
 | 
					^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Default: ``Funkwhale <noreply@yourdomain>``
 | 
					.. autodata:: config.settings.common.TAGS_MAX_BY_OBJ
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.MUSICBRAINZ_HOSTNAME
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.MUSICBRAINZ_CACHE_DURATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. note::
 | 
					Channels and podcasts
 | 
				
			||||||
 | 
					^^^^^^^^^^^^^^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Both the forms ``Funkwhale <noreply@yourdomain>`` and
 | 
					.. autodata:: config.settings.common.PODCASTS_RSS_FEED_REFRESH_DELAY
 | 
				
			||||||
    ``noreply@yourdomain`` work.
 | 
					.. autodata:: config.settings.common.PODCASTS_RSS_FEED_MAX_ITEMS
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.PODCASTS_THIRD_PARTY_VISIBILITY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Subsonic
 | 
				
			||||||
 | 
					^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. _setting-MUSIC_DIRECTORY_PATH:
 | 
					.. autodata:: config.settings.common.SUBSONIC_DEFAULT_TRANSCODING_FORMAT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
``MUSIC_DIRECTORY_PATH``
 | 
					Other settings
 | 
				
			||||||
^^^^^^^^^^^^^^^^^^^^^^^^
 | 
					^^^^^^^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Default: ``None``
 | 
					.. autodata:: config.settings.common.INSTANCE_SUPPORT_MESSAGE_DELAY
 | 
				
			||||||
 | 
					.. autodata:: config.settings.common.FUNKWHALE_SUPPORT_MESSAGE_DELAY
 | 
				
			||||||
The path on your server where Funkwhale can import files using :ref:`in-place import
 | 
					.. autodata:: config.settings.common.MIN_DELAY_BETWEEN_DOWNLOADS_COUNT
 | 
				
			||||||
<in-place-import>`. It must be readable by the webserver and Funkwhale
 | 
					.. autodata:: config.settings.common.MARKDOWN_EXTENSIONS
 | 
				
			||||||
api and worker processes.
 | 
					.. autodata:: config.settings.common.LINKIFIER_SUPPORTED_TLDS
 | 
				
			||||||
 | 
					 | 
				
			||||||
On docker installations, we recommend you use the default of ``/music``
 | 
					 | 
				
			||||||
for this value. For non-docker installation, you can use any absolute path.
 | 
					 | 
				
			||||||
``/srv/funkwhale/data/music`` is a safe choice if you don't know what to use.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. note:: This path should not include any trailing slash
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. warning::
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   You need to adapt your :ref:`reverse-proxy configuration<reverse-proxy-setup>` to
 | 
					 | 
				
			||||||
   serve the directory pointed by ``MUSIC_DIRECTORY_PATH`` on
 | 
					 | 
				
			||||||
   ``/_protected/music`` URL.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. _setting-MUSIC_DIRECTORY_SERVE_PATH:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
``MUSIC_DIRECTORY_SERVE_PATH``
 | 
					 | 
				
			||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Default: :ref:`setting-MUSIC_DIRECTORY_PATH`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
When using Docker, the value of :ref:`setting-MUSIC_DIRECTORY_PATH` in your containers
 | 
					 | 
				
			||||||
may differ from the real path on your host. Assuming you have the following directive
 | 
					 | 
				
			||||||
in your :file:`docker-compose.yml` file::
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    volumes:
 | 
					 | 
				
			||||||
      - /srv/funkwhale/data/music:/music:ro
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Then, the value of :ref:`setting-MUSIC_DIRECTORY_SERVE_PATH` should be
 | 
					 | 
				
			||||||
``/srv/funkwhale/data/music``. This must be readable by the webserver.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
On non-docker setup, you don't need to configure this setting.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. note:: This path should not include any trailing slash
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. _setting-REVERSE_PROXY_TYPE:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
``REVERSE_PROXY_TYPE``
 | 
					 | 
				
			||||||
^^^^^^^^^^^^^^^^^^^^^^
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Default: ``nginx``
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The type of reverse-proxy behind which Funkwhale is served. Either ``apache2``
 | 
					 | 
				
			||||||
or ``nginx``. This is only used if you are using in-place import.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
User permissions
 | 
					User permissions
 | 
				
			||||||
----------------
 | 
					----------------
 | 
				
			||||||
| 
						 | 
					@ -194,7 +200,7 @@ to users at ``/api/admin/users/user/``.
 | 
				
			||||||
Front-end settings
 | 
					Front-end settings
 | 
				
			||||||
------------------
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
We offer a basic mechanism to customize the behaviour and look and feel of Funkwhale's Web UI.
 | 
					We offer a basic mechanism to customize the behavior and look and feel of Funkwhale's Web UI.
 | 
				
			||||||
To use any of the options below, you will need to create a custom JSON configuration file and serve it
 | 
					To use any of the options below, you will need to create a custom JSON configuration file and serve it
 | 
				
			||||||
on ``https://yourinstanceurl/settings.json``.
 | 
					on ``https://yourinstanceurl/settings.json``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -296,7 +302,7 @@ On nginx, add the following snippet to your vhost config::
 | 
				
			||||||
        alias /srv/funkwhale/custom;
 | 
					        alias /srv/funkwhale/custom;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
On apache, use the following one::
 | 
					On apache, use the following::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Alias /custom /srv/funkwhale/custom
 | 
					    Alias /custom /srv/funkwhale/custom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								docs/conf.py
								
								
								
								
							
							
						
						
									
										15
									
								
								docs/conf.py
								
								
								
								
							| 
						 | 
					@ -26,6 +26,16 @@ sys.path.insert(0, os.path.abspath("../api"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import funkwhale_api  # NOQA
 | 
					import funkwhale_api  # NOQA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FUNKWHALE_CONFIG = {
 | 
				
			||||||
 | 
					    "FUNKWHALE_URL": "mypod.funkwhale",
 | 
				
			||||||
 | 
					    "FUNKWHAL_PROTOCOL": "https",
 | 
				
			||||||
 | 
					    "DATABASE_URL": "postgres://localhost:5432/db",
 | 
				
			||||||
 | 
					    "AWS_ACCESS_KEY_ID": 'my_access_key',
 | 
				
			||||||
 | 
					    "AWS_SECRET_ACCESS_KEY": 'my_secret_key',
 | 
				
			||||||
 | 
					    "AWS_STORAGE_BUCKET_NAME": 'my_bucket',
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					for key, value in FUNKWHALE_CONFIG.items():
 | 
				
			||||||
 | 
					    os.environ[key] = value
 | 
				
			||||||
# -- General configuration ------------------------------------------------
 | 
					# -- General configuration ------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If your documentation needs a minimal Sphinx version, state it here.
 | 
					# If your documentation needs a minimal Sphinx version, state it here.
 | 
				
			||||||
| 
						 | 
					@ -35,8 +45,9 @@ import funkwhale_api  # NOQA
 | 
				
			||||||
# Add any Sphinx extension module names here, as strings. They can be
 | 
					# Add any Sphinx extension module names here, as strings. They can be
 | 
				
			||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 | 
					# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 | 
				
			||||||
# ones.
 | 
					# ones.
 | 
				
			||||||
extensions = ["sphinx.ext.graphviz"]
 | 
					extensions = ["sphinx.ext.graphviz", "sphinx.ext.autodoc"]
 | 
				
			||||||
 | 
					autodoc_mock_imports = ["celery", "django_auth_ldap", "ldap"]
 | 
				
			||||||
 | 
					add_module_names = False
 | 
				
			||||||
# Add any paths that contain templates here, relative to this directory.
 | 
					# Add any paths that contain templates here, relative to this directory.
 | 
				
			||||||
templates_path = ["_templates"]
 | 
					templates_path = ["_templates"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,5 +6,5 @@ call(["python", "-m", "sphinx", ".", "/tmp/_build"])
 | 
				
			||||||
from livereload import Server, shell
 | 
					from livereload import Server, shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
server = Server()
 | 
					server = Server()
 | 
				
			||||||
server.watch(".", shell("python -m sphinx . /tmp/_build"))
 | 
					server.watch("..", shell("python -m sphinx . /tmp/_build"))
 | 
				
			||||||
server.serve(root="/tmp/_build/", liveport=35730, port=8001, host="0.0.0.0")
 | 
					server.serve(root="/tmp/_build/", liveport=35730, port=8001, host="0.0.0.0")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue