diff --git a/CHANGELOG b/CHANGELOG index ffd0d491c..c15693222 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3587,8 +3587,8 @@ without developping our own alternative clients for each and every platform. Most advanced Subsonic clients support offline caching of music files, playlist management and search, which makes them well-suited for nomadic use. -Please head over :doc:`users/apps` for more informations about supported clients -and user instructions. +Please see `our list of supported apps `_ +for more informations about supported clients and user instructions. At the instance-level, the Subsonic API is enabled by default, but require and additional endpoint to be added in you reverse-proxy configuration. diff --git a/api/config/settings/common.py b/api/config/settings/common.py index 3fe52fdfb..8688b9ace 100644 --- a/api/config/settings/common.py +++ b/api/config/settings/common.py @@ -125,7 +125,7 @@ else: try: FUNKWHALE_HOSTNAME = env("FUNKWHALE_HOSTNAME") """ - Hostname of your Funkwhale pod, e.g. ``mypod.audio`` + Hostname of your Funkwhale pod, e.g. ``mypod.audio``. """ FUNKWHALE_PROTOCOL = env("FUNKWHALE_PROTOCOL", default="https") @@ -309,7 +309,7 @@ DEFAULT_FROM_EMAIL = env( "DEFAULT_FROM_EMAIL", default="Funkwhale ".format(FUNKWHALE_HOSTNAME) ) """ -Name and e-mail address used to send system e-mails. +Name and email address used to send system emails. Default: ``Funkwhale `` @@ -321,17 +321,17 @@ Default: ``Funkwhale `` """ EMAIL_SUBJECT_PREFIX = env("EMAIL_SUBJECT_PREFIX", default="[Funkwhale] ") """ -Subject prefix for system e-mails. +Subject prefix for system emails. """ SERVER_EMAIL = env("SERVER_EMAIL", default=DEFAULT_FROM_EMAIL) EMAIL_CONFIG = env.email_url("EMAIL_CONFIG", default="consolemail://") """ -SMTP configuration for sending e-mails. Possible values: +SMTP configuration for sending emails. Possible values: -- ``EMAIL_CONFIG=consolemail://``: output e-mails to console (the default) -- ``EMAIL_CONFIG=dummymail://``: disable e-mail sending completely +- ``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: @@ -339,15 +339,6 @@ On a production instance, you'll usually want to use an external SMTP server: - ``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) @@ -356,7 +347,7 @@ vars().update(EMAIL_CONFIG) # See: https://docs.djangoproject.com/en/dev/ref/settings/#databases DATABASE_URL = env.db("DATABASE_URL") """ -URL to connect to the PostgreSQL database. Examples: +The URL used to connect to the PostgreSQL database. Examples: - ``postgresql://funkwhale@:5432/funkwhale`` - ``postgresql://:@:/`` @@ -371,7 +362,7 @@ 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. +The maximum time in seconds before database connections close. """ MIGRATION_MODULES = { # see https://github.com/jazzband/django-oauth-toolkit/issues/634 @@ -463,10 +454,11 @@ 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`, -it's safe to disable it. +Whether to proxy audio files through your reverse proxy. +We recommend you leave this enabled to enforce access control. + +If you're using S3 storage with :attr:`AWS_QUERYSTRING_AUTH` +enabled, it's safe to disable this setting. """ AWS_DEFAULT_ACL = env("AWS_DEFAULT_ACL", default=None) """ @@ -483,9 +475,10 @@ See: https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#can """ 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. +Whether to include signatures in S3 URLs. Signatures +are used to enforce access control. -Defaults to the inverse of :attr:`PROXY_MEDIA`. +Defaults to the opposite of :attr:`PROXY_MEDIA`. """ AWS_S3_MAX_MEMORY_SIZE = env.int( @@ -494,8 +487,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. +The time in seconds before AWS signatures expire. +Only takes effect you enable :attr:`AWS_QUERYSTRING_AUTH` """ AWS_ACCESS_KEY_ID = env("AWS_ACCESS_KEY_ID", default=None) @@ -511,7 +504,7 @@ if AWS_ACCESS_KEY_ID: """ AWS_STORAGE_BUCKET_NAME = env("AWS_STORAGE_BUCKET_NAME") """ - Bucket name of your S3 storage. + Your S3 bucket name. """ AWS_S3_CUSTOM_DOMAIN = env("AWS_S3_CUSTOM_DOMAIN", default=None) """ @@ -520,14 +513,17 @@ 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 the full URL to the storage server. Example: + set the following variable to the full URL to the storage server. + + Examples: - ``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 name in order to access files. + """ + If you're using Amazon S3 to serve media without a proxy, + you need to specify your region name to access files. Example: @@ -537,9 +533,8 @@ 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. + A directory in your S3 bucket where you store files. + Use this if you plan to share the bucket between services. """ DEFAULT_FILE_STORAGE = "funkwhale_api.common.storage.ASCIIS3Boto3Storage" @@ -560,14 +555,13 @@ STATICFILES_FINDERS = ( # 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. +The path where you store media files (such as album covers or audio tracks) +on your system. Make sure 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 +The URL from which your pod serves media files. Change this if you're hosting media files on a separate domain, or if you host Funkwhale on a non-standard port. """ FILE_UPLOAD_PERMISSIONS = 0o644 @@ -576,7 +570,7 @@ ATTACHMENTS_UNATTACHED_PRUNE_DELAY = env.int( "ATTACHMENTS_UNATTACHED_PRUNE_DELAY", default=3600 * 24 ) """ -Delay in seconds before uploaded but unattached attachements are pruned +The delay in seconds before Funkwhale prunes uploaded but detached attachments from the system. """ @@ -607,14 +601,12 @@ ACCOUNT_EMAIL_VERIFICATION_ENFORCE = env.bool( "ACCOUNT_EMAIL_VERIFICATION_ENFORCE", default=False ) """ -Determine wether users need to verify their e-mail 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 e-mails, using :attr:`EMAIL_CONFIG`. +Set whether users need to verify their email address before using your pod. Enabling this setting +is useful for reducing spam and bot accounts. To use this setting you need to configure a mail server +to send verification emails. See :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. +.. note:: + Superusers created through the command line never need to verify their email address. """ ACCOUNT_EMAIL_VERIFICATION = ( "mandatory" if ACCOUNT_EMAIL_VERIFICATION_ENFORCE else "optional" @@ -653,9 +645,9 @@ SCOPED_TOKENS_MAX_AGE = 60 * 60 * 24 * 3 # ------------------------------------------------------------------------------ AUTH_LDAP_ENABLED = env.bool("LDAP_ENABLED", default=False) """ -Wether to enable LDAP authentication. +Whether to enable LDAP authentication. -See :doc:`/installation/ldap` for more information. +See :doc:`/administrator_documentation/configuration_docs/ldap` for more information. """ if AUTH_LDAP_ENABLED: @@ -730,17 +722,18 @@ AUTOSLUG_SLUGIFY_FUNCTION = "slugify.slugify" 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: +The URL of your redis server. For example: - ``redis://:/`` - ``redis://127.0.0.1:6379/0`` - ``redis://:password@localhost:6379/0`` -for password auth (the extra semicolon is important) + +If you're using password auth (the extra slash 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 + If you want to use Redis over unix sockets, you also need to update :attr:`CELERY_BROKER_URL` """ @@ -785,11 +778,11 @@ 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 -to use a different one, or use Redis sockets to connect. +The celery task broker URL. Defaults to :attr:`CACHE_URL`. +You don't need to tweak this unless you want +to use a different server or use Redis sockets to connect. -Exemple: +Example: - ``redis://127.0.0.1:6379/0`` - ``redis+socket:///run/redis/redis.sock?virtual_host=0`` @@ -885,8 +878,8 @@ AUTH_PASSWORD_VALIDATORS = [ ] DISABLE_PASSWORD_VALIDATORS = env.bool("DISABLE_PASSWORD_VALIDATORS", default=False) """ -Wether to disable password validators (length, common words, -similarity with username…) used during regitration. +Whether to disable password validation rules during registration. +Validators include password length, common words, similarity with username. """ if DISABLE_PASSWORD_VALIDATORS: AUTH_PASSWORD_VALIDATORS = [] @@ -925,9 +918,9 @@ 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. +Whether to enable throttling (also known as rate-limiting). +We recommend you leave this enabled to improve the quality +of the service, especially on public pods . """ if THROTTLING_ENABLED: @@ -1076,9 +1069,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 app features. +Tweak this if you're hitting rate limit issues or if you want +to reduce the consumption of specific endpoints. Takes +the format ``=/``. Example: @@ -1100,35 +1094,39 @@ ATOMIC_REQUESTS = False USE_X_FORWARDED_HOST = True USE_X_FORWARDED_PORT = True -# Wether we should use Apache, Nginx (or other) headers +# Whether 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, -the API will use different kind of headers to serve audio files +Set your reverse proxy type. This changes the headers the +API uses to serve audio files. Allowed values: -Allowed values: ``nginx``, ``apache2`` +- ``nginx`` +- ``apache2`` """ 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 **DO NOT** put a slash at the end. +The path used to process internal redirection +to the reverse proxy. -You shouldn't have to tweak this. +.. important:: + + Don't insert a slash at the end of this path. """ MUSICBRAINZ_CACHE_DURATION = env.int("MUSICBRAINZ_CACHE_DURATION", default=300) """ -How long to cache MusicBrainz results, in seconds. +Length of time in seconds to cache MusicBrainz results. """ 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. +The hostname of your MusicBrainz instance. Change +this setting if you run your own server or use a mirror. +You can include a port number in the hostname. -Example: +Examples: - ``mymusicbrainz.mirror`` - ``localhost:5000`` @@ -1137,7 +1135,7 @@ Example: # Custom Admin URL, use {% url 'admin:index' %} ADMIN_URL = env("DJANGO_ADMIN_URL", default="^api/admin/") """ -Path to the Django admin area. +Path to the Django admin dashboard. Examples: @@ -1173,14 +1171,14 @@ 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 can't be used for registration. Given as a list of strings. """ 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. +Whether to enforce TLS certificate verification +when performing outgoing HTTP requests. + +Disabling this feature is not recommended. """ EXTERNAL_REQUESTS_TIMEOUT = env.int("EXTERNAL_REQUESTS_TIMEOUT", default=10) """ @@ -1189,43 +1187,43 @@ 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 api and worker processes. +The path on your server where Funkwhale places +files from in-place imports. This path needs to be +readable by the webserver and ``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. +.. important:: -.. note:: This path should not include any trailing slash. + Don’t insert a slash at the end of this path. -.. warning:: +On Docker installations, we recommend you use the default ``/music`` path. +On Debian installations you can use any absolute path. Defaults to +``/srv/funkwhale/data/music``. - You need to adapt your :ref:`reverse proxy configuration - ` to serve the directory pointed by - ``MUSIC_DIRECTORY_PATH`` on ``/_protected/music`` URL. +.. note:: + + You need to add this path to your reverse proxy configuration. + Add the directory to your ``/_protected/music`` server block. """ MUSIC_DIRECTORY_SERVE_PATH = env( "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:: +On Docker setups the value of :attr:`MUSIC_DIRECTORY_PATH` +may be different from the actual path on your server. +You can specify this path in your :file:`docker-compose.yml` file:: volumes: - - /srv/funkwhale/data/music:/music:ro + - /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. +In this case, you need to set :attr:`MUSIC_DIRECTORY_SERVE_PATH` +to ``/srv/funkwhale/data/music``. The webserver needs to be +able to read this directory. -On non-docker setup, you don't need to configure this setting. +.. important:: -.. note:: This path should not include any trailing slash. + Don’t insert a slash at the end of this path. """ # When this is set to default=True, we need to reenable migration music/0042 @@ -1236,7 +1234,7 @@ USERS_INVITATION_EXPIRATION_DAYS = env.int( "USERS_INVITATION_EXPIRATION_DAYS", default=14 ) """ -Expiration delay, in days, for user invitations. +The number of days before a user invite expires. """ VERSATILEIMAGEFIELD_RENDITION_KEY_SETS = { @@ -1266,26 +1264,27 @@ SUBSONIC_DEFAULT_TRANSCODING_FORMAT = ( env("SUBSONIC_DEFAULT_TRANSCODING_FORMAT", default="mp3") or None ) """ -Default format for transcoding when using Subsonic API. +The default format files are transcoded into when using the 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. +Extra tags are 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 +The delay in minutes before a remote object is automatically refetched when accessed in the UI. """ MODERATION_EMAIL_NOTIFICATIONS_ENABLED = env.bool( "MODERATION_EMAIL_NOTIFICATIONS_ENABLED", default=True ) """ -Whether to enable e-mail notifications to moderators and pods admins. +Whether to enable email notifications to moderators and pod admins. """ FEDERATION_AUTHENTIFY_FETCHES = True FEDERATION_SYNCHRONOUS_FETCH = env.bool("FEDERATION_SYNCHRONOUS_FETCH", default=True) @@ -1293,27 +1292,27 @@ 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. +The delay in seconds between two manual fetches of the same remote object. """ 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. +The number of days after signup before the "support your pod" message is shown. """ FUNKWHALE_SUPPORT_MESSAGE_DELAY = env.int("FUNKWHALE_SUPPORT_MESSAGE_DELAY", default=15) """ -Delay after signup, in days, before the "support Funkwhale" message is shown. +The number of days after signup before the "support Funkwhale" message is shown. """ 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. +The required number of seconds between downloads of a track +by the same IP or user to be counted separately in listen statistics. """ MARKDOWN_EXTENSIONS = env.list("MARKDOWN_EXTENSIONS", default=["nl2br", "extra"]) """ -List of markdown extensions to enable. +A list of markdown extensions to enable. See ``_. """ @@ -1323,27 +1322,28 @@ Additional TLDs to support with our markdown linkifier. """ 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. +Whether to proxy attachment files hosted on third party pods and and servers. +Leaving this set to ``true`` is recommended. This reduces the risk of leaking +user browsing information and reduces the bandwidth used on remote pods. """ 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. +By default, only people who subscribe to a podcast RSS have access +to its episodes. Switch to "instance" or "everyone" to change the default +visibility. -Switch to "instance" or "everyone" to change that. +.. note:: -Changing it only affect new podcasts. + Changing this value only affect 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. +The delay in seconds between two fetch of RSS feeds. -Reducing this mean you'll receive new episodes faster, -but will require more resources. +A lower rate means new episodes are fetched sooner, +but requires more resources. """ # maximum items loaded through XML feed PODCASTS_RSS_FEED_MAX_ITEMS = env.int("PODCASTS_RSS_FEED_MAX_ITEMS", default=250) diff --git a/changes/changelog.d/admin_docs.enhancement b/changes/changelog.d/admin_docs.enhancement new file mode 100644 index 000000000..7cdb0dc8a --- /dev/null +++ b/changes/changelog.d/admin_docs.enhancement @@ -0,0 +1 @@ +All administrator documentation has been rewritten to improve clarity and update outdated information. diff --git a/docs/admin/0.17.rst b/docs/admin/0.17.rst deleted file mode 100644 index 051506f52..000000000 --- a/docs/admin/0.17.rst +++ /dev/null @@ -1,214 +0,0 @@ -About Funkwhale 0.17 -==================== - -Funkwhale 0.17 is a special version, which contains a lot of breaking changes. - -Before doing the upgrade, please read this document carefully. - - -Overview of the changes -^^^^^^^^^^^^^^^^^^^^^^^ - - -.. note:: - - The what and why are described more thoroughly in this page: https://dev.funkwhale.audio/funkwhale/funkwhale/merge_requests/368 - -To sum it up, this release big completely changes the way audio content is managed in Funkwhale. -As you may guess, this has a huge impact on the whole project, because audio is at the -core of Funkwhale. - -Here is a side by side comparison of earlier versions and this release -to help you understand the scale of the changes: - -+----------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Before | After | Reason | -+========================================================================================+=================================================================================================+=========================================================================================================================================================================================================================================================+ -| There is one big audio library, managed at the instance level | Each user can have their own libraries (either public, private or shared at the instance level) | Managing the library at instance was cumbersome and dangerous: sharing an instance library over federation would quickly pose copyright issues, as well as opening public instances. It also made it impossible to only share a subset of the music. | -+----------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Users needed a specific permissions from instance owners to upload audio content | Users can upload music to their own libraries without any specific permissions | This change makes it easier for new users to start using Funkwhale, and for creators to share their content on the network. | -+----------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Users with permissions can upload as much content as they want in the instance library | Users have a storage quota and cannot exceed that storage | This change gives visibiliy to instance owners about their resource usage. If you host 100 users with a 1Gb quota, you know that your Funkwhale instance will not store more than 100Gb of music files. | -+----------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| N/A | Users can upload private content or share content with only specific users | This is a new feature, and we think it will enable users to upload their own music libraries to their instance, without breaking the law or putting their admins in trouble, since their media will remain private. | -+----------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Youtube Import | This feature is removed | This feature posed copyright issues and impacted the credibility of the project, so we removed it. | -+----------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Music requests | This feature is removed | Since all users can now upload content without specific permissions, we think this feature is less-likely to be useful in its current state. | -+----------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - -From a shared, instance-wide library to users libraries -------------------------------------------------------- - -As you can see, there is a big switch: in earlier versions, each instance had one big library, -that was available to all its users. This model don't scale well (especially if you put -federation on top of that), because it's an all-or-nothing choice if you want to share it. - -Starting from version 0.17, each user will be able to create personal libraries -and upload content in those, up to a configurable quota. - -Those libraries can have one of the following visibility level: - -- **Private**: only the owner of the library can access its content -- **Instance**: users from the same instance can access the library content -- **Public**: everyone (including other instances) can access the library content - -Regardless of this visibility level, library owners can also share them manually -with other users, both from the same instance or from the federation. - -We think this change will have a really positive impact: - -- Admins should be more inclined to open their instance to strangers, because copyrighted media - can be upload and shared privately -- Creators should have a better experience when joining the network, because they can now - upload their own content and share it over the federation without any admin intervention -- The federation should grow faster, because user libraries can contain copyrighted content - and be shared, without putting the admins at risk - -Accessing music ---------------- - -From an end-user perspective, you will be able to browse any artist or album or track -that is known by your instance, but you'll only be able to listen to content -that match one of those criteria: - -- The content is available is one of your libraries -- The content is available in a public library -- The content is available in one library from your instance that has a visibility level set to "instance" -- The content is available in one of the libraries you follow - -Following someone else's library is a four step process: - -1. Get the library link from its owner -2. Use this link on your instance to follow the library -3. Wait until your follow request is approved by the library owner -4. If this library is unknown on your instance, it will be scanned to import its content, which may take a few minutes - -Libraries owner can revoke follows at any time, which will effectively prevent -the ancient follower from accessing the library content. - -A brand new federation ----------------------- - -This is more "under the hood" work, but the whole federation/ActivityPub logic -was rewritten for this release. This new implementation is more spec compliant -and should scale better. - -The following activities are propagated over federation: - -- Library follow creation, accept and reject -- Audio creation and deletion -- Library deletion - -A better import UI ------------------- - -This version includes a completely new import UI which should make -file uploading less annoying. In particular, the UI updates in real-time -and has a better error reporting. - -A better import engine ----------------------- - -Funkwhale is known for its quircks during music import. Missing covers, -split albums, bad management of tracks with multiple artists, missing -data for files imported over federation, bad performance, discrepancies between -the user-provided tags and what is actually stored in the database... - -This should be greatly improved now, as the whole import logic was rewritten -from scratch. - -Import is done completely offline and no longer calls the MusicBrainz API, -except to retrieve covers if those are not embedded in the imported files. -MusicBrainz references are still stored in the database, but we rely solely -on the tags from the audio file now. - -This has two positive consequences: - -- Improved performance for both small and big imports (possibly by a factor of 10) -- More reliable import result: if your file is tagged in a specific way, we will only - use tags for the import. - -Imports from federation, command-line and UI/API all use the same code, -which should greatly reduce the bugs/discrepencies. - -Finally, the import engine now understands the difference between a track artist -and an album artist, which should put an end to the album splitting issues -for tracks that had a different artist than the album artist. - -What will break ---------------- - -If you've read until here, you can probably understand that all of these changes -comes at a cost: version 0.17 contains breaking changes, removed features and other -changes. - -The following features were removed: - -- YouTube imports: for copyright reasons, keeping this in the core was not possible -- Music requests: those are now less useful since anyone can upload content - -Also, the current federation will break, as it's absolutely not compatible -with what we've built in version 0.17, and maintaining compatibility was simply not possible. - -Apart from that, other features should work the same way as they did before. - -Migration path --------------- - -.. warning:: - - This migration is huge. Do a backup. Please. The database, and the music files. - Please. - -.. warning:: I'm not kidding. - - -Migration will be similar to previous ones, with an additional script to run that will -take care of updating existing rows in the database. Especially, this script -will be responsible to create a library for each registered user, and to -bind content imported by each one to this library. - -Libraries created this way will have a different visibility level depending of your instance configuration: - -- If your instance requires authentication to access the API / listen to music, libraries will - be marked with "instance" visibility. As a result, all users from the instance will still - be able to listen to all the music of the instance after the migration -- If your instance does not require authentication to access the API / listen to music, - libraries will be completely public, allowing anyone to access the content (including federation) - -This script will also contain other database-related operations, but the impact will remain -invisible. - - -Upgrade instructions --------------------- - -Follow instructions from https://docs.funkwhale.audio/upgrading/index.html, -then run the migrations script. - -On docker-setups:: - - # if you missed this one from a previous upgrade - docker-compose run --rm api python manage.py script create_actors --no-input - docker-compose run --rm api python manage.py script migrate_to_user_libraries --no-input - -On non docker-setups:: - - # if you missed this one from a previous upgrade - sudo -u funkwhale -H -E /srv/funkwhale/virtualenv/bin/python api/manage.py script create_actors --no-input - sudo -u funkwhale -H -E /srv/funkwhale/virtualenv/bin/python api/manage.py script migrate_to_user_libraries --no-input - -If the scripts complete without errors, your instance should be updated and ready to use :) - -.. note:: - - If you use nginx, ensure your funkwhale_proxy.conf file does not contain this: - - proxy_set_header X-Forwarded-Host $host:$server_port; - - If you have this line present, replace it with: - - proxy_set_header X-Forwarded-Host $host; - - And reload your nginx server. diff --git a/docs/admin/backup.rst b/docs/admin/backup.rst deleted file mode 100644 index 7578784dc..000000000 --- a/docs/admin/backup.rst +++ /dev/null @@ -1,79 +0,0 @@ -Backup your Funkwhale instance -============================== - -.. note:: - - Before upgrading your instance, we strongly advise you to make at least a database backup. Ideally, you should make a full backup, including the database and the media files. - - -Docker setup ------------- - -If you've followed the setup instructions in :doc:`../installation/docker`, here is the backup path: - -Multi-container installation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Backup the database -^^^^^^^^^^^^^^^^^^^ - -On docker setups, you have to ``pg_dumpall`` in container ``funkwhale_postgres_1``: - -.. code-block:: shell - - docker exec -t funkwhale_postgres_1 pg_dumpall -c -U postgres > dump_`date +%d-%m-%Y"_"%H_%M_%S`.sql - -Backup the media files -^^^^^^^^^^^^^^^^^^^^^^ - -To backup docker data volumes, as the volumes are bound mounted to the host, the ``rsync`` way would go like this: - -.. code-block:: shell - - rsync -avzhP /srv/funkwhale/data/media /path/to/your/backup/media - rsync -avzhP /srv/funkwhale/data/music /path/to/your/backup/music - - -Backup the configuration files -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -On docker setups, the configuration file is located at the root level: - -.. code-block:: shell - - rsync -avzhP /srv/funkwhale/.env /path/to/your/backup/.env - - -Non-docker setup ----------------- - -Backup the database -^^^^^^^^^^^^^^^^^^^ - -On non-docker setups, you have to ``pg_dump`` as user ``postgres``: - -.. code-block:: shell - - sudo -u postgres -H pg_dump funkwhale > /path/to/your/backup/dump_`date +%d-%m-%Y"_"%H_%M_%S`.sql - -Backup the media files -^^^^^^^^^^^^^^^^^^^^^^ - -A simple way to backup your media files is to use ``rsync``: - -.. code-block:: shell - - rsync -avzhP /srv/funkwhale/data/media /path/to/your/backup/media - rsync -avzhP /srv/funkwhale/data/music /path/to/your/backup/music - -Backup the configuration files -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - rsync -avzhP /srv/funkwhale/config/.env /path/to/your/backup/.env - -.. note:: - You may also want to backup your proxy configuration file. - - For frequent backups, you may want to use deduplication and compression to keep the backup size low. In this case, a tool like ``borg`` will be more appropriate. diff --git a/docs/admin/commands.rst b/docs/admin/commands.rst deleted file mode 100644 index f562521fe..000000000 --- a/docs/admin/commands.rst +++ /dev/null @@ -1,197 +0,0 @@ -Management commands -=================== - -User management ---------------- - -It's possible to create, remove and update users directly from the command line. - -This feature is useful if you want to experiment, automate or perform batch actions that -would be too repetitive through the web UI. - -All users-related commands are available under the ``python manage.py fw users`` namespace: - -.. code-block:: sh - - # print subcommands and help - python manage.py fw users --help - - -Creation -^^^^^^^^ - -.. code-block:: sh - - # print help - python manage.py fw users create --help - - # create a user interactively - python manage.py fw users create - - # create a user with a random password - python manage.py fw users create --username alice --email alice@email.host -p "" - - # create a user with password set from an environment variable - export FUNKWHALE_CLI_USER_PASSWORD=securepassword - python manage.py fw users create --username bob --email bob@email.host - -Additional options are available to further configure the user during creation, such as -setting permissions or user quota. Please refer to the command help. - - -Update -^^^^^^ - -.. code-block:: sh - - # print help - python manage.py fw users set --help - - # set upload quota to 500MB for alice - python manage.py fw users set --upload-quota 500 alice - - # disable confirmation prompt with --no-input - python manage.py fw users set --no-input --upload-quota 500 alice - - # make alice and bob staff members - python manage.py fw users set --staff --superuser alice bob - - # remove staff privileges from bob - python manage.py fw users set --no-staff --no-superuser bob - - # give bob moderation permission - python manage.py fw users set --permission-moderation bob - - # reset alice's password - python manage.py fw users set --password "securepassword" alice - - # reset bob's password through an environment variable - export FUNKWHALE_CLI_USER_UPDATE_PASSWORD=newsecurepassword - python manage.py fw users set bob - -Deletion -^^^^^^^^ - -.. code-block:: sh - - # print help - python manage.py fw users rm --help - - # delete bob's account, but keep a reference to their account in the database - # to prevent future signup with the same username - python manage.py fw users rm bob - - # delete alice's account, with no confirmation prompt - python manage.py fw users rm --no-input alice - - # delete alice and bob accounts, including all reference to their account - # (people will be able to signup again with their usernames) - python manage.py fw users rm --hard alice bob - - -Pruning library ---------------- - -Because Funkwhale is a multi-user and federated audio server, we don't delete any artist, album -and track objects in the database when you delete the corresponding files. - -This is on purpose, because those objects may be referenced in user playlists, favorites, -listening history or on other instances, or other users could have upload files matching -linked to those entities in their own private libraries. - -Therefore, Funkwhale has a really conservative approach and doesn't delete metadata when -audio files are deleted. - -This behaviour can be problematic in some situations though, e.g. if you imported -a lot of wrongly tagged files, then deleted the files to reimport them later. - -To help with that, we provide a management you can run on the server and that will effectively -prune you library from track, album and artist metadata that is not tied to any file: - -.. code-block:: sh - - # print help - python manage.py prune_library --help - - # prune tracks with no uploads - python manage.py prune_library --tracks - - # prune albums with no tracks - python manage.py prune_library --albums - - # prune artists with no tracks/albums - python manage.py prune_library --artists - - # prune everything (tracks, albums and artists) - python manage.py prune_library --tracks --albums --artists - -The ``prune_library`` command will not delete anything by default, and only gives -you an estimate of how many database objects would be affected by the pruning. - -Once you have reviewed the output and are comfortable with the changes, you should rerun -the command with the ``--no-dry-run`` flag to disable dry run mode and actually apply -the changes on the database. - -.. warning:: - - Running this command with ``--no-dry-run`` is irreversible. Unless you have a backup, - there will be no way to retrieve the deleted data. - -.. note:: - - The command will exclude tracks that are favorited, included in playlists or listening - history by default. If you want to include those in the pruning process as well, - add the corresponding ``--ignore-favorites``, ``--ignore-playlists`` and ``--ignore-listenings`` - flags. - -Remove obsolete files from database ------------------------------------ - -When importing using the :ref:`in-place method `, if you move or remove -in-place imported files on disk, Funkwhale will still have a reference to those files and won't -be able to serve them properly. - -To help with that, whenever you remove or move files that were previously imported -with the ``--in-place`` flag, you can run the following command:: - - python manage.py check_inplace_files - -This command will loop through all the database objects that reference -an in-place imported file, check that the file is accessible on disk, -or delete the database object if it's not. - -Once you have reviewed the output and are comfortable with the changes, you should rerun -the command with the ``--no-dry-run`` flag to disable dry run mode and actually delete the -database objects. - -.. warning:: - - Running this command with ``--no-dry-run`` is irreversible. Unless you have a backup, - there will be no way to retrieve the deleted data. - -Adding tags from tracks ------------------------ - -By default, genre tags found imported files are associated with the corresponding track. - -While you can always associate genre information with an artist or album through the web UI, -it may be tedious to do so by hand for a large number of objects. - -We offer a command you can run after an import to do this for you. It will: - -1. Find all local artists or albums with no tags -2. Get all the tags associated with the corresponding tracks -3. Associate tags that are found on all tracks to the corresponding artist or album - -..note:: - - A periodic task also runs in the background every few days to perform the same process. - -Usage: - -.. code-block:: sh - - # For albums - python manage.py fw albums add-tags-from-tracks --help - # For artists - python manage.py fw artists add-tags-from-tracks --help diff --git a/docs/admin/configuration.rst b/docs/admin/configuration.rst deleted file mode 100644 index 7fad9a929..000000000 --- a/docs/admin/configuration.rst +++ /dev/null @@ -1,340 +0,0 @@ -Instance configuration -====================== - -General configuration is achieved using two type of settings: - -- :ref:`environment variables ` and -- :ref:`instance settings `. - -.. _environment-variables: - -Environment variables ---------------------- - -Those are located in your ``.env`` file, which you should have created -during installation. A full list of available variables is given :ref:`below `. - -Options from this file are heavily commented, and usually target lower level -and technical aspects of your instance, such as database credentials. - -.. note:: - - You should restart all Funkwhale processes when you change the values - on environment variables:: - - sudo systemctl restart funkwhale.target - - -.. note:: - - Some characters are unsafe to use in configuration variables that are URLs, - such as the user and password in the database and SMTP sections. - If those variables contain such characters, they must be urlencoded, for - instance using the following command:: - - python3 -c 'import urllib.parse; print(urllib.parse.quote_plus("p@ssword")) - - See as well https://github.com/joke2k/django-environ#using-unsafe-characters-in-urls - -.. _instance-settings: - -Instance settings ------------------ - -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, -such your instance description, signup policy and so on. - -You can edit those settings directly from the web application, assuming -you have the required permissions. The URL is ``/manage/settings``, and -you will also find a link to this page in the sidebar. - -If you plan to use acoustid and external imports -(e.g. with the YouTube backends), you should edit the corresponding -settings in this interface. - -.. note:: - - If you have any issue with the web application, a management interface is also - available for those settings from :doc:`Django's administration interface `. It's - less user friendly, though, and we recommend you use the web app interface - whenever possible. - - The URL should be ``/api/admin/dynamic_preferences/globalpreferencemodel/`` (prepend your domain in front of it, of course). - - -Configuration reference ------------------------ - -Pod -^^^ - -.. autodata:: config.settings.common.FUNKWHALE_HOSTNAME - :annotation: -.. autodata:: config.settings.common.FUNKWHALE_PROTOCOL - -Database and redis -^^^^^^^^^^^^^^^^^^ - -.. 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: - -Accounts and registration -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. 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: - -Media storage and serving -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. 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 - -Audio acquisition -^^^^^^^^^^^^^^^^^ - -.. autodata:: config.settings.common.MUSIC_DIRECTORY_PATH -.. autodata:: config.settings.common.MUSIC_DIRECTORY_SERVE_PATH - -S3 Storage -^^^^^^^^^^ - -.. 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 - -API configuration -^^^^^^^^^^^^^^^^^ - -.. 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 - -Federation -^^^^^^^^^^ - -.. autodata:: config.settings.common.FEDERATION_OBJECT_FETCH_DELAY -.. autodata:: config.settings.common.FEDERATION_DUPLICATE_FETCH_DELAY - -Metadata -^^^^^^^^ - -.. autodata:: config.settings.common.TAGS_MAX_BY_OBJ -.. autodata:: config.settings.common.MUSICBRAINZ_HOSTNAME -.. autodata:: config.settings.common.MUSICBRAINZ_CACHE_DURATION - -Channels and podcasts -^^^^^^^^^^^^^^^^^^^^^ - -.. autodata:: config.settings.common.PODCASTS_RSS_FEED_REFRESH_DELAY -.. autodata:: config.settings.common.PODCASTS_RSS_FEED_MAX_ITEMS -.. autodata:: config.settings.common.PODCASTS_THIRD_PARTY_VISIBILITY - -Subsonic -^^^^^^^^ - -.. autodata:: config.settings.common.SUBSONIC_DEFAULT_TRANSCODING_FORMAT - -Email configuration -^^^^^^^^^^^^^^^^^^^ - -.. autodata:: config.settings.common.EMAIL_CONFIG - :annotation: = consolemail:// -.. autodata:: config.settings.common.DEFAULT_FROM_EMAIL - :annotation: = Funkwhale -.. autodata:: config.settings.common.EMAIL_SUBJECT_PREFIX - -Other settings -^^^^^^^^^^^^^^ - -.. autodata:: config.settings.common.INSTANCE_SUPPORT_MESSAGE_DELAY -.. autodata:: config.settings.common.FUNKWHALE_SUPPORT_MESSAGE_DELAY -.. autodata:: config.settings.common.MIN_DELAY_BETWEEN_DOWNLOADS_COUNT -.. autodata:: config.settings.common.MARKDOWN_EXTENSIONS -.. autodata:: config.settings.common.LINKIFIER_SUPPORTED_TLDS - -User permissions ----------------- - -Funkwhale's permission model works as follows: - -- Anonymous users cannot do anything unless configured specifically; -- Logged-in users can use the application, but cannot do things that affect the whole instance; -- Superusers can do anything. - -To make things more granular and allow some delegation of responsibility, -superusers can grant specific permissions to specific users. Available -permissions are: - -- **Manage instance-level settings**: users with this permission can edit instance - settings as described in :ref:`instance-settings`; -- **Manage library**: users with this permission can import new music in the - instance; -- **Manage library federation**: users with this permission can ask to federate with - other instances, and accept/deny federation requests from other instances. - -There is no dedicated interface to manage users permissions, but superusers -can login on the :doc:`Django's admin ` at ``/api/admin/`` and grant permissions -to users at ``/api/admin/users/user/``. - -Front-end settings ------------------- - -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 -on ``https://yourinstanceurl/settings.json``. - -On typical deployments, this url returns a 404 error, which is simply ignored. - -Set-up -^^^^^^ - -First, create the settings file: - -.. code-block:: shell - - cd /srv/funkwhale/ - - # create a directory for your configuration file - # you can use a different name / path of course - mkdir custom - - # populate the configuration file with default values - cat < custom/settings.json - { - "additionalStylesheets": [], - "defaultServerUrl": null - } - EOF - -Once the ``settings.json`` file is created, you will need to serve it from your reverse proxy. - -If you are using nginx, add the following snippet to your vhost configuration:: - - location /settings.json { - alias /srv/funkwhale/custom/settings.json; - } - -On Apache, add the following to your vhost configuration:: - - Alias /settings.json /srv/funkwhale/custom/settings.json - -Then, reload your reverse proxy. - -At this point, visiting ``https://yourinstanceurl/settings.json`` should serve the content -of the settings.json file. - -.. warning:: - - The settings.json file must be a valid JSON file. If you have any issue, try linting - the file with a tool such as ``_ to detect potential - syntax issues. - -Available configuration options -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Your :file:`settings.json` can contain the following options: - -+----------------------------------+--------------------+---------------------------------------+---------------------------------------------------------------+ -| Name | Type | Example value | Description | -+----------------------------------+--------------------+---------------------------------------+---------------------------------------------------------------+ -| ``additionalStylesheets`` | Array of URLs | ``["https://test/theme.css"]`` | A list of stylesheets URL (absolute or relative) | -| | | (default: ``[]``) | that the web UI should load. see the "Theming" section | -| | | | below for a detailed explanation | -| | | | | -+----------------------------------+--------------------+---------------------------------------+---------------------------------------------------------------+ -| ``defaultServerUrl`` | URL | ``"https://api.yourdomain.com"`` | The URL of the API server this front-end should | -| | | (default: ``null``) | connect with. If null, the UI will use | -| | | | the value of VUE_APP_INSTANCE_URL | -| | | | (specified during build) or fallback to the current domain | -+----------------------------------+--------------------+---------------------------------------+---------------------------------------------------------------+ - -Missing options or options with a ``null`` value in the ``settings.json`` file are ignored. - -Theming -^^^^^^^ - -To theme your Funkwhale instance, you need: - -1. A CSS file for your theme, that can be loaded by the front-end; -2. To update the value of ``additionalStylesheets`` in your settings.json file to point to your CSS file URL. - -.. code-block:: shell - - cd /srv/funkwhale/custom - nano settings.json - # append - # "additionalStylesheets": ["/front/custom/custom.css"] - # to the configuration or replace the existing value, if any - - # create a basic theming file changing the background to red - cat < custom.css - body { - background-color: red; - } - EOF - -The last step to make this work is to ensure your CSS file is served by the reverse proxy. - -On nginx, add the following snippet to your vhost config:: - - location /custom { - alias /srv/funkwhale/custom; - } - -On Apache, use the following:: - - Alias /custom /srv/funkwhale/custom - - - Options FollowSymLinks - AllowOverride None - Require all granted - - -Once done, reload your reverse proxy, refresh Funkwhale in your web browser, and you should see -a red background. - -.. note:: - - You can reference external urls as well in ``additionalStylesheets``, simply use - the full urls. Be especially careful with external urls as they may affect your users - privacy. - -.. warning:: - - Loading additional stylesheets and CSS rules can affect the performance and - usability of your instance. If you encounter issues with the interfaces and use - custom stylesheets, try to disable those to ensure the issue is not caused - by your customizations. diff --git a/docs/admin/debugging.rst b/docs/admin/debugging.rst deleted file mode 100644 index d2f0147a8..000000000 --- a/docs/admin/debugging.rst +++ /dev/null @@ -1,50 +0,0 @@ -Debugging Funkwhale -=================== - -In order to track down errors its useful to provide as many information as possible. Usually pasting -the logs should be sufficient, but there are some tools for some deeper debugging. - -Frontend Logs -------------- - -Logs and errors written by the Frontend can be accessed with Firefox. When opening the website of -your Funkwhale instance, simply hit ``Ctlr + Shift + J``. Alternatively open the Firefox Menu and open -the Browser Console in the developers menu. - -In the opening window you can see all the output. You can copy what you want to share or repeat the -failing operation to see what error occurs. - -Backend Logs ------------- - -Depending on your setup you can see the logs from our API server in different ways. - -Docker -^^^^^^ - -Simply run ``docker-compose logs --tail=100 api`` If you want continuous logs, add the ``f`` flag. - -Quick install -^^^^^^^^^^^^^ - -To get the logs, run ``journalctl -xn -u funkwhale-server`` - -Profiling ---------- - -In order to find performance issues, its possible to run API requests with activated profiling. In -order to do this, add ``funkwhale_api.common.middleware.ProfilerMiddleware`` to the environment -variable ``ADDITIONAL_MIDDLEWARES_BEFORE`` - -If enabled, simply add ``?prof`` to the request URL you want to profile. You should get an HTML-Report -of the running request. - -Memory Tracing --------------- - -Its possible to print memory traces for each API request to the API logs. In order to do this, add -``funkwhale_api.common.middleware.PymallocMiddleware`` to the environment variable -``ADDITIONAL_MODDLEWARES_BEFORE`` This adds a middleware which should not do anything by default. -Tracing can be activated by setting ``PYTHONTRACEMALLOC=1`` This might has some inpact on the -performance, please report how it goes. The Middleware now prints the top 25 memory allocations to -the API logs. diff --git a/docs/admin/django.rst b/docs/admin/django.rst deleted file mode 100644 index 1fadd62f4..000000000 --- a/docs/admin/django.rst +++ /dev/null @@ -1,79 +0,0 @@ -Using the Django Administration Backend -======================================= - -Funkwhale is being actively developed, and new features are being added to the frontend all the time. However, there are some administrative tasks that can only be undertaken in the Django Administration backend. - -.. Warning:: - Deleting items on the backend is **not** recommended. Deletions performed on the backend are permanent. If you remove something in the backend, you will need to re-add it from scratch. - -Accessing the Django Backend ----------------------------- - -To access your instance's backend, navigate to ``https://yourdomain/api/admin``. You will be prompted to log in. By default, the login details will be those of the priviliged user created during the setup process. - -Deleting Items -------------------- - -By default, deleting items in the front end removes the file from the server but **does not** delete associated entities such as artists, albums, and track data, meaning that they will still be viewable but no longer playable. Items deleted in this way will also still count on the instance statistics. To remove them completely, it is necessary to remove them from the database entirely using the Django Administration backend. - -.. Warning:: - Deleting tracks, albums, or artists will also remove them completely from any associated playlists, radios, or favorites lists. Before continuing, make sure other users on the instance are aware of the deletion(s). - -Deleting a Track -^^^^^^^^^^^^^^^^ - -* Navigate to ``https://yourdomain/api/admin/music/track`` -* Select the track(s) you wish to delete -* In the ``Action`` dropdown menu, select "Delete Selected Items" -* Click on "Go". You will be prompted to confirm the track's deletion - -Deleting an Album -^^^^^^^^^^^^^^^^^ - -* Navigate to ``https://yourdomain/api/admin/music/album`` -* Select the album(s) you wish to delete -* In the ``Action`` dropdown menu, select "Delete Selected Items" -* Click on "Go". You will be prompted to confirm the album's deletion - -.. note:: - - Deleting an album will remove all tracks associated with the album - -Deleting an Artist -^^^^^^^^^^^^^^^^^^ - -* Navigate to ``https://yourdomain/api/admin/music/artist`` -* Select the artist(s) you wish to delete -* In the ``Action`` dropdown menu, select "Delete Selected Items" -* Click on "Go". You will be prompted to confirm the artist's deletion - -.. note:: - - Deleting an artist will remove all tracks and albums associated with the artist - -Removing a Followed Library ---------------------------- - -In Funkwhale, unfollowing a library will leave the items in place but inaccessible. To completely remove them: - -* Navigate to ``https://yourdomain/api/admin/music/library/`` -* Tick the box next to the library you wish to remove -* In the ``Action`` dropdown menu, select "Delete Selected Items" -* Click on "Go". You will be prompted to confirm the library's deletion - -Adding Missing Album Art -------------------------- - -Sometimes album art can fail to appear despite music being properly tagged. When this happens, it is possible to replace the missing art. - -* Navigate to ``https://yourdomain/api/admin/music/album`` -* Search for and select the album in question -* Find the item marked "Cover" -* Click "Browse" and select the file from your computer -* Click "Save" to confirm the changes - -The album art will now be present on the frontend. - -.. note:: - - You can also clear currently loaded album art by checking the checkbox next to the current item and selecting "Clear" diff --git a/docs/admin/external-storages.rst b/docs/admin/external-storages.rst deleted file mode 100644 index d2e3e36dc..000000000 --- a/docs/admin/external-storages.rst +++ /dev/null @@ -1,206 +0,0 @@ -Using external storages to store Funkwhale content -================================================== - -By default, Funkwhale will store user-uploaded and related media such as audio files, -transcoded files, avatars and album covers on a server directory. - -However, for bigger instances or more complex deployment scenarios, you may want -to use distributed or external storages. - -S3 and S3-compatible servers ----------------------------- - -.. note:: - - This feature was released in Funkwhale 0.19 and is still considered experimental. - Please let us know if you see anything unusual while using it. - -Funkwhale supports storing media files Amazon S3 and compatible implementations such as Minio or Wasabi. - -In this scenario, the content itself is stored in the S3 bucket. Non-sensitive media such as -album covers or user avatars are served directly from the bucket. However, audio files -are still served by the reverse proxy, to enforce proper authentication. - -To enable S3 on Funkwhale, add the following environment variables:: - - AWS_ACCESS_KEY_ID= - AWS_SECRET_ACCESS_KEY= - AWS_STORAGE_BUCKET_NAME= - # 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 - # AWS_LOCATION= - - # If you use a S3-compatible storage such as minio, set the following variable - # the full URL to the storage server. Example: - # AWS_S3_ENDPOINT_URL=https://minio.mydomain.com - # AWS_S3_ENDPOINT_URL= - -Then, edit your nginx configuration. On docker setups, the file is located at ``/srv/funkwhale/nginx/funkwhale.template``, -and at ``/etc/nginx/sites-available/funkwhale.template`` on non-docker setups. - -Replace the ``location /_protected/media`` block with the following:: - - location ~ /_protected/media/(.+) { - internal; - # Needed to ensure DSub auth isn't forwarded to S3/Minio, see #932 - proxy_set_header Authorization ""; - proxy_pass $1; - } - -Add your S3 store URL to the ``img-src`` and ``media-src`` headers - -.. code-block:: shell - - add_header Content-Security-Policy "...img-src 'self' https:// data:;...media-src https:// 'self' data:"; - -Then restart Funkwhale and nginx. - -From now on, media files will be stored on the S3 bucket you configured. If you already -had media files before configuring the S3 bucket, you also have to move those on the bucket -by hand (which is outside the scope of this guide). - -.. note:: - - At the moment, we do not support S3 when using Apache as a reverse proxy. - -.. note:: - - If you are attempting to integrate your docker deployment with an existing nginx webserver, - such as the one provided by `linuxserver/swag `_ - (formerly `linuxserver/letsencrypt `_), - you may run into an issue where an additional ``Content-Security-Policy`` header appears in responses from the server, - without the newly included S3 URL values. - - In this case, you can suppress the extraneous ``Content-Security-Policy`` header by specifying it in a ``proxy_hide_header`` - `directive `_ in the ``location /`` block. - - .. code-block:: shell - - location / { - proxy_pass http://funkwhale:80; - # ... - # ... include the rest of the preset directives - # ... - proxy_hide_header Content-Security-Policy; - } - - -Serving audio files directly from the bucket -******************************************** - -Depending on your setup, you may want to serve audio files directly from the S3 bucket -instead of proxying them through Funkwhale, e.g to reduce the bandwidth consumption on your server, -or get better performance. - -You can achieve that by adding ``PROXY_MEDIA=false`` to your ``.env`` file. - -When receiving a request on the stream endpoint, Funkwhale will check for authentication and permissions, -then issue a 302 redirect to the file URL in the bucket. - -This URL is actually be visible by the client, but contains a signature valid only for one hour, to ensure -no one can reuse this URL or share it publicly to distribute unauthorized content. - -.. note:: - - If you are using Amazon S3, you will need to set your ``AWS_S3_REGION_NAME`` in the ``.env`` file to - use this feature. - -.. note:: - - Since some Subsonic clients don't support 302 redirections, Funkwhale will ignore - the ``PROXY_MEDIA`` setting and always proxy file when accessed through the Subsonic API. - - -Securing your S3 bucket -*********************** - -It's important to ensure your the root of your bucket doesn't list its content, -which is the default on many S3 servers. Otherwise, anyone could find out the true -URLs of your audio files and bypass authentication. - -To avoid that, you can set the following policy on your bucket:: - - { - "Version": "2012-10-17", - "Statement": [ - { - "Action": [ - "s3:GetObject" - ], - "Effect": "Allow", - "Principal": { - "AWS": [ - "*" - ] - }, - "Resource": [ - "arn:aws:s3:::/*" - ], - "Sid": "Public" - } - ] - } - -If you are using ``awscli``, you can store this policy in a ``/tmp/policy`` file, and -apply it using the following command:: - - aws s3api put-bucket-policy --bucket --policy file:///tmp/policy - -Troubleshooting -*************** - -No Resolver Found -^^^^^^^^^^^^^^^^^ - -Depending on your setup, you may experience the following issue when trying to stream -music directly from your S3-compatible store. - -.. code-block:: shell - - [error] 2832#2832: *1 no resolver defined to resolve [address] client: [IP], server: [servername], request: "GET API request", host: "[your_domain]", referrer: "[your_domain/library]" - -This happpens when the nginx config is unable to use your server's DNS resolver. This issue -is still under investigation, but in the meantime can be worked around by specifying a resolver -in your ``funkwhale.template`` under the ``location ~/_protected/media/(.+)`` section. - -.. code-block:: shell - - location ~ /_protected/media/(.+) { - resolver 1.1.1.1; - internal; - proxy_set_header Authorization ""; - proxy_pass $1; - } - -No Images or Media Loading -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you are serving media from an S3-compatible store, you may experience an issue where -nothing loads in the front end. The error logs in your browser may show something like -the following: - -.. code-block:: text - - Content Security Policy: The page's settings blocked the loading of a resource at https:// ("img-src") - Content Security Policy: The page's settings blocked the loading of a resource at https:// ("media-src") - -This happens when your S3 store isn't defined in the ``Content-Security-Policy`` headers -in your Nginx files. To resolve the issue, add the base URL of your S3 store to the ``img-src`` -and ``media-src`` headers and reload nginx. - -.. code-block:: shell - - add_header Content-Security-Policy "...img-src 'self' https:// data:;...media-src https:// 'self' data:"; - -Broken Images in Audio Player On Page Reload -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you are serving media directly from an S3-compatible store, you may find that images -in the queue and the player won't load after the page is refreshed. This happens if the -generated URL has expired and the authorization is no longer valid. You can extend the expiry time -using the following setting in your ``.env`` file: - -.. code-block:: shell - - # The default value is 3600 (60 mins). The maximum is 604800 (7 days) - AWS_QUERYSTRING_EXPIRE=604800 diff --git a/docs/admin/importing-music.rst b/docs/admin/importing-music.rst deleted file mode 100644 index 27e303195..000000000 --- a/docs/admin/importing-music.rst +++ /dev/null @@ -1,227 +0,0 @@ -Importing music from the server -=============================== - -Funkwhale can import music files saved on the server -assuming they are readable by the Funkwhale application. -Your music files should contain at least -``artist``, ``album`` and ``title`` tags, -but we recommend you tag extensively using a proper tool, -such as Beets or Musicbrainz Picard. - -Funkwhale supports two different import modes: - -- copy(default): files are copied into Funkwhale's internal storage. This means importing a 1GB library will result in the same amount of space being used by Funkwhale. -- :ref:`in-place ` (with ``--in-place`` flag): files are referenced in Funkwhale's DB but not copied or touched in anyway. This is useful if you have a huge library, or one that is updated by an external tool such as Beets. - -Regardless of the mode you choose, -follow the below steps to import music, -assuming your files are located in -``/srv/funkwhale/data/music``: - -.. code-block:: bash - - export LIBRARY_ID="" - python api/manage.py import_files $LIBRARY_ID "/srv/funkwhale/data/music/" --recursive --noinput - -.. note:: - You have to create a library in the Web UI to get your library ID. - Simply visit https://yourdomain/content/libraries/ to create one. - - Library IDs are part of the library url or sharing link. - For example, the library ID of - https://funkwhale.instance/content/libraries/769a2ae3-eb3d-4aff-9f94-2c4d80d5c2d1, - is 769a2bc3-eb1d-4aff-9f84-2c4d80d5c2d1 - - You can use only the first characters of the ID when calling the command, like that: - ``export LIBRARY_ID="769a2bc3"`` - -When you use docker, ``/srv/funkwhale/data/music`` is mounted from the host -to the ``/music`` directory on the container: - -.. code-block:: bash - - export LIBRARY_ID="" - docker-compose run --rm api python manage.py import_files $LIBRARY_ID "/music/" --recursive --noinput - -When you installed Funkwhale via ansible, you need to call a script instead of Python, and the folder path must be adapted accordingly: - -.. code-block:: bash - - export LIBRARY_ID="" - /srv/funkwhale/manage import_files $LIBRARY_ID "/srv/funkwhale/data/music/" --recursive --noinput - - -The import command supports several options, -check the help for details:: - - docker-compose run --rm api python manage.py import_files --help - -.. note:: - - We recommend tagging your music collection using `Picard `_ to have the best quality metadata. - -.. note:: - - This command is idempotent, - meaning you can run it multiple times on the same files - and already imported files are simply skipped. - -.. note:: - - At the moment, only Flac, OGG/Vorbis and MP3 or AIFF files with ID3 tags are supported. - - -.. _in-place-import: - -In-place import -^^^^^^^^^^^^^^^ - -By default, the CLI-importer will copy imported files to Funkwhale's internal storage. -This means importing a 1GB library will result -in the same amount of space being used by Funkwhale. - -While this behaviour has some benefits (easier backups and configuration), -it is not always the best choice, -especially if you have a huge library to import -and don't want to double your disk usage. - -The CLI importer supports an additional ``--in-place`` option -through which Funkwhale will store file paths rather than file content. - -Structure -********* - -Because imported files are not managed by Funkwhale, -we offer additional configuration options -to ensure the webserver can serve them properly: - -- :data:`MUSIC_DIRECTORY_PATH ` -- :data:`MUSIC_DIRECTORY_SERVING_PATH ` - -We recommend you symlink all your music directories into ``/srv/funkwhale/data/music`` -and run the `import_files` command from that directory. -This will make it possible to use multiple music directories -without any additional configuration on the webserver side. - -For instance, if you have an NFS share -with your music mounted at ``/media/mynfsshare``, -you can create a symlink like this:: - - ln -s /media/mynfsshare /srv/funkwhale/data/music/nfsshare - -And import music from the share:: - - export LIBRARY_ID="" - python api/manage.py import_files $LIBRARY_ID "/srv/funkwhale/data/music/nfsshare/" --recursive --noinput --in-place - -Docker -****** - -Docker setups require a bit more work, -because while the ``/srv/funkwhale/data/music`` is mounted in containers, -symlinked directories are not. - -To fix that, you can use bind mounts instead of symbolic links, -as they replicate the source directory tree. -With the previous NFS share, use this command:: - - mount --bind /media/mynfsshare /srv/funkwhale/data/music/nfsshare - -If you want to go with symlinks, -ensure each symlinked directory is mounted as a volume -as well as in your ``docker-compose.yml`` file:: - - celeryworker: - volumes: - - ./data/music:/music:ro - - ./data/media:/app/funkwhale_api/media - # add your symlinked dirs here - - /media/nfsshare:/media/nfsshare:ro - - api: - volumes: - - ./data/music:/music:ro - - ./data/media:/app/funkwhale_api/media - # add your symlinked dirs here - - /media/nfsshare:/media/nfsshare:ro - -Metadata updates -^^^^^^^^^^^^^^^^ - -When doing an import with in ``in-place`` mode, -the importer will also check and update existing entries found in the database. -For instance, if the ID3 Title tag of an existing song was updated since the last scan, Funkwhale picks up the new title. -The following fields can be updated this way: - -- Track mbid -- Track title -- Track position and disc number -- Track license and copyright -- Track genre (`from version 1.2 `_) -- Album cover -- Album title -- Album mbid -- Album release date -- Artist name -- Artist mbid -- Album artist name -- Album artist mbid - -Changes in artist name can lead to multiple artists with the same name in the database, -`this is a known issue `_ -and can be remedied by adding mbids. - -React to filesystem events with ``--watch`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you have a really big library or update it regularly, -running the ``import_files`` command by hand may not be practical. -For this use case, -the ``import_files`` command supports a ``--watch`` flag -through which it observes filesystem events instead of performing a full import. - -File creation, move, update and removal -are handled when ``--watch`` is provided: - -- Files created in the watched directory are imported immediately -- If using ``in-place`` mode, files updates trigger a metadata update on the corresponding entries -- If using ``in-place`` mode, files that are moved and known by Funkwhale will see their path updated in Funkwhale's DB -- If using ``in-place`` mode, files that are removed and known by Funkwhale will be removed from Funkwhale's DB - -Pruning dangling metadata with ``--prune`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Funkwhale is, by design, conservative with music metadata in its database. -If you remove a file from Funkwhale's DB, -the corresponding artist, album and track object won't be deleted by default. - -If you want to prune dangling metadata from the database once the ``import_files`` command is over, simply add the ``--prune`` flag. -This also works in with ``--watch``. - -Album covers -^^^^^^^^^^^^ - -Whenever possible, Funkwhale obtains album covers for tracks, -with the following precedence: - -1. The cover embedded in the audio files themeselves, if any (Flac/MP3 only) -2. Use a cover.jpg or a cover.png file from the imported track directory, if any -3. Fetch cover art from musicbrainz, assuming the file is tagged correctly - -Getting demo tracks -^^^^^^^^^^^^^^^^^^^ - -If you do not have any music on your server -but want to test the import process, -you can call the following methods -to download a few albums licenced under creative commons (courtesy of Jamendo): - -.. parsed-literal:: - - curl -L -o download-tracks.sh "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/|version|/demo/download-tracks.sh" - curl -L -o music.txt "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/|version|/demo/music.txt" - chmod +x download-tracks.sh - ./download-tracks.sh music.txt - -This will download a bunch of zip archives (one per album) -under the ``data/music`` directory and unzip their content. diff --git a/docs/admin/index.rst b/docs/admin/index.rst deleted file mode 100644 index 1c22351f9..000000000 --- a/docs/admin/index.rst +++ /dev/null @@ -1,43 +0,0 @@ -Administrator Documentation -===================================== - -This documentation is targeted at administrators of instances. This typically refers to -the person(s) responsible for running the server and managing the software on a technical -level. - -Setup Guides ------------- - -.. toctree:: - :maxdepth: 2 - - ../installation/index - configuration - importing-music - external-storages - optimization - backup - migration - uninstall - ldap - -Administration --------------- - -.. toctree:: - :maxdepth: 2 - - django - commands - url - upgrading - mrf - -Troubleshooting ---------------- - -.. toctree:: - :maxdepth: 2 - - troubleshooting - debugging diff --git a/docs/admin/ldap.rst b/docs/admin/ldap.rst deleted file mode 100644 index 862b30401..000000000 --- a/docs/admin/ldap.rst +++ /dev/null @@ -1,43 +0,0 @@ -LDAP configuration -================== - -LDAP is a protocol for providing directory services, in practice allowing a central authority for user login information. - -Funkwhale supports LDAP through the Django LDAP authentication module and by setting several configuration options. - -.. warning:: - - Note that LDAP-based users cannot change their password inside the app. - -Dependencies ------------- - -LDAP support requires some additional dependencies to enable. On the OS level both ``libldap2-dev`` and ``libsasl2-dev`` are required, and the Python modules ``python-ldap`` and ``python-django-auth-ldap`` must be installed. These dependencies are all included in the ``requirements.*`` files so deploying with those will install these dependencies by default. However, they are not required unless LDAP support is explicitly enabled. - -Environment variables ---------------------- - -LDAP authentication is configured entirely through the environment variables. The following options enable the LDAP features: - -Basic features -^^^^^^^^^^^^^^ - -- ``LDAP_ENABLED``: Set to ``True`` to enable LDAP support. Default: ``False``. -- ``LDAP_SERVER_URI``: LDAP URI to the authentication server, e.g. ``ldap://my.host:389``. -- ``LDAP_BIND_DN``: LDAP user DN to bind as to perform searches. -- ``LDAP_BIND_PASSWORD``: LDAP user password for bind DN. -- ``LDAP_SEARCH_FILTER``: The LDAP user filter, using ``{0}`` as the username placeholder, e.g. ``(|(cn={0})(mail={0}))``; uses standard LDAP search syntax. Default: ``(uid={0})``. -- ``LDAP_START_TLS``: Set to ``True`` to enable LDAP StartTLS support. Default: ``False``. -- ``LDAP_ROOT_DN``: The LDAP search root DN, e.g. ``dc=my,dc=domain,dc=com``; supports multiple entries in a space-delimited list, e.g. ``dc=users,dc=domain,dc=com dc=admins,dc=domain,dc=com``. -- ``LDAP_USER_ATTR_MAP``: A mapping of Django user attributes to LDAP values, e.g. ``first_name:givenName, last_name:sn, username:cn, email:mail``. Default: ``first_name:givenName, last_name:sn, username:cn, email:mail``. -- ``AUTH_LDAP_BIND_AS_AUTHENTICATING_USER``: Controls whether direct binding is used. Default: ``False``. - -Group features -^^^^^^^^^^^^^^ - -For details on these options, see the `Django documentation `_. Group configuration is disabled unless an ``LDAP_GROUP_DN`` is set. This is an advanced LDAP feature and most users should not need to configure these settings. - -- ``LDAP_GROUP_DN``: The LDAP group search root DN, e.g. ``ou=groups,dc=domain,dc=com``. -- ``LDAP_GROUP_FILTER``: The LDAP group filter, e.g. ``(objectClass=groupOfNames)``. -- ``LDAP_REQUIRE_GROUP``: A group users must be a part of to authenticate, e.g. ``cn=enabled,ou=groups,dc=domain,dc=com``. -- ``LDAP_DENY_GROUP``: A group users must not be a part of to authenticate, e.g. ``cn=disabled,ou=groups,dc=domain,dc=com``. diff --git a/docs/admin/migration.rst b/docs/admin/migration.rst deleted file mode 100644 index 9c23c5098..000000000 --- a/docs/admin/migration.rst +++ /dev/null @@ -1,113 +0,0 @@ -Migrating to a New Server -========================= - -Sometimes, it may be necessary or desirable to migrate your -existing Funkwhale setup to a new server. This can be helpful -if you need to boost resources or if you wish to use a different -hosting platform. - -In this guide, the existing Funkwhale setup is called the origin server, and the new setup the destination server. - -Requirements ------------- - -To get started with your new setup, you will need to have the -following: - -- `rsync `_ installed on the **destination** server -- SSH access set up between the two servers - -Non-Docker ----------- - -On the destination server, run through the :doc:`installation steps<../installation/debian>` with the exception of the following points: - -- Do not enable the extensions ``unaccent`` and ``citext`` when setting up the database; -- Do not initialize the database by applying the migrate command; -- Do not create an admin account. - -Stop all funkwhale related services on the destination server: - -.. code-block:: shell - - sudo systemctl stop funkwhale.target - -On the origin server, create a database backup: - -.. code-block:: shell - - sudo -u funkwhale pg_dump -d funkwhale > "db.dump" - -On the destination server, use rsync to fetch the contents of ``/srv/funwkhale/data/media/music/`` and ``/srv/funkwhale/data/media/`` from the origin server, as well as the database dump and the ``.env`` file: - -.. code-block:: shell - - origin = - username = - - rsync -a $username@$origin:/srv/funkwhale/data/media/ /srv/funkwhale/data/media/ - rsync -a $username@$origin:/srv/funkwhale/data/music/ /srv/funkwhale/data/music/ - - rsync -a $username@$origin:/srv/funkwhale/config/.env /srv/funkwhale/config/ - rsync -a $username@$origin:/srv/funkwhale/db.dump /srv/funkwhale/ - -On the destination server, restore the database dump: - -.. code-block:: shell - - sudo psql -d funkwhale db.dump - -Once the database has been restored, follow the database migration steps from the non-docker installation guide to complete the installation on the destination server. - -Ensure that all DNS changes have been made and start the services: - -.. code-block:: shell - - sudo systemctl start funkwhale.target - -Docker ------- - -On the destination server, run through the :doc:`installation steps<../installation/docker>` but skip the ``docker-compose run --rm api python manage.py migrate`` step. - -Stop all funkwhale related containers on the destination server. - -On the origin server, create a database backup: - -.. code-block:: shell - - docker exec -t funkwhale_postgres_1 pg_dumpall -c -U postgres > "db.dump" - -On the destination server, use rsync to fetch the contents of ``/srv/funwkhale/data/media/music`` and ``/srv/funkwhale/data/media`` from the origin server, as well as the database dump nd the ``.env`` file: - -.. code-block:: shell - - origin = - username = - - rsync -a $username@$origin:/srv/funkwhale/data/media/ /srv/funkwhale/data/media/ - rsync -a $username@$origin:/srv/funkwhale/data/music/ /srv/funkwhale/data/music/ - - rsync -a $username@$origin:/srv/funkwhale/.env /srv/funkwhale/ - rsync -a $username@$origin:/srv/funkwhale/db.dump /srv/funkwhale/ - -Initialize the Postgres container with the funkwhale database and its user. For easier, we create a db init dump file than we import in the postgres container: - -.. code-block:: shell - - echo "CREATE DATABASE "funkwhale" - WITH ENCODING 'utf8'; - CREATE USER funkwhale; - GRANT ALL PRIVILEGES ON DATABASE funkwhale TO funkwhale;" > init.dump - - docker exec -i funkwhale_postgres_1 psql -U postgres -d postgres < "init.dump" - -After that, we can restore the database dump: - -.. code-block:: shell - - docker exec -i funkwhale_postgres_1 psql -U postgres -d postgres < "db.dump" - -Once the database has been restored, run the migrations following the docker installation guide. - -Ensure that all DNS changes have been made and start the services. diff --git a/docs/admin/mrf.rst b/docs/admin/mrf.rst deleted file mode 100644 index b8d339785..000000000 --- a/docs/admin/mrf.rst +++ /dev/null @@ -1,117 +0,0 @@ -Message Rewrite Facility (MRF) -============================== - -Funkwhale includes a feature that mimics `Pleroma's Message Rewrite Facility `_. -Using the MRF, instance admins can write and configure custom and automated moderation rules -that couldn't be implemented otherwise using :doc:`our other built-in moderation tools <../moderator/index>`. - -Architecture ------------- - -The MRF is a pluggable system that will process messages and forward those to the list -of registered policies, in turn. Each policy can mutate the message, leave it as is, or discard it entirely. - -Some of our built-in moderation tools are actually implemented as a MRF policy, e.g: - -- Allow-list, when checking incoming messages (`code `__) -- Domain and user blocking, when checking incoming messages (`code `__) - -.. note:: - - While Pleroma MRF policies can also affect outgoing messages, this is not supported yet in Funkwhale. - - -Disclaimer ----------- - -Writing custom MRF can impact negatively the performance and stability of your pod, as well as message -delivery. Your policy will be called everytime a message is delivered, so ensure you don't execute -any slow operation here. - -Please note that the Funkwhale developers consider custom MRF policy modules to fall under the purview of the AGPL. As such, you are obligated to release the sources to your custom MRF policy modules upon request. - -Writing your first MRF policy ------------------------------ - -MRF Policies are written as Python 3 functions that take at least one ``payload`` parameter. -This payload is the raw ActivityPub message, received via HTTP, after the HTTP signature check. - -In the example below we write a policy that discards all Follow requests from listed domains: - -.. code-block:: python - - import urllib.parse - from funkwhale_api.moderation import mrf - - BLOCKED_FOLLOW_DOMAINS = ['domain1.com', 'botdomain.org'] - - # registering the policy is required to have it applied - # the name can be anything you want, it will appear in the mrf logs - @mrf.inbox.register(name='blocked_follow_domains') - def blocked_follow_domains_policy(payload, **kwargs): - actor_id = payload.get('actor') - domain = urllib.parse.urlparse(actor_id).hostname - if domain not in BLOCKED_FOLLOW_DOMAINS: - # raising mrf.Skip isn't strictly necessary but it provides - # for info in the debug logs. Otherwise, you can simply return - raise mrf.Skip("This domain isn't blocked") - - activity_type = payload.get('type') - object_type = payload.get('object', {}).get('type') - - if object_type == 'Follow' and activity_type == 'Create': - raise mrf.Discard('Follow from blocked domain') - - -This code must be stored in a Funkwhale plugin. To create one, just execute the following: - -.. code-block:: shell - - # plugin name must contain only ASCII letters, numbers and undercores - export PLUGIN_NAME="myplugin" - # this is the default path where Funkwhale will look for plugins - # if you want to use another path, update this path and ensure - # your PLUGINS_PATH is also included in your .env - export PLUGINS_PATH="/srv/funkwhale/plugins/" - mkdir -p $PLUGINS_PATH/$PLUGIN_NAME - cd $PLUGINS_PATH/$PLUGIN_NAME - - touch __init__.py # required to make the plugin a valid Python package - # create the required apps.py file to register our plugin in Funkwhale - cat > apps.py <` for that. - -Problems usually fall into one of those categories: - -- **Frontend**: Funkwhale's interface is not loading, not behaving as expected, music is not playing -- **API**: the interface do not display any data or show errors -- **Import**: uploaded/imported tracks are not imported correctly or at all -- **Federation**: you cannot contact other Funkwhale servers, access their library, play federated tracks -- **Everything else** - -Each category comes with its own set of diagnose tools and/or commands we will detail below. We'll also give you simple -steps for each type of problem. Please try those to see if it fix your issues. If none of those works, please report your issue on our -issue tracker. - -.. note:: - - To get detailed log messages, set the environment variable ``LOGLEVEL=debug``. - If you are using the docker setup you can configure this in the ``.env`` file. - -Backend issues -^^^^^^^^^^^^^^ - -Diagnostic tools: - -- Reverse proxy logs: - - Apache logs should be available at :file:`/var/log/apache/access.log` and :file:`/var/log/apache/error.log` - - Nginx logs should be available at :file:`/var/log/nginx/access.log` and :file:`/var/log/nginx/error.log` -- API logs: - - Docker setup: ``docker-compose logs -f --tail=50 api`` (remove the ``--tail`` flag to get the full logs) - - Non-docker setup: ``journalctl -xn -u funkwhale-server`` - -.. note:: - - If you edit your .env file to test a new configuration, you have to restart your services to pick up the changes: - - - Docker setup: ``docker-compose up -d`` - - Non-docker setup: ``systemctl restart funkwhale.target`` - -Common problems -*************** - -Instance works properly, but audio files are not served (404 error) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- If you're using docker, ensure the ``MEDIA_ROOT`` variable is commented in your env file -- Ensure the ``_protected/media`` block points toward the path where media files are stored (``/srv/funkwhale/data/media``, by default) -- If you're using in-place import, ensure :data:`MUSIC_DIRECTORY_PATH `, :data:`MUSIC_DIRECTORY_SERVE_PATH ` and :data:`REVERSE_PROXY_TYPE ` are configured properly, and that the files are readable by the webserver - -Weakref error when running ``python manage.py `` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -On Python <3.6, you may see this kind of errors when running commands like ``python manage.py migrate``:: - - Exception ignored in: .remove at 0x107e7a6a8> - Traceback (most recent call last): - File "/srv/funkwhale/venv/lib/python3.5/weakref.py", line 117, in remove - TypeError: 'NoneType' object is not callable - -This is caused by a bug in Python (cf https://github.com/celery/celery/issues/3818), and is not affecting in any way -the command you execute. You can safely ignore this error. - -``Your models have changes that are not yet reflected in a migration`` warning -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When running ``python manage.py migrate`` (both in docker or non-docker), you may end-up with this:: - - Operations to perform: - Apply all migrations: account, admin, auth, authtoken, common, contenttypes, dynamic_preferences, favorites, federation, history, music, playlists, radios, requests, sessions, sites, socialaccount, taggit, users - Running migrations: - No migrations to apply. - - Your models have changes that are not yet reflected in a migration, and so won't be applied. - Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them. - -This warning can be safely ignored. You should not run the suggested ``manage.py makemigrations`` command. - -File import issues -^^^^^^^^^^^^^^^^^^ - -Unless you are using the CLI to import files, imports are send as tasks in a queue to a celery worker that will process them. - -Diagnostic tools: - -- Celery worker logs: - - Docker setup: ``docker-compose logs -f --tail=50 celeryworker`` (remove the ``--tail`` flag to get the full logs) - - Non-docker setup: ``journalctl -xn -u funkwhale-worker`` - -Federation issues -^^^^^^^^^^^^^^^^^ - -Received federations messages are sent to a dedicated task queue and processed asynchronously by a celery worker. - -Diagnostic tools: - -- API logs: - - Docker setup: ``docker-compose logs -f --tail=50 api`` (remove the ``--tail`` flag to get the full logs) - - Non-docker setup: ``journalctl -xn -u funkwhale-server`` -- Celery worker logs: - - Docker setup: ``docker-compose logs -f --tail=50 celeryworker`` (remove the ``--tail`` flag to get the full logs) - - Non-docker setup: ``journalctl -xn -u funkwhale-worker`` - -Common problems -*************** - -I have no access to another instance library -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Check if it works with the demo library (library@demo.funkwhale.audio) -- Check if the remote library received your follow request and approved it -- Trigger a scan via the interface -- Have a look in the celery logs for potential errors during the scan - -Other problems -^^^^^^^^^^^^^^ - -It's a bit hard to give targeted advice about problems that do not fit in the previous categories. However, we can recommend to: - -- Try to identify the scope of the issue and reproduce it reliably -- Ensure your instance is configured as detailed in the installation documentation, and if you did not use the default - values, to check what you changed -- To read the .env file carefully, as most of the options are described in the comments - - -Report an issue or get help -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Well be more than happy to help you to debug installation and configuration issues. The main channel -for receiving support about your Funkwhale installation is the `#funkwhale-troubleshooting:matrix.org `_ Matrix channel. - -Before asking for help, we'd really appreciate if you took the time to go through this document and try to diagnose the problem yourself. But if you don't find -anything relevant or don't have the time, we'll be there for you! - -Here are a few recommendations on how to structure and what to include in your help requests: - -- Give us as much context as possible about your installation (OS, version, Docker/non-docker, reverse-proxy type, relevant logs and errors, etc.) -- Including screenshots or small gifs or videos can help us considerably when debugging front-end issues - -You can also open issues on our `issue tracker `_. Please have a quick look for -similar issues before doing that, and use the issue tracker only to report bugs, suggest enhancements (both in the software and the documentation) or new features. - -.. warning:: - - If you ever need to share screenshots or urls with someone else, ensure those do not include your personal token. - This token is binded to your account and can be used to connect and use your account. - - Urls that includes your token looks like: ``https://your.instance/api/v1/uploads/42/serve/?jwt=yoursecrettoken`` - -Improving this documentation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you feel like something should be improved in this document (and in the documentation in general), feel free to :doc:`contribute to the documentation <../documentation/creating>`. -If you're not comfortable contributing or would like to ask somebody else to do it, feel free to :doc:`request a change in documentation <../documentation/identifying>`. - diff --git a/docs/admin/uninstall.rst b/docs/admin/uninstall.rst deleted file mode 100644 index df85edec4..000000000 --- a/docs/admin/uninstall.rst +++ /dev/null @@ -1,89 +0,0 @@ -Uninstall Funkwhale -=================== - -The following instructions helps you remove Funkwhale from your server, for instance after migrating to another server, or if you do not want to use Funkwhale anymore. - -.. warning:: - - The following instructions cannot be undone and might result in loss of data. If necessary, please make a backup of your server following the :doc:`backup instructions`. - - Especially, it must be noted that: - - - Remote content hosted on an S3 or S3-compatible server will not be removed. - - In place imports will not be removed, provided they are located outside ``/srv/funkwhale/`` - -.. note:: - - These instructions apply only for the manual installation on Debian or Arch Linux. It matches the default setup. - -First, stop the all funkwhale related services: - -.. code-block:: shell - - sudo systemctl stop funkwhale.target - -Remove the reverse proxy configuration data and reload the reverse proxy. - -If you are using nginx: - -.. code-block:: shell - - sudo rm /etc/nginx/sites-enabled/funkwhale.conf - sudo rm /etc/nginx/sites-available/funkwhale.conf - sudo rm /etc/nginx/funkwhale_proxy.conf - - sudo systemctl reload nginx - -If you are using Apache2: - -.. code-block:: shell - - sudo rm /etc/apache2/sites-enabled/funkwhale.conf - sudo rm /etc/apache2/sites-available/funkwhale.conf - - sudo service apache2 restart - -Remove the systemd services: - -.. code-block:: shell - - sudo systemctl disable funkwhale-server - sudo systemctl disable funkwhale-worker - sudo systemctl disable funkwhale-beat - - sudo rm /etc/systemd/system/funkwhale-server.service - sudo rm /etc/systemd/system/funkwhale-worker.service - sudo rm /etc/systemd/system/funkwhale-beat.service - sudo rm /etc/systemd/system/funkwhale.target - - sudo systemctl daemon-reload - sudo systemctl reset-failed - -Then, remove the database: - -.. code-block:: shell - - sudo -u postgres psql -c 'DROP DATABASE funkwhale;' - sudo -u postgres psql -c 'DROP USER funkwhale;' - -Finally, remove the user ``funkwhale`` and all funkwhale related data, including the server and the data: - -.. code-block:: shell - - sudo userdel -r funkwhale - -.. warning:: - - The last command will remove ``/srv/funkwhale/``. On the default setup, this directory contains all user data. Please proceed cautiously! - - However, it must be noted that: - - - Remote content hosted on an S3 or S3-compatible server will not be removed. - - In place imports will not be removed, provided they are not located in the directory ``/srv/funkwhale/`` - -.. note:: - - If relevant, you might also want to: - - - remove the SSL certificates; - - remove the corresponding DNS entries. \ No newline at end of file diff --git a/docs/admin/upgrading.rst b/docs/admin/upgrading.rst deleted file mode 100644 index b9895650a..000000000 --- a/docs/admin/upgrading.rst +++ /dev/null @@ -1,199 +0,0 @@ -Upgrading your Funkwhale instance to a newer version -==================================================== - -.. note:: - - Before upgrading your instance, we strongly advise you to make at least a database backup. Ideally, you should make a full backup, including - the database and the media files. - - We're commited to make upgrade as easy and straightforward as possible, - however, Funkwhale is still in development and you'll be safer with a backup. - - -Reading the release notes -------------------------- - -Please take a few minutes to read the :doc:`../changelog`: updates should work -similarly from version to version, but some of them may require additional steps. -Those steps would be described in the version release notes. - - -Insights about new versions ---------------------------- - -Some versions may be bigger than usual, and we'll try to detail the changes -when possible. - -.. toctree:: - :maxdepth: 1 - - 0.17 - - -Docker setup ------------- - -If you've followed the setup instructions in :doc:`../installation/docker`, upgrade path is -easy: - -Mono-container installation -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Basically, you need to pull the new container image, stop and delete your existing container, -and relaunch a new one: - -To upgrade your service, change the version number of the image in ``docker-compose.yml`` with the latest release (i.e. |version|). - -Pull the new images: - -.. code-block:: shell - - docker-compose pull - -Restart the service: - -.. code-block:: shell - - docker-compose up -d - -Multi-container installation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. parsed-literal:: - # this assumes you want to upgrade to version "|version|" - export FUNKWHALE_VERSION="|version|" - -.. code-block:: shell - - cd /srv/funkwhale - # hardcode the targeted version your env file - # (look for the FUNKWHALE_VERSION variable) - nano .env - # Load your environment variables - source .env - # Download newest nginx configuration file - curl -L -o nginx/funkwhale.template "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/docker.nginx.template" - curl -L -o nginx/funkwhale_proxy.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/docker.funkwhale_proxy.conf" - # Pull the new version containers - docker-compose pull - # Apply the database migrations - docker-compose run --rm api python manage.py migrate - # Relaunch the containers - docker-compose up -d - -.. warning:: - - You may sometimes get the following warning while applying migrations:: - - "Your models have changes that are not yet reflected in a migration, and so won't be applied." - - This is a warning, not an error, and it can be safely ignored. - Never run the ``makemigrations`` command yourself. - -Upgrading the Postgres container -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -With some Funkwhale releases, it is recommended to upgrade the version of the -Postgres database server container. For example, Funkwhale 0.17 recommended -Postgres 9.4, but Funkwhale 0.18 recommends Postgres 11. When upgrading -Postgres, it is not sufficient to change the container referenced in -``docker-compose.yml``. New major versions of Postgres cannot read the databases -created by older major versions. The data has to be exported from a running -instance of the old version and imported by the new version. - -Thankfully, there is a Docker container available to automate this process. You -can use the following snippet to upgrade your database in ``./postgres``, -keeping a backup of the old version in ``./postgres-old``: - -.. code-block:: shell - - # Replace "9.4" and "11" with the versions you are migrating between. - export OLD_POSTGRES=9.4 - export NEW_POSTGRES=11 - docker-compose stop postgres - docker run --rm \ - -v $(pwd)/data/postgres:/var/lib/postgresql/${OLD_POSTGRES}/data \ - -v $(pwd)/data/postgres-new:/var/lib/postgresql/${NEW_POSTGRES}/data \ - tianon/postgres-upgrade:${OLD_POSTGRES}-to-${NEW_POSTGRES} - # Add back the access control rule that doesn't survive the upgrade - echo "host all all all trust" | sudo tee -a ./data/postgres-new/pg_hba.conf - # Swap over to the new database - mv ./data/postgres ./data/postgres-old - mv ./data/postgres-new ./data/postgres - - -Non-docker setup ----------------- - -If you installed Funkwhale using the install script, upgrading is done using ``sh -c "$(curl -sSL https://get.funkwhale.audio/upgrade.sh)"``. Make sure to run this command with root permissions. - -If you manually installed Funkwhale, please use the following instructions. - -Upgrade the static files -^^^^^^^^^^^^^^^^^^^^^^^^ - -On non-docker setups, the front-end app -is updated separately from the API. This is as simple as downloading -the zip with the static files and extracting it in the correct place. - -The following example assume your setup match :ref:`frontend-setup`. - -.. parsed-literal:: - - # this assumes you want to upgrade to version "|version|" - export FUNKWHALE_VERSION="|version|" - cd /srv/funkwhale - sudo -u funkwhale curl -L -o front.zip "https://dev.funkwhale.audio/funkwhale/funkwhale/builds/artifacts/$FUNKWHALE_VERSION/download?job=build_front" - sudo -u funkwhale unzip -o front.zip - sudo -u funkwhale rm front.zip - -Upgrading the API -^^^^^^^^^^^^^^^^^ - -On non-docker, upgrade involves a few more commands. We assume your setup -match what is described in :doc:`/installation/debian`: - -.. parsed-literal:: - - # this assumes you want to upgrade to version "|version|" - export FUNKWHALE_VERSION="|version|" - cd /srv/funkwhale - - # download more recent API files - sudo -u funkwhale curl -L -o "api-$FUNKWHALE_VERSION.zip" "https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/$FUNKWHALE_VERSION/download?job=build_api" - sudo -u funkwhale unzip "api-$FUNKWHALE_VERSION.zip" -d extracted - sudo -u funkwhale rm -rf api/ && sudo -u funkwhale mv extracted/api . - sudo -u funkwhale rm -rf extracted - sudo -u funkwhale rm api-$FUNKWHALE_VERSION.zip - - # update os dependencies - sudo api/install_os_dependencies.sh install - cd api - sudo -u funkwhale -H -E poetry install --no-dev - - # collect static files - sudo -u funkwhale -H -E poetry run python manage.py collectstatic --no-input - - # stop the services - sudo systemctl stop funkwhale.target - - # apply database migrations - sudo -u funkwhale -H -E poetry run python api/manage.py migrate - - # restart the services - sudo systemctl start funkwhale.target - -.. note:: - If you see a PermissionError when running the ``migrate`` command, try running the following commands by hand, and relaunch the migrations:: - - sudo -u postgres psql funkwhale -c 'CREATE EXTENSION IF NOT EXISTS "citext";' - sudo -u postgres psql funkwhale -c 'CREATE EXTENSION IF NOT EXISTS "unaccent";' - -.. warning:: - - You may sometimes get the following warning while applying migrations:: - - "Your models have changes that are not yet reflected in a migration, and so won't be applied." - - This is a warning, not an error, and it can be safely ignored. - Never run the ``makemigrations`` command yourself. diff --git a/docs/admin/url.rst b/docs/admin/url.rst deleted file mode 100644 index 18a552036..000000000 --- a/docs/admin/url.rst +++ /dev/null @@ -1,98 +0,0 @@ -Changing Your Instance URL -========================== - -.. DANGER:: - - We highly recommend not to change your instance URL. Members of the community tried to do this and documented their steps here. - This guide might be incomplete or fail for your instance. There is no support for this procedure and likely no way back. - -At some point, you may wish to change your instance URL. In order to -do this, you will need to change the following: - -- The instance URL in your .env file -- The instance URL in your ``/etc/nginx/sites-enabled/funkwhale.conf`` or ``/etc/apache2/sites-enabled/funkwhale.conf`` depending on your web server setup -- Any references to the old URL in your database - -The changes to the database can be achieved with the ``fix_federation_ids`` script in the ``manage.py`` -file. - -Example output: - -.. code-block:: shell - - # For Docker setups - docker-compose run --rm api python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input - - # For non-Docker setups - python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input - - # Output - Will replace 108 found occurrences of 'https://old-url' by 'https://new-url': - - - 20 music.Artist - - 13 music.Album - - 39 music.Track - - 31 music.Upload - - 1 music.Library - - 4 federation.Actor - - 0 federation.Activity - - 0 federation.Follow - - 0 federation.LibraryFollow - - Replacing on 20 music.Artist… - Replacing on 13 music.Album… - Replacing on 39 music.Track… - Replacing on 31 music.Upload… - Replacing on 1 music.Library… - Replacing on 4 federation.Actor… - Replacing on 0 federation.Activity… - Replacing on 0 federation.Follow… - Replacing on 0 federation.LibraryFollow… - -On Docker Installations ------------------------ - -If you have followed the :doc:`Docker installation instructions <../installation/docker>`, you -will need to do the following: - -- Edit your .env file to change the ``FUNKWHALE_HOSTNAME`` and ``DJANGO_ALLOWED_HOSTS`` value to your new URL -- Edit your ``/etc/nginx/sites-enabled/funkwhale.conf`` file to change the ``server_name`` values to your new URL -- Run the following command to change all mentions of your old instance URL in the database: - -.. code-block:: shell - - docker-compose run --rm api python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input - -- Restart Nginx or Apache to pick up the new changes - -.. code-block:: shell - - # For Nginx - sudo systemctl restart nginx - - # For Apache - sudo systemctl restart apache2 - -On Non-Docker Installations ---------------------------- - -If you have followed the :doc:`non-docker setup <../installation/debian>`, you will need to do the following: - -- Edit your .env file to change the ``FUNKWHALE_HOSTNAME`` and ``DJANGO_ALLOWED_HOSTS`` value to your new URL -- Edit your ``/etc/nginx/sites-enabled/funkwhale.conf`` file to change the ``server_name`` values to your new URL -- Run the following command to change all mentions of your old instance URL in the database: - -.. code-block:: shell - - python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input - -- Restart Nginx or Apache to pick up the new changes - -.. code-block:: shell - - # For Nginx - sudo systemctl restart nginx - - # For Apache - sudo systemctl restart apache2 - diff --git a/docs/administrator_documentation/configuration_docs/change_url.md b/docs/administrator_documentation/configuration_docs/change_url.md new file mode 100644 index 000000000..06b4e8aaa --- /dev/null +++ b/docs/administrator_documentation/configuration_docs/change_url.md @@ -0,0 +1,88 @@ +# Change your instance URL + +```{danger} +We recommend you don't change your instance URL. Changing it __will__ cause instability and problems with federation. If you change your URL, the Funkwhale project can't offer support for problems that arise. +``` + +Your instance URL is your pod's unique identifier in the {term}`fediverse`. If you want to change it, you need to update a lot of information + +- The instance URL in your {file}`.env` file. +- The instance URL in your vhost. +- Any references to the old URL in your database. + +To clean the database, the {file}`manage.py` script contains a `fix_federation_ids` command. + +```{warning} +Running `fix_federation_ids` with the `--no-dry-run` flag is irreversible. Make sure you [back up your data](../upgrade_docs/backup.md). +``` + +## Update your instance URL + +1. Change the `FUNKWHALE_HOSTNAME` and `DJANGO_ALLOWED_HOSTS` value in your {file}`.env` file. +2. Change the `server_name` values in your {file}`/etc/nginx/sites-enabled/funkwhale.conf` file. +3. Run the `fix_federation_ids` command to clean up your database. + + ````{tabbed} Debian + + ```{code} bash + poetry run python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input + ``` + + ```` + + ````{tabbed} Docker + + ```{code} bash + docker-compose run --rm api python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input + ``` + + ```` + + Example output: + + ``` + Will replace 108 found occurrences of 'https://old-url' by 'https://new-url': + + - 20 music.Artist + - 13 music.Album + - 39 music.Track + - 31 music.Upload + - 1 music.Library + - 4 federation.Actor + - 0 federation.Activity + - 0 federation.Follow + - 0 federation.LibraryFollow + + Replacing on 20 music.Artist… + Replacing on 13 music.Album… + Replacing on 39 music.Track… + Replacing on 31 music.Upload… + Replacing on 1 music.Library… + Replacing on 4 federation.Actor… + Replacing on 0 federation.Activity… + Replacing on 0 federation.Follow… + Replacing on 0 federation.LibraryFollow… + ``` + +4. Restart your webserver to pick up the changes. + +````{tabbed} Nginx + +```{code} bash +sudo systemctl restart nginx + +``` + + +```` + +````{tabbed} Apache + + +```{code} bash +sudo systemctl restart apache2 + +``` + + +```` diff --git a/docs/administrator_documentation/configuration_docs/env_file.md b/docs/administrator_documentation/configuration_docs/env_file.md new file mode 100644 index 000000000..01e809d05 --- /dev/null +++ b/docs/administrator_documentation/configuration_docs/env_file.md @@ -0,0 +1,277 @@ +# Customize your environment file + +Your `.env` (environment) file contains variables you can change to customize your pod. You can change these variables at any time to alter how your pod runs. + +You need to restart your Funkwhale services after changing your `.env` file. + +````{tabbed} Debian + + ```{code} bash + sudo systemctl restart funkwhale.target + ``` + +```` + +````{tabbed} Docker + + ```{code} bash + docker-compose restart + ``` + +```` + +## Variables + +````{important} + +Some environment variables accept a URL as a value. To encode URLs and avoid problems with special characters, use `urllib.parse` on your URL value. + + ```py + python3 -c 'import urllib.parse; print(urllib.parse.quote_plus("p@ssword")) + ``` + + ```{seealso} + The [django-environ documentation](https://github.com/joke2k/django-environ/blob/main/docs/tips.rst#using-unsafe-characters-in-urls). + ``` + +```` + +### Pod configuration + +```{eval-rst} +.. autodata:: config.settings.common.FUNKWHALE_HOSTNAME + :annotation: = mypod.audio +.. autodata:: config.settings.common.FUNKWHALE_PROTOCOL + :annotation: = https +``` + +### Database and redis configuration + +```{eval-rst} +.. autodata:: config.settings.common.DATABASE_URL + :annotation: = postgresql://:@:/ +.. autodata:: config.settings.common.DB_CONN_MAX_AGE +.. autodata:: config.settings.common.CACHE_URL + :annotation: = redis://:/ +.. autodata:: config.settings.common.CELERY_BROKER_URL + :annotation: = redis://127.0.0.1:6379/0 +``` + +### Accounts and registration + +```{eval-rst} + +.. autodata:: config.settings.common.ACCOUNT_EMAIL_VERIFICATION_ENFORCE + :annotation: = true +.. autodata:: config.settings.common.USERS_INVITATION_EXPIRATION_DAYS + :annotation: = 7 +.. autodata:: config.settings.common.DISABLE_PASSWORD_VALIDATORS + :annotation: = true +.. autodata:: config.settings.common.ACCOUNT_USERNAME_BLACKLIST + :annotation: = test,funkwhale +``` + +```{py:data} LDAP_ENABLED +--- +value: false +--- + +Whether to enable LDAP authentication. + +See {doc}`/administrator_documentation/configuration_docs/ldap` for more information. + +``` + +### Media storage and serving configuration + +```{eval-rst} + +.. autodata:: config.settings.common.MEDIA_URL + :annotation: = https://mypod.audio/media/ +.. autodata:: config.settings.common.MEDIA_ROOT + :annotation: = /srv/funkwhale/data/media +.. autodata:: config.settings.common.PROXY_MEDIA + :annotation: = true +.. autodata:: config.settings.common.EXTERNAL_MEDIA_PROXY_ENABLED + :annotation: = false +.. autodata:: config.settings.common.ATTACHMENTS_UNATTACHED_PRUNE_DELAY + :annotation: = true +.. autodata:: config.settings.common.REVERSE_PROXY_TYPE + :annotation: = nginx +.. autodata:: config.settings.common.PROTECT_FILES_PATH + :annotation: = /_protected + +``` + +### S3 storage configuration + +```{eval-rst} + +.. autodata:: config.settings.common.AWS_QUERYSTRING_AUTH +.. autodata:: config.settings.common.AWS_QUERYSTRING_EXPIRE +.. autodata:: config.settings.common.AWS_ACCESS_KEY_ID +.. autodata:: config.settings.common.AWS_SECRET_ACCESS_KEY +.. autodata:: config.settings.common.AWS_STORAGE_BUCKET_NAME +.. autodata:: config.settings.common.AWS_S3_CUSTOM_DOMAIN +.. autodata:: config.settings.common.AWS_S3_ENDPOINT_URL + :annotation: = https://minio.mydomain.com +.. autodata:: config.settings.common.AWS_S3_REGION_NAME + :annotation: = eu-west-2 +.. autodata:: config.settings.common.AWS_LOCATION + :annotation: = funkwhale_music + +``` + +### In-place import configuration + +```{eval-rst} + +.. autodata:: config.settings.common.MUSIC_DIRECTORY_PATH + :annotation: = /srv/funkwhale/data/music +.. autodata:: config.settings.common.MUSIC_DIRECTORY_SERVE_PATH + :annotation: = /srv/funkwhale/data/music + +``` + +### API configuration + +```{eval-rst} + +.. autodata:: config.settings.common.THROTTLING_ENABLED +.. autodata:: config.settings.common.THROTTLING_RATES + :annotation: = signup=5/d,password-reset=2/d,anonymous-reports=5/d + +``` + +```{dropdown} Standard endpoints + +| Endpoint name | Description | Default rate (per user) | +|---------------------------|----------------------------------------------------------|-------------------------| +| `anonymous-wildcard` | Anonymous requests not covered by other limits | 1000 per hour | +| `authenticated-wildcard` | Authenticated requests not covered by other limits | 2000 per hour | +| `authenticated-create` | Authenticated POST requests | 1000 per hour | +| `anonymous-create` | Anonymous POST requests | 1000 per day | +| `authenticated-list` | Authenticated GET requests | 10000 per hour | +| `anonymous-list` | Anonymous GET requests | 10000 per day | +| `authenticated-retrieve` | Authenticated GET requests on resource details | 10000 per hour | +| `anonymous-retrieve` | Anonymous GET requests on resource details | 10000 per day | +| `authenticated-destroy` | Authenticated DELETE requests on resource details | 500 per hour | +| `anonymous-destroy` | Anonymous DELETE requests on resource details | 1000 per day | +| `authenticated-update` | Authenticated PATCH and PUT requests on resource details | 1000 per hour | +| `anonymous-update` | Anonymous PATCH and PUT requests on resource details | 1000 per day | +| `subsonic` | All Subsonic API requests | 2000 per hour | + +``` + +```{dropdown} User action endpoints + +| Endpoint name | Description | Default rate (per user) | +|---------------------------|----------------------------------------------------------|-------------------------| +| `login` | User login | 30 per hour | +| `signup` | User signup | 10 per day | +| `verify-email` | Email address confirmation | 20 per hour | +| `password-change` | Password change (when authenticated) | 20 per hour | +| `password-reset` | Password reset request | 20 per hour | +| `password-reset-confirm` | Password reset confirmation | 20 per hour | +| `fetch` | Fetch remote objects | 200 per day | + +``` + +```{dropdown} Dangerous endpoints + +| Endpoint name | Description | Default rate (per user) | +|---------------------------|----------------------------------------------------------|-------------------------| +| `authenticated-reports` | Authenticated report submissions | 100 per day | +| `anonymous-reports` | Anonymous report submissions | 10 per day | +| `authenticated-oauth-app` | Authenticated OAuth app creation | 10 per hour | +| `anonymous-oauth-app` | Anonymous OAuth app creation | 10 per day | +| `oauth-authorize` | OAuth app authorization | 100 per hour | +| `oauth-token` | OAuth token creation | 100 per hour | +| `oauth-revoke-token` | OAuth token deletion | 100 per hour | + +``` + +```{eval-rst} + +.. autodata:: config.settings.common.ADMIN_URL +.. autodata:: config.settings.common.EXTERNAL_REQUESTS_VERIFY_SSL +.. autodata:: config.settings.common.EXTERNAL_REQUESTS_TIMEOUT + +``` + +### Federation configuration + +```{eval-rst} + +.. autodata:: config.settings.common.FEDERATION_OBJECT_FETCH_DELAY +.. autodata:: config.settings.common.FEDERATION_DUPLICATE_FETCH_DELAY + +``` + +### Metadata configuration + +```{eval-rst} + +.. autodata:: config.settings.common.TAGS_MAX_BY_OBJ +.. autodata:: config.settings.common.MUSICBRAINZ_HOSTNAME +.. autodata:: config.settings.common.MUSICBRAINZ_CACHE_DURATION + +``` + +### Channels and podcast configuration + +```{eval-rst} + +.. autodata:: config.settings.common.PODCASTS_RSS_FEED_REFRESH_DELAY +.. autodata:: config.settings.common.PODCASTS_RSS_FEED_MAX_ITEMS +.. autodata:: config.settings.common.PODCASTS_THIRD_PARTY_VISIBILITY + +``` + +### Subsonic configuration + +```{eval-rst} + +.. autodata:: config.settings.common.SUBSONIC_DEFAULT_TRANSCODING_FORMAT + +``` + +### Email configuration + +```{eval-rst} + +.. autodata:: config.settings.common.EMAIL_CONFIG + :annotation: = consolemail:// +.. autodata:: config.settings.common.DEFAULT_FROM_EMAIL + :annotation: = Funkwhale +.. autodata:: config.settings.common.EMAIL_SUBJECT_PREFIX + +``` + +### Plugin configuration + +```{eval-rst} + +.. autodata:: config.settings.common.FUNKWHALE_PLUGINS_PATH + +``` + +```{py:data} FUNKWHALE_PLUGINS +--- +value: "['funkwhale_api.contrib.scrobbler', 'funkwhale_api.contrib.listenbrainz', 'funkwhale_api.contrib.maloja']" +--- + +List of Funkwhale plugins to load. +``` + +### Other settings + +```{eval-rst} + +.. autodata:: config.settings.common.INSTANCE_SUPPORT_MESSAGE_DELAY +.. autodata:: config.settings.common.FUNKWHALE_SUPPORT_MESSAGE_DELAY +.. autodata:: config.settings.common.MIN_DELAY_BETWEEN_DOWNLOADS_COUNT +.. autodata:: config.settings.common.MARKDOWN_EXTENSIONS +.. autodata:: config.settings.common.LINKIFIER_SUPPORTED_TLDS + +``` diff --git a/docs/administrator_documentation/configuration_docs/frontend.md b/docs/administrator_documentation/configuration_docs/frontend.md new file mode 100644 index 000000000..b0095be67 --- /dev/null +++ b/docs/administrator_documentation/configuration_docs/frontend.md @@ -0,0 +1,137 @@ +# Customize the Funkwhale frontend + +You can customize the look and behavior of the Funkwhale UI using a JSON configuration file. This file enables you to make very basic changes to the Funkwhale web app. + +## Set up your custom configuration + +### Create your configuration file + +To customize your Funkwhale pod, you need to serve a {file}`settings.json` file at `https://yourinstanceurl/settings.json`. Follow these steps to set up your configuration file: + +1. SSH into your Funkwhale server. +2. Navigate to your `/srv/funkwhale` folder + + ```{code} bash + cd /srv/funkwhale + ``` + +3. Create a new `custom` directory for your file. + + ```{code} bash + mkdir custom + ``` + +4. Create a new config file and populate it with placeholder settings. + + ```{code} bash + cat < custom/settings.json + { + "additionalStylesheets": [], + "defaultServerUrl": null + } + EOF + ``` + +```{dropdown} Supported parameters + +| Parameter | Data type | Description | Example | +|-------------------------|------------|-----------------------------------------------------------------------------------------------|--------------------------------| +| `additionalStylesheets` | Array | A list of URLs (relative or absolute) pointing to stylesheets. | `["https://test/theme.css"]` | +| `defaultServerUrl` | URL | The URL of the API server you want to connect the frontend to. Defaults to the current domain | `"https://api.yourdomain.com"` | + +``` + +### Configure your reverse proxy + +Once you've created your {file}`settings.json` file you need to configure your reverse proxy to serve it. + +````{tabbed} Nginx + +Add the following snippet to your {file}`/etc/nginx/sites-available/funkwhale.conf` config file: + +``` +location /settings.json { + alias /srv/funkwhale/custom; +} +``` + +```` + +````{tabbed} Apache + +Add the following snippet to your vhost configuration: + +``` +Alias /settings.json /srv/funkwhale/custom/settings.json +``` + +```` + +Reload your webserver. You should be able to see the contents of your configuration file at `https://yourinstanceurl/settings.json`. + +## Add a custom theme + +You can use a custom stylesheet to theme your Funkwhale pod. To do this: + +1. Navigate to your {file}`/srv/funkwhale/custom` directory. + + ```{code} bash + cd /srv/funkwhale/custom + ``` + +2. Copy your CSS file to this directory, or create a new one. + + ```{code} bash + # A basic CSS file. Turns the pod's background red. + + cat < custom.css + body { + background-color: red; + } + EOF + ``` + +3. Add the location of your CSS file to the `additionalStylesheets` parameter in your {file}`settings.json` file. + + ```{code} bash + nano settings.json + + # Add ["/front/custom/custom.css"] to the additionalStylesheets parameter + # The resulting file looks like this: + # { + # "additionalStylesheets": ["/front/custom/custom.css"], + # "defaultServerUrl": null + # } + ``` + +4. Add the whole {file}`custom` dir to your vhost configuration. + + ````{tabbed} Nginx + + Add the following to your {file}`/etc/nginx/sites-available/funkwhale.conf` file: + + ``` + location /custom { + alias /srv/funkwhale/custom; + } + ``` + ```` + + ````{tabbed} Apache + + Add the following to your vhost file. + + ``` + Alias /custom /srv/funkwhale/custom + + + Options FollowSymLinks + AllowOverride None + Require all granted + + ``` + ```` + +5. Restart your webserver. + +Refresh your Funkwhale app. The background should now be red. diff --git a/docs/administrator_documentation/configuration_docs/index.md b/docs/administrator_documentation/configuration_docs/index.md new file mode 100644 index 000000000..bc5ebecf7 --- /dev/null +++ b/docs/administrator_documentation/configuration_docs/index.md @@ -0,0 +1,20 @@ +# Configure your Funkwhale pod + +You can customize a lot of settings relating to your Funkwhale pod. These range from server-level settings to user-specific settings. Check out the guides in this section to get started. + +```{toctree} +--- +caption: Configuration options +maxdepth: 1 +--- + +Environment file +Instance settings +object_storage +Frontend customization +optimize +ldap +change_url +mrf + +``` diff --git a/docs/administrator_documentation/configuration_docs/instance_settings.md b/docs/administrator_documentation/configuration_docs/instance_settings.md new file mode 100644 index 000000000..1c06bebf2 --- /dev/null +++ b/docs/administrator_documentation/configuration_docs/instance_settings.md @@ -0,0 +1,211 @@ +# Instance settings + +You can find instance settings on your pod's web interface. These settings control high level pod configuration. You don't need to restart the pod after changing these settings. + +To find your instance settings: + +```{tabbed} Desktop + +1. Log in to your {term}`pod`. +2. Select the wrench icon ({fa}`wrench`) at the top of the sidebar to open the {guilabel}`Administration` menu. +3. Select {guilabel}`Settings`. The {guilabel}`Instance settings` page opens. +``` + +```{tabbed} Mobile + +1. Log in to your {term}`pod`. +2. Select the wrench icon ({fa}`wrench`) at the top of the page to open the {guilabel}`Administration` menu. +3. Select {guilabel}`Settings`. The {guilabel}`Instance settings` page opens. + +``` + +## Available settings + +### Instance information + +```{glossary} + +Pod name + The public name of your Funkwhale pod. This is displayed on the "Home" and "About" pages. + +Short description + A short description of your pod. Users see this on the pod's "Home" page. + +Long description + A longer description of your pod. Users see this on the pod's "About" page. Supports markdown formatting. + +Contact email + A contact email address that users and visitors can use to contact the pod administrator. + +Rules + A free text field for you to add your pod's rules and code of conduct. This is seen on the pod's "About" page. Supports markdown formatting + +Terms of service + A free text field for you to add your pod's terms of service and privacy policy. This is seen on the pod's "About" page. Supports markdown formatting. + +Banner image + A large image seen on the pod's "Home" and "About" pages. The image should be at least 600x100px. + +Support message + A short message you can display to your pod's users to ask for support or just send a periodic message. Supports markdown. + +``` + +--- + +### Sign-ups + +```{glossary} + +Open registration to new users + Enable this setting to allow new users to create an account on your pod. + +Enable manual sign-up validation + Enable this setting to require all new registrations to be validated by a moderator. + +Sign-up form customization + Use this tool to create a custom sign-up form. New users see this form when creating a new account. Supports markdown + +``` + +--- + +### Security + +````{glossary} + +API Requires authentication + Controls whether {term}`unauthenticated users ` can access content on your pod. If __enabled__, users need to have an account on your pod to access content. If __disabled__, users without an account can listen to content stored in public libraries. + + ```{seealso} + {doc}`../../moderator_documentation/content/library_visibility`. + ``` + +Default permissions + A list of {term}`permissions` that are added to users by default. If your pod is publicly accessible, you should leave this empty. + +Upload quota + The default upload quota for users in MB. You can override this on a per-user basis. + + ```{seealso} + {doc}`../../moderator_documentation/reports/handle_users` + ``` + +```` + +--- + +### Music + +```{glossary} + +Transcoding enabled + Enable this setting to let your server transcode files into a different format if the client requests it. This is useful if a device doesn't support formats like Ogg or FLAC. + +Transcoding cache duration + The number of minutes you want to store transcoded files on your server. Funkwhale removes transcoded tracks that haven't been downloaded within this duration to save space. + +``` + +### Channels + +```{glossary} + +Enable channels + Whether user channels can be created and followed on your pod. + +Max channels allowed per user + The maximum number of channels each user can create. + +``` + +--- + +### Playlists + +```{glossary} + +Max tracks per playlist + The maximum number of tracks a user can add to a playlist. + +``` + +--- + +### Moderation + +```{glossary} + +Enable allow-listing + Enable this setting to ensure your pod only communicates with pods you have added to your allow list. When this setting is disabled, your pod will communicate with all other servers not included in your deny list. + +Publish your allowed-domains list + Whether to make your list of allowed domains public. Enable this if you want users to check who you are federating with. + +Accountless report categories + A list of {term}`categories ` that {term}`anonymous` users can submit. + +``` + +--- + +### Federation + +```{glossary} + +Federation enabled + Whether to enable federation features on your pod. + +Enable public index + Whether to allow other pods and bots to index public content on your pod. + +Federation collection page size + The number of items to display in ActivityPub collections. + +Music cache duration + The number of minutes you want to store local copies of federated tracks on your server. Funkwhale removes federated tracks that haven't been downloaded within this duration to save space. + +Federation actor fetch delay + The number of minutes the server waits before refetching actors on request authentication. + +``` + +--- + +### Subsonic + +```{glossary} + +Enabled Subsonic API + Whether to enable the Subsonic API. This controls whether users are able to connect to your pod using Subsonic apps. + +``` + +--- + +### User Interface + +```{glossary} + +Custom CSS code + Add CSS rules to control the look and feel of your pod. These rules are added to a `