diff --git a/api/config/settings/common.py b/api/config/settings/common.py index 878be7087..75a002853 100644 --- a/api/config/settings/common.py +++ b/api/config/settings/common.py @@ -26,10 +26,14 @@ logging.config.dictConfig( "version": 1, "disable_existing_loggers": False, "formatters": { - "console": {"format": "%(asctime)s %(name)-12s %(levelname)-8s %(message)s"} + "console": { + "format": + "%(asctime)s %(name)-12s %(levelname)-8s %(message)s"} }, "handlers": { - "console": {"class": "logging.StreamHandler", "formatter": "console"}, + "console": { + "class": "logging.StreamHandler", + "formatter": "console"}, }, "loggers": { "funkwhale_api": { @@ -81,7 +85,8 @@ FUNKWHALE_PLUGINS_PATH = env( "FUNKWHALE_PLUGINS_PATH", default="/srv/funkwhale/plugins/" ) """ -Path to a directory containing Funkwhale plugins. These will be imported at runtime. +Path to a directory containing Funkwhale plugins. +These will be imported at runtime. """ sys.path.append(FUNKWHALE_PLUGINS_PATH) CORE_PLUGINS = [ @@ -101,14 +106,19 @@ if LOAD_CORE_PLUGINS: PLUGINS = list(OrderedDict.fromkeys(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: logger.info("Running with no plugins") from .. import plugins # noqa plugins.startup.autodiscover([p + ".funkwhale_startup" for p in PLUGINS]) -DEPENDENCIES = plugins.trigger_filter(plugins.PLUGINS_DEPENDENCIES, [], enabled=True) +DEPENDENCIES = plugins.trigger_filter( + plugins.PLUGINS_DEPENDENCIES, + [], + enabled=True) plugins.install_dependencies(DEPENDENCIES) FUNKWHALE_HOSTNAME = None FUNKWHALE_HOSTNAME_SUFFIX = env("FUNKWHALE_HOSTNAME_SUFFIX", default=None) @@ -128,7 +138,8 @@ else: FUNKWHALE_PROTOCOL = env("FUNKWHALE_PROTOCOL", default="https") """ - Protocol end users will use to access your pod, either ``http`` or ``https``. + Protocol end users will use to access your pod, + either ``http`` or ``https``. """ except Exception: FUNKWHALE_URL = env("FUNKWHALE_URL") @@ -143,13 +154,16 @@ FUNKWHALE_SPA_HTML_ROOT = env( "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 tags relevant to the given page (e.g page title, cover, etc.). +URL or path to the Web Application files. -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. +Funkwhale needs access to it so that it can inject tags +relevant to the given page (e.g page title, cover, etc.). -Use something like ``/srv/funkwhale/front/dist/`` if the web processes shows request errors related to this. +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( @@ -167,19 +181,25 @@ FUNKWHALE_SPA_REWRITE_MANIFEST_URL = env.bool( APP_NAME = "Funkwhale" -FEDERATION_HOSTNAME = env("FEDERATION_HOSTNAME", default=FUNKWHALE_HOSTNAME).lower() +FEDERATION_HOSTNAME = env( + "FEDERATION_HOSTNAME", + default=FUNKWHALE_HOSTNAME).lower() FEDERATION_SERVICE_ACTOR_USERNAME = env( "FEDERATION_SERVICE_ACTOR_USERNAME", default="service" ) # 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. +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. """ @@ -256,7 +276,9 @@ INSTALLED_APPS = ( # MIDDLEWARE CONFIGURATION # ------------------------------------------------------------------------------ -ADDITIONAL_MIDDLEWARES_BEFORE = env.list("ADDITIONAL_MIDDLEWARES_BEFORE", default=[]) +ADDITIONAL_MIDDLEWARES_BEFORE = env.list( + "ADDITIONAL_MIDDLEWARES_BEFORE", + default=[]) MIDDLEWARE = ( tuple(plugins.trigger_filter(plugins.MIDDLEWARES_BEFORE, [], enabled=True)) + tuple(ADDITIONAL_MIDDLEWARES_BEFORE) @@ -275,7 +297,10 @@ MIDDLEWARE = ( "funkwhale_api.users.middleware.RecordActivityMiddleware", "funkwhale_api.common.middleware.ThrottleStatusMiddleware", ) - + tuple(plugins.trigger_filter(plugins.MIDDLEWARES_AFTER, [], enabled=True)) + + tuple(plugins.trigger_filter( + plugins.MIDDLEWARES_AFTER, + [], + enabled=True)) ) # DEBUG @@ -283,12 +308,14 @@ MIDDLEWARE = ( # See: https://docs.djangoproject.com/en/dev/ref/settings/#debug DJANGO_DEBUG = DEBUG = env.bool("DJANGO_DEBUG", False) """ -Whether to enable debugging info and pages. Never enable this on a production server, +Whether to enable debugging info and pages. +Never enable this on a production server, as it can leak very sensitive information. """ # 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 FIXTURE_DIRS = (str(APPS_DIR.path("fixtures")),) # EMAIL CONFIGURATION @@ -297,7 +324,8 @@ FIXTURE_DIRS = (str(APPS_DIR.path("fixtures")),) # EMAIL # ------------------------------------------------------------------------------ DEFAULT_FROM_EMAIL = env( - "DEFAULT_FROM_EMAIL", default="Funkwhale ".format(FUNKWHALE_HOSTNAME) + "DEFAULT_FROM_EMAIL", + default="Funkwhale ".format(FUNKWHALE_HOSTNAME) ) """ Name and email address used to send system emails. @@ -335,7 +363,8 @@ On a production instance, you'll usually want to use an external SMTP server: 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"))'`` + ``python3 -c 'import urllib.parse; + print(urllib.parse.quote_plus("noreply@youremail.host"))'`` (returns ``noreply%40youremail.host``) """ @@ -399,20 +428,25 @@ USE_TZ = True # See: https://docs.djangoproject.com/en/dev/ref/settings/#templates TEMPLATES = [ { - # See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND + # See: + # https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND "BACKEND": "django.template.backends.django.DjangoTemplates", - # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs + # See: + # https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs "DIRS": [str(APPS_DIR.path("templates"))], "OPTIONS": { - # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug + # See: + # https://docs.djangoproject.com/en/dev/ref/settings/#template-debug "debug": DEBUG, - # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders + # See: + # https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types "loaders": [ "django.template.loaders.filesystem.Loader", "django.template.loaders.app_directories.Loader", ], - # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors + # See: + # https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors "context_processors": [ "django.template.context_processors.debug", "django.template.context_processors.request", @@ -428,7 +462,8 @@ TEMPLATES = [ } ] -# See: http://django-crispy-forms.readthedocs.org/en/latest/install.html#template-packs +# See: +# http://django-crispy-forms.readthedocs.org/en/latest/install.html#template-packs CRISPY_TEMPLATE_PACK = "bootstrap3" # STATIC FILE CONFIGURATION @@ -444,12 +479,15 @@ DEFAULT_FILE_STORAGE = "funkwhale_api.common.storage.ASCIIFileSystemStorage" 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`, +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_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. @@ -462,7 +500,8 @@ AWS_S3_MAX_MEMORY_SIZE = env.int( AWS_QUERYSTRING_EXPIRE = env.int("AWS_QUERYSTRING_EXPIRE", default=3600) """ -Expiration delay, in seconds, of signatures generated when :attr:`AWS_QUERYSTRING_AUTH` is enabled. +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) @@ -486,14 +525,16 @@ if AWS_ACCESS_KEY_ID: """ 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 + 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) - """If you are using Amazon S3 to serve media directly, you will need to specify your region + """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`` @@ -502,34 +543,38 @@ if AWS_ACCESS_KEY_ID: AWS_S3_SIGNATURE_VERSION = "s3v4" 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 + 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" -# 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")),) -# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders +# See: https://docs.djangoproject.com/en/dev/ref/contrib/ +# staticfiles/#staticfiles-finders STATICFILES_FINDERS = ( "django.contrib.staticfiles.finders.FileSystemFinder", "django.contrib.staticfiles.finders.AppDirectoriesFinder", ) # MEDIA CONFIGURATION -# ------------------------------------------------------------------------------ +# ---------------------------------------------------------------------------- # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root MEDIA_ROOT = env("MEDIA_ROOT", default=str(APPS_DIR("media"))) """ -Path where media files (such as album covers or audio tracks) are stored on your system. Ensure this directory actually exists. +Path where media files (such as album covers or audio tracks) are stored +on your system. Ensure this directory actually exists. """ # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url 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. +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 @@ -537,11 +582,12 @@ ATTACHMENTS_UNATTACHED_PRUNE_DELAY = env.int( "ATTACHMENTS_UNATTACHED_PRUNE_DELAY", default=3600 * 24 ) """ -Delay in seconds before uploaded but unattached attachements are pruned from the system. +Delay, in seconds, before uploaded but unattached attachements are pruned +from the system. """ # URL Configuration -# ------------------------------------------------------------------------------ +# ---------------------------------------------------------------------------- ROOT_URLCONF = "config.urls" SPA_URLCONF = "config.spa_urls" ASGI_APPLICATION = "config.routing.application" @@ -552,7 +598,7 @@ SECURE_BROWSER_XSS_FILTER = True SECURE_CONTENT_TYPE_NOSNIFF = True # AUTHENTICATION CONFIGURATION -# ------------------------------------------------------------------------------ +# ---------------------------------------------------------------------------- AUTHENTICATION_BACKENDS = ( "funkwhale_api.users.auth_backends.ModelBackend", "funkwhale_api.users.auth_backends.AllAuthBackend", @@ -567,17 +613,20 @@ ACCOUNT_EMAIL_VERIFICATION_ENFORCE = env.bool( "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`. +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. +Note that regardless of the setting value, superusers created through the +command line will never require verification. """ ACCOUNT_EMAIL_VERIFICATION = ( "mandatory" if ACCOUNT_EMAIL_VERIFICATION_ENFORCE else "optional" ) -ACCOUNT_USERNAME_VALIDATORS = "funkwhale_api.users.serializers.username_validators" +ACCOUNT_USERNAME_VALIDATORS = \ + "funkwhale_api.users.serializers.username_validators" # Custom user app defaults # Select the correct user model @@ -605,18 +654,23 @@ OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = "users.RefreshToken" SCOPED_TOKENS_MAX_AGE = 60 * 60 * 24 * 3 # LDAP AUTHENTICATION CONFIGURATION -# ------------------------------------------------------------------------------ +# ---------------------------------------------------------------------------- AUTH_LDAP_ENABLED = env.bool("LDAP_ENABLED", default=False) """ -Wether to enable LDAP authentication. See :doc:`/installation/ldap` for more information. +Wether to enable LDAP authentication. + +See :doc:`/installation/ldap` for more information. """ if AUTH_LDAP_ENABLED: - # Import the LDAP modules here; this way, we don't need the dependency unless someone - # actually enables the LDAP support + # Import the LDAP modules here; this way, we don't need the dependency + # unless someone actually enables the LDAP support import ldap - from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion, GroupOfNamesType + from django_auth_ldap.config import \ + LDAPSearch, \ + LDAPSearchUnion, \ + GroupOfNamesType # Add LDAP to the authentication backends AUTHENTICATION_BACKENDS += ("django_auth_ldap.backend.LDAPBackend",) @@ -625,9 +679,9 @@ if AUTH_LDAP_ENABLED: AUTH_LDAP_SERVER_URI = env("LDAP_SERVER_URI") AUTH_LDAP_BIND_DN = env("LDAP_BIND_DN", default="") AUTH_LDAP_BIND_PASSWORD = env("LDAP_BIND_PASSWORD", default="") - AUTH_LDAP_SEARCH_FILTER = env("LDAP_SEARCH_FILTER", default="(uid={0})").format( - "%(user)s" - ) + AUTH_LDAP_SEARCH_FILTER = env( + "LDAP_SEARCH_FILTER", + default="(uid={0})").format("%(user)s") AUTH_LDAP_START_TLS = env.bool("LDAP_START_TLS", default=False) AUTH_LDAP_BIND_AS_AUTHENTICATING_USER = env( "AUTH_LDAP_BIND_AS_AUTHENTICATING_USER", default=False @@ -639,7 +693,9 @@ if AUTH_LDAP_ENABLED: "username:cn", "email:mail", ] - LDAP_USER_ATTR_MAP = env.list("LDAP_USER_ATTR_MAP", default=DEFAULT_USER_ATTR_MAP) + LDAP_USER_ATTR_MAP = env.list( + "LDAP_USER_ATTR_MAP", + default=DEFAULT_USER_ATTR_MAP) AUTH_LDAP_USER_ATTR_MAP = {} for m in LDAP_USER_ATTR_MAP: funkwhale_field, ldap_field = m.split(":") @@ -686,12 +742,14 @@ URL to your redis server. Examples: - ``redis://:/`` - ``redis://127.0.0.1:6379/0`` -- ``redis://:password@localhost:6379/0`` for password auth (the extra semicolon is important) +- ``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` + If you want to use Redis over unix sockets, you'll also need + to update :attr:`CELERY_BROKER_URL` """ CACHES = { @@ -735,7 +793,8 @@ CELERY_BROKER_URL = env( "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 +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: @@ -813,18 +872,26 @@ def get_user_secret_key(user): OLD_PASSWORD_FIELD_ENABLED = True AUTH_PASSWORD_VALIDATORS = [ { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" + "NAME": + "django.contrib.auth.password_validation." + "UserAttributeSimilarityValidator" }, { - "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + "NAME": + "django.contrib.auth.password_validation.MinimumLengthValidator", "OPTIONS": {"min_length": env.int("PASSWORD_MIN_LENGTH", default=8)}, }, - {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, - {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, + {"NAME": + "django.contrib.auth.password_validation.CommonPasswordValidator"}, + {"NAME": + "django.contrib.auth.password_validation.NumericPasswordValidator"}, ] -DISABLE_PASSWORD_VALIDATORS = 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. +Wether to disable password validators (length, common words, similarity with +username…) used during regitration. """ if DISABLE_PASSWORD_VALIDATORS: AUTH_PASSWORD_VALIDATORS = [] @@ -837,7 +904,8 @@ CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_CREDENTIALS = True REST_FRAMEWORK = { - "DEFAULT_PAGINATION_CLASS": "funkwhale_api.common.pagination.FunkwhalePagination", + "DEFAULT_PAGINATION_CLASS": + "funkwhale_api.common.pagination.FunkwhalePagination", "PAGE_SIZE": 25, "DEFAULT_PARSER_CLASSES": ( "rest_framework.parsers.JSONParser", @@ -863,8 +931,10 @@ REST_FRAMEWORK = { } 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. +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: @@ -874,12 +944,15 @@ if THROTTLING_ENABLED: ) THROTTLING_SCOPES = { - "*": {"anonymous": "anonymous-wildcard", "authenticated": "authenticated-wildcard"}, + "*": { + "anonymous": "anonymous-wildcard", + "authenticated": "authenticated-wildcard"}, "create": { "authenticated": "authenticated-create", "anonymous": "anonymous-create", }, - "list": {"authenticated": "authenticated-list", "anonymous": "anonymous-list"}, + "list": { + "authenticated": "authenticated-list", "anonymous": "anonymous-list"}, "retrieve": { "authenticated": "authenticated-retrieve", "anonymous": "anonymous-retrieve", @@ -926,7 +999,8 @@ THROTTLING_RATES = { "description": "Anonymous GET requests on resource lists", }, "authenticated-retrieve": { - "rate": THROTTLING_USER_RATES.get("authenticated-retrieve", "10000/hour"), + "rate": + THROTTLING_USER_RATES.get("authenticated-retrieve", "10000/hour"), "description": "Authenticated GET requests on resource detail", }, "anonymous-retrieve": { @@ -943,7 +1017,8 @@ THROTTLING_RATES = { }, "authenticated-update": { "rate": THROTTLING_USER_RATES.get("authenticated-update", "1000/hour"), - "description": "Authenticated PATCH and PUT requests on resource detail", + "description": + "Authenticated PATCH and PUTrequests on resource detail", }, "anonymous-update": { "rate": THROTTLING_USER_RATES.get("anonymous-update", "1000/day"), @@ -963,7 +1038,8 @@ THROTTLING_RATES = { "description": "Anonymous report submission", }, "authenticated-oauth-app": { - "rate": THROTTLING_USER_RATES.get("authenticated-oauth-app", "10/hour"), + "rate": + THROTTLING_USER_RATES.get("authenticated-oauth-app", "10/hour"), "description": "Authenticated OAuth app creation", }, "anonymous-oauth-app": { @@ -1013,9 +1089,10 @@ THROTTLING_RATES = { } 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. +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: @@ -1037,8 +1114,8 @@ ATOMIC_REQUESTS = False USE_X_FORWARDED_HOST = True USE_X_FORWARDED_PORT = True -# Wether we should use Apache, Nginx (or other) headers when serving audio files -# Default to Nginx +# Wether we should use Apache, Nginx (or other) headers when +# serving audio files. Defaults to Nginx REVERSE_PROXY_TYPE = env("REVERSE_PROXY_TYPE", default="nginx") """ Depending on the reverse proxy used in front of your funkwhale instance, @@ -1046,11 +1123,13 @@ 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" PROTECT_FILES_PATH = env("PROTECT_FILES_PATH", default="/_protected") """ -Which path will be used to process the internal redirection to the reverse proxy +Path to 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. @@ -1110,11 +1189,15 @@ ACCOUNT_USERNAME_BLACKLIST = [ "actor", ] + env.list("ACCOUNT_USERNAME_BLACKLIST", default=[]) """ -List of usernames that will be unavailable during registration, given as a list of strings. +List of usernames that will be unavailable during registration, +given as a list of strings. """ -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). +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) @@ -1124,8 +1207,9 @@ Default timeout for external requests. MUSIC_DIRECTORY_PATH = env("MUSIC_DIRECTORY_PATH", default=None) """ -The path on your server where Funkwhale can import files using :ref:`in-place import -`. It must be readable by the webserver and Funkwhale +The path on your server where Funkwhale can import files using +:ref:`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`` @@ -1136,9 +1220,9 @@ for this value. For non-docker installation, you can use any absolute path. .. warning:: - You need to adapt your :ref:`reverse-proxy configuration` to - serve the directory pointed by ``MUSIC_DIRECTORY_PATH`` on - ``/_protected/music`` URL. + You need to adapt your :ref:`reverse proxy configuration + ` to serve the directory pointed by + ``MUSIC_DIRECTORY_PATH`` on ``/_protected/music`` URL. """ MUSIC_DIRECTORY_SERVE_PATH = env( @@ -1148,8 +1232,9 @@ MUSIC_DIRECTORY_SERVE_PATH = env( 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:: +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 @@ -1188,14 +1273,16 @@ VERSATILEIMAGEFIELD_RENDITION_KEY_SETS = { } VERSATILEIMAGEFIELD_SETTINGS = { "create_images_on_demand": False, - "jpeg_resize_quality": env.int("THUMBNAIL_JPEG_RESIZE_QUALITY", default=95), + "jpeg_resize_quality": + env.int("THUMBNAIL_JPEG_RESIZE_QUALITY", default=95), } RSA_KEY_SIZE = 2048 # for performance gain in tests, since we don't need to actually create the # thumbnails CREATE_IMAGE_THUMBNAILS = env.bool("CREATE_IMAGE_THUMBNAILS", default=True) # we rotate actor keys at most every two days by default -ACTOR_KEY_ROTATION_DELAY = env.int("ACTOR_KEY_ROTATION_DELAY", default=3600 * 48) +ACTOR_KEY_ROTATION_DELAY = env.int( + "ACTOR_KEY_ROTATION_DELAY", default=3600 * 48) SUBSONIC_DEFAULT_TRANSCODING_FORMAT = ( env("SUBSONIC_DEFAULT_TRANSCODING_FORMAT", default="mp3") or None ) @@ -1205,13 +1292,15 @@ Default format for transcoding when using Subsonic API. # extra tags will be ignored 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. +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", default=60 * 24 * 3 ) """ -Delay, in minutes, before a remote object will be automatically refetched when accessed in the UI. +Delay, in minutes, before a remote object will be automatically refetched +when accessed in the UI. """ MODERATION_EMAIL_NOTIFICATIONS_ENABLED = env.bool( "MODERATION_EMAIL_NOTIFICATIONS_ENABLED", default=True @@ -1220,18 +1309,24 @@ MODERATION_EMAIL_NOTIFICATIONS_ENABLED = env.bool( Whether to enable email notifications to moderators and pods admins. """ 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", default=60 * 50 ) """ 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 after signup, in days, before the "support your pod" message is shown. """ -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 after signup, in days, before the "support Funkwhale" message is shown. """ @@ -1240,41 +1335,53 @@ MIN_DELAY_BETWEEN_DOWNLOADS_COUNT = env.int( "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. +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. See ``_. """ -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) """ -Wether to proxy attachment files hosted on third party pods and and servers. Keeping -this to true is recommended, to reduce leaking browsing information of your users, and -reduce the bandwidth used on remote pods. +Wether to proxy attachment files hosted on third party pods and and servers. +Keeping 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. +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. +Changing it only affects new podcasts. """ PODCASTS_RSS_FEED_REFRESH_DELAY = env.int( "PODCASTS_RSS_FEED_REFRESH_DELAY", default=60 * 60 * 24 ) """ -Delay in seconds between two fetch of RSS feeds. Reducing this mean you'll receive new episodes faster, -but will require more resources. +Delay, in seconds, between two fetch of RSS feeds. + +Reducing this mean you'll receive new episodes faster, but will require more +resources. """ # 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. """ @@ -1283,7 +1390,8 @@ IGNORE_FORWARDED_HOST_AND_PROTO = env.bool( "IGNORE_FORWARDED_HOST_AND_PROTO", default=True ) """ -Use :attr:`FUNKWHALE_HOSTNAME` and :attr:`FUNKWHALE_PROTOCOL ` instead of request header. +Use :attr:`FUNKWHALE_HOSTNAME` and :attr:`FUNKWHALE_PROTOCOL ` +instead of request header. """ HASHING_ALGORITHM = "sha256"