diff --git a/api/funkwhale_api/federation/actors.py b/api/funkwhale_api/federation/actors.py
index a0e23d12f864c9ef29fc1b39e3bd1819e0cb9c62..7a209b1ff4cca48028a094685bff8eb258652f89 100644
--- a/api/funkwhale_api/federation/actors.py
+++ b/api/funkwhale_api/federation/actors.py
@@ -12,6 +12,7 @@ from rest_framework.exceptions import PermissionDenied
 
 from dynamic_preferences.registries import global_preferences_registry
 
+from funkwhale_api.common import preferences
 from funkwhale_api.common import session
 from funkwhale_api.common import utils as funkwhale_utils
 from funkwhale_api.music import models as music_models
@@ -55,7 +56,7 @@ def get_actor(actor_url):
     except models.Actor.DoesNotExist:
         actor = None
     fetch_delta = datetime.timedelta(
-        minutes=settings.FEDERATION_ACTOR_FETCH_DELAY)
+        minutes=preferences.get('federation__actor_fetch_delay'))
     if actor and actor.last_fetch_date > timezone.now() - fetch_delta:
         # cache is hot, we can return as is
         return actor
@@ -225,7 +226,7 @@ class LibraryActor(SystemActor):
 
     @property
     def manually_approves_followers(self):
-        return settings.FEDERATION_MUSIC_NEEDS_APPROVAL
+        return preferences.get('federation__music_needs_approval')
 
     @transaction.atomic
     def handle_create(self, ac, sender):
diff --git a/api/funkwhale_api/federation/dynamic_preferences_registry.py b/api/funkwhale_api/federation/dynamic_preferences_registry.py
index 43877c75c9717eda3c46c0f039366803aadd77c9..e86b9f6f2b8b30da1c82145ef288e591449aa9f3 100644
--- a/api/funkwhale_api/federation/dynamic_preferences_registry.py
+++ b/api/funkwhale_api/federation/dynamic_preferences_registry.py
@@ -3,6 +3,7 @@ from django.forms import widgets
 from dynamic_preferences import types
 from dynamic_preferences.registries import global_preferences_registry
 
+from funkwhale_api.common import preferences
 federation = types.Section('federation')
 
 
@@ -18,3 +19,53 @@ class MusicCacheDuration(types.IntPreference):
         'locally? Federated files that were not listened in this interval '
         'will be erased and refetched from the remote on the next listening.'
     )
+
+
+@global_preferences_registry.register
+class Enabled(preferences.DefaultFromSettingMixin, types.BooleanPreference):
+    section = federation
+    name = 'enabled'
+    setting = 'FEDERATION_ENABLED'
+    verbose_name = 'Federation enabled'
+    help_text = (
+        'Use this setting to enable or disable federation logic and API'
+        ' globally'
+    )
+
+
+@global_preferences_registry.register
+class CollectionPageSize(
+        preferences.DefaultFromSettingMixin, types.IntPreference):
+    section = federation
+    name = 'collection_page_size'
+    setting = 'FEDERATION_COLLECTION_PAGE_SIZE'
+    verbose_name = 'Federation collection page size'
+    help_text = (
+        'How much items to display in ActivityPub collections'
+    )
+
+
+@global_preferences_registry.register
+class ActorFetchDelay(
+        preferences.DefaultFromSettingMixin, types.IntPreference):
+    section = federation
+    name = 'actor_fetch_delay'
+    setting = 'FEDERATION_ACTOR_FETCH_DELAY'
+    verbose_name = 'Federation actor fetch delay'
+    help_text = (
+        'How much minutes to wait before refetching actors on '
+        'request authentication'
+    )
+
+
+@global_preferences_registry.register
+class MusicNeedsApproval(
+        preferences.DefaultFromSettingMixin, types.BooleanPreference):
+    section = federation
+    name = 'music_needs_approval'
+    setting = 'FEDERATION_MUSIC_NEEDS_APPROVAL'
+    verbose_name = 'Federation music needs approval'
+    help_text = (
+        'When true, other federation actors will require your approval'
+        ' before being able to browse your library.'
+    )
diff --git a/api/funkwhale_api/federation/permissions.py b/api/funkwhale_api/federation/permissions.py
index c6f0660b198e88037e0480a0e88fa4cbadb7ad9d..438b675cb300a6ba1607e24c639189224488cced 100644
--- a/api/funkwhale_api/federation/permissions.py
+++ b/api/funkwhale_api/federation/permissions.py
@@ -2,13 +2,14 @@ from django.conf import settings
 
 from rest_framework.permissions import BasePermission
 
+from funkwhale_api.common import preferences
 from . import actors
 
 
 class LibraryFollower(BasePermission):
 
     def has_permission(self, request, view):
-        if not settings.FEDERATION_MUSIC_NEEDS_APPROVAL:
+        if not preferences.get('federation__music_needs_approval'):
             return True
 
         actor = getattr(request, 'actor', None)
diff --git a/api/funkwhale_api/federation/views.py b/api/funkwhale_api/federation/views.py
index 381f87eff2e90f4a64feade856756044393d4f4d..9b51a534df506169be39b66d75becca94bb5d90c 100644
--- a/api/funkwhale_api/federation/views.py
+++ b/api/funkwhale_api/federation/views.py
@@ -13,6 +13,7 @@ from rest_framework import viewsets
 from rest_framework.decorators import list_route, detail_route
 from rest_framework.serializers import ValidationError
 
+from funkwhale_api.common import preferences
 from funkwhale_api.common import utils as funkwhale_utils
 from funkwhale_api.common.permissions import HasModelPermission
 from funkwhale_api.music.models import TrackFile
@@ -33,7 +34,7 @@ from . import webfinger
 
 class FederationMixin(object):
     def dispatch(self, request, *args, **kwargs):
-        if not settings.FEDERATION_ENABLED:
+        if not preferences.get('federation__enabled'):
             return HttpResponse(status=405)
         return super().dispatch(request, *args, **kwargs)
 
@@ -136,7 +137,8 @@ class MusicFilesViewSet(FederationMixin, viewsets.GenericViewSet):
         if page is None:
             conf = {
                 'id': utils.full_url(reverse('federation:music:files-list')),
-                'page_size': settings.FEDERATION_COLLECTION_PAGE_SIZE,
+                'page_size': preferences.get(
+                    'federation__collection_page_size'),
                 'items': qs,
                 'item_serializer': serializers.AudioSerializer,
                 'actor': library,
@@ -150,7 +152,7 @@ class MusicFilesViewSet(FederationMixin, viewsets.GenericViewSet):
                 return response.Response(
                     {'page': ['Invalid page number']}, status=400)
             p = paginator.Paginator(
-                qs, settings.FEDERATION_COLLECTION_PAGE_SIZE)
+                qs, preferences.get('federation__collection_page_size'))
             try:
                 page = p.page(page_number)
                 conf = {
diff --git a/api/funkwhale_api/music/tasks.py b/api/funkwhale_api/music/tasks.py
index aaaa2cdca12539808b6bf1554a946d4dfbb9ae30..4509c9a57e6faf11b63d21c98af189a940c30677 100644
--- a/api/funkwhale_api/music/tasks.py
+++ b/api/funkwhale_api/music/tasks.py
@@ -2,8 +2,7 @@ import os
 
 from django.core.files.base import ContentFile
 
-from dynamic_preferences.registries import global_preferences_registry
-
+from funkwhale_api.common import preferences
 from funkwhale_api.federation import activity
 from funkwhale_api.federation import actors
 from funkwhale_api.federation import models as federation_models
@@ -80,8 +79,7 @@ def _do_import(import_job, replace=False, use_acoustid=True):
     acoustid_track_id = None
     duration = None
     track = None
-    manager = global_preferences_registry.manager()
-    use_acoustid = use_acoustid and manager['providers_acoustid__api_key']
+    use_acoustid = use_acoustid and preferences.get('providers_acoustid__api_key')
     if not mbid and use_acoustid and from_file:
         # we try to deduce mbid from acoustid
         client = get_acoustid_client()
@@ -185,7 +183,7 @@ def fetch_content(lyrics):
 @celery.require_instance(
     models.ImportBatch.objects.filter(status='finished'), 'import_batch')
 def import_batch_notify_followers(import_batch):
-    if not settings.FEDERATION_ENABLED:
+    if not preferences.get('federation__enabled'):
         return
 
     if import_batch.source == 'federation':
diff --git a/api/tests/federation/test_actors.py b/api/tests/federation/test_actors.py
index f566e7a72aa4fd5bf7f1417856903d39535e4f66..6f73a9b9b2fc2fae47933898ba6c518158fcafbd 100644
--- a/api/tests/federation/test_actors.py
+++ b/api/tests/federation/test_actors.py
@@ -39,8 +39,8 @@ def test_get_actor(factories, r_mock):
     assert serializers.ActorSerializer(new_actor).data == payload
 
 
-def test_get_actor_use_existing(factories, settings, mocker):
-    settings.FEDERATION_ACTOR_FETCH_DELAY = 60
+def test_get_actor_use_existing(factories, preferences, mocker):
+    preferences['federation__actor_fetch_delay'] = 60
     actor = factories['federation.Actor']()
     get_data = mocker.patch('funkwhale_api.federation.actors.get_actor_data')
     new_actor = actors.get_actor(actor.url)
@@ -49,8 +49,8 @@ def test_get_actor_use_existing(factories, settings, mocker):
     get_data.assert_not_called()
 
 
-def test_get_actor_refresh(factories, settings, mocker):
-    settings.FEDERATION_ACTOR_FETCH_DELAY = 0
+def test_get_actor_refresh(factories, preferences, mocker):
+    preferences['federation__actor_fetch_delay'] = 0
     actor = factories['federation.Actor']()
     payload = serializers.ActorSerializer(actor).data
     # actor changed their username in the meantime
@@ -274,9 +274,9 @@ def test_actor_is_system(
 
 
 @pytest.mark.parametrize('value', [False, True])
-def test_library_actor_manually_approves_based_on_setting(
-        value, settings):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = value
+def test_library_actor_manually_approves_based_on_preference(
+        value, preferences):
+    preferences['federation__music_needs_approval'] = value
     library_conf = actors.SYSTEM_ACTORS['library']
     assert library_conf.manually_approves_followers is value
 
@@ -356,8 +356,8 @@ def test_test_actor_handles_undo_follow(
 
 
 def test_library_actor_handles_follow_manual_approval(
-        settings, mocker, factories):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = True
+        preferences, mocker, factories):
+    preferences['federation__music_needs_approval'] = True
     actor = factories['federation.Actor']()
     now = timezone.now()
     mocker.patch('django.utils.timezone.now', return_value=now)
@@ -377,8 +377,8 @@ def test_library_actor_handles_follow_manual_approval(
 
 
 def test_library_actor_handles_follow_auto_approval(
-        settings, mocker, factories):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = False
+        preferences, mocker, factories):
+    preferences['federation__music_needs_approval'] = False
     actor = factories['federation.Actor']()
     accept_follow = mocker.patch(
         'funkwhale_api.federation.activity.accept_follow')
diff --git a/api/tests/federation/test_permissions.py b/api/tests/federation/test_permissions.py
index 9b86832108fdc36a708c22ea104af4561cf0c1d9..a87f26f1b910b77b63ba65061f319d9f8ab4ba50 100644
--- a/api/tests/federation/test_permissions.py
+++ b/api/tests/federation/test_permissions.py
@@ -5,8 +5,8 @@ from funkwhale_api.federation import permissions
 
 
 def test_library_follower(
-        factories, api_request, anonymous_user, settings):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = True
+        factories, api_request, anonymous_user, preferences):
+    preferences['federation__music_needs_approval'] = True
     view = APIView.as_view()
     permission = permissions.LibraryFollower()
     request = api_request.get('/')
@@ -17,8 +17,8 @@ def test_library_follower(
 
 
 def test_library_follower_actor_non_follower(
-        factories, api_request, anonymous_user, settings):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = True
+        factories, api_request, anonymous_user, preferences):
+    preferences['federation__music_needs_approval'] = True
     actor = factories['federation.Actor']()
     view = APIView.as_view()
     permission = permissions.LibraryFollower()
@@ -31,8 +31,8 @@ def test_library_follower_actor_non_follower(
 
 
 def test_library_follower_actor_follower_not_approved(
-        factories, api_request, anonymous_user, settings):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = True
+        factories, api_request, anonymous_user, preferences):
+    preferences['federation__music_needs_approval'] = True
     library = actors.SYSTEM_ACTORS['library'].get_actor_instance()
     follow = factories['federation.Follow'](target=library, approved=False)
     view = APIView.as_view()
@@ -46,8 +46,8 @@ def test_library_follower_actor_follower_not_approved(
 
 
 def test_library_follower_actor_follower(
-        factories, api_request, anonymous_user, settings):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = True
+        factories, api_request, anonymous_user, preferences):
+    preferences['federation__music_needs_approval'] = True
     library = actors.SYSTEM_ACTORS['library'].get_actor_instance()
     follow = factories['federation.Follow'](target=library, approved=True)
     view = APIView.as_view()
diff --git a/api/tests/federation/test_views.py b/api/tests/federation/test_views.py
index ae94bcdc02ab2e23704eb3622ec311128713e9ce..09ecfc8ff7f6d192808890b78eb9d3226ad8cc7e 100644
--- a/api/tests/federation/test_views.py
+++ b/api/tests/federation/test_views.py
@@ -13,7 +13,7 @@ from funkwhale_api.federation import webfinger
 
 
 @pytest.mark.parametrize('system_actor', actors.SYSTEM_ACTORS.keys())
-def test_instance_actors(system_actor, db, settings, api_client):
+def test_instance_actors(system_actor, db, api_client):
     actor = actors.SYSTEM_ACTORS[system_actor].get_actor_instance()
     url = reverse(
         'federation:instance-actors-detail',
@@ -34,8 +34,8 @@ def test_instance_actors(system_actor, db, settings, api_client):
     ('well-known-webfinger', {}),
 ])
 def test_instance_endpoints_405_if_federation_disabled(
-        authenticated_actor, db, settings, api_client, route, kwargs):
-    settings.FEDERATION_ENABLED = False
+        authenticated_actor, db, preferences, api_client, route, kwargs):
+    preferences['federation__enabled'] = False
     url = reverse('federation:{}'.format(route), kwargs=kwargs)
     response = api_client.get(url)
 
@@ -71,8 +71,8 @@ def test_wellknown_webfinger_system(
 
 
 def test_audio_file_list_requires_authenticated_actor(
-        db, settings, api_client):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = True
+        db, preferences, api_client):
+    preferences['federation__music_needs_approval'] = True
     url = reverse('federation:music:files-list')
     response = api_client.get(url)
 
@@ -80,9 +80,9 @@ def test_audio_file_list_requires_authenticated_actor(
 
 
 def test_audio_file_list_actor_no_page(
-        db, settings, api_client, factories):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = False
-    settings.FEDERATION_COLLECTION_PAGE_SIZE = 2
+        db, preferences, api_client, factories):
+    preferences['federation__music_needs_approval'] = False
+    preferences['federation__collection_page_size'] = 2
     library = actors.SYSTEM_ACTORS['library'].get_actor_instance()
     tfs = factories['music.TrackFile'].create_batch(size=5)
     conf = {
@@ -101,9 +101,9 @@ def test_audio_file_list_actor_no_page(
 
 
 def test_audio_file_list_actor_page(
-        db, settings, api_client, factories):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = False
-    settings.FEDERATION_COLLECTION_PAGE_SIZE = 2
+        db, preferences, api_client, factories):
+    preferences['federation__music_needs_approval'] = False
+    preferences['federation__collection_page_size'] = 2
     library = actors.SYSTEM_ACTORS['library'].get_actor_instance()
     tfs = factories['music.TrackFile'].create_batch(size=5)
     conf = {
@@ -121,8 +121,8 @@ def test_audio_file_list_actor_page(
 
 
 def test_audio_file_list_actor_page_exclude_federated_files(
-        db, settings, api_client, factories):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = False
+        db, preferences, api_client, factories):
+    preferences['federation__music_needs_approval'] = False
     library = actors.SYSTEM_ACTORS['library'].get_actor_instance()
     tfs = factories['music.TrackFile'].create_batch(size=5, federation=True)
 
@@ -134,8 +134,8 @@ def test_audio_file_list_actor_page_exclude_federated_files(
 
 
 def test_audio_file_list_actor_page_error(
-        db, settings, api_client, factories):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = False
+        db, preferences, api_client, factories):
+    preferences['federation__music_needs_approval'] = False
     url = reverse('federation:music:files-list')
     response = api_client.get(url, data={'page': 'nope'})
 
@@ -143,15 +143,15 @@ def test_audio_file_list_actor_page_error(
 
 
 def test_audio_file_list_actor_page_error_too_far(
-        db, settings, api_client, factories):
-    settings.FEDERATION_MUSIC_NEEDS_APPROVAL = False
+        db, preferences, api_client, factories):
+    preferences['federation__music_needs_approval'] = False
     url = reverse('federation:music:files-list')
     response = api_client.get(url, data={'page': 5000})
 
     assert response.status_code == 404
 
 
-def test_library_actor_includes_library_link(db, settings, api_client):
+def test_library_actor_includes_library_link(db, preferences, api_client):
     actor = actors.SYSTEM_ACTORS['library'].get_actor_instance()
     url = reverse(
         'federation:instance-actors-detail',
diff --git a/api/tests/music/test_import.py b/api/tests/music/test_import.py
index fa1c98eb4ca78c7e9fab5861989852687d764f03..000e6a8b6265eca2178c98ff52b0807956314830 100644
--- a/api/tests/music/test_import.py
+++ b/api/tests/music/test_import.py
@@ -169,10 +169,10 @@ def test_import_job_run_triggers_notifies_followers(
 
 
 def test_import_batch_notifies_followers_skip_on_disabled_federation(
-        settings, factories, mocker):
+        preferences, factories, mocker):
     mocked_deliver = mocker.patch('funkwhale_api.federation.activity.deliver')
     batch = factories['music.ImportBatch'](finished=True)
-    settings.FEDERATION_ENABLED = False
+    preferences['federation__enabled'] = False
     tasks.import_batch_notify_followers(import_batch_id=batch.pk)
 
     mocked_deliver.assert_not_called()
diff --git a/deploy/env.prod.sample b/deploy/env.prod.sample
index 54f2e1ef08192d5a181d04bb69ad69b0848f2faa..e357d08d3389202ac28920b7332448099705223e 100644
--- a/deploy/env.prod.sample
+++ b/deploy/env.prod.sample
@@ -98,15 +98,6 @@ API_AUTHENTICATION_REQUIRED=True
 RAVEN_ENABLED=false
 RAVEN_DSN=https://44332e9fdd3d42879c7d35bf8562c6a4:0062dc16a22b41679cd5765e5342f716@sentry.eliotberriot.com/5
 
-# This settings enable/disable federation on the instance level
-FEDERATION_ENABLED=True
-# This setting decide wether music library is shared automatically
-# to followers or if it requires manual approval before.
-# FEDERATION_MUSIC_NEEDS_APPROVAL=False
-# means anyone can subscribe to your library and import your file,
-# use with caution.
-FEDERATION_MUSIC_NEEDS_APPROVAL=True
-
 # In-place import settings
 # You can safely leave those settings uncommented if you don't plan to use
 # in place imports.