diff --git a/changes/changelog.d/650.enhancement b/changes/changelog.d/650.enhancement
new file mode 100644
index 0000000000000000000000000000000000000000..c7fb6460095ecb899214c3fe98e844bc824ca6ae
--- /dev/null
+++ b/changes/changelog.d/650.enhancement
@@ -0,0 +1 @@
+Support setting a server URL in settings.json (#650)
diff --git a/docs/configuration.rst b/docs/configuration.rst
index 6190f0e9f3fb480a30d75990380471b1f0e00842..ffb702d6b842445374f4eb86007d5809a025e1d1 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -159,58 +159,113 @@ There is no dedicated interface to manage users permissions, but superusers
 can login on the Django's admin at ``/api/admin/`` and grant permissions
 to users at ``/api/admin/users/user/``.
 
-Theming
--------
+Front-end settings
+------------------
 
-Funkwhale supports custom themes, which are great if you want to personalize the
-look and feel of your instance. Theming is achieved by declaring
-additional stylesheets you want to load in the front-end.
+We offer a basic mechanism to customize the behaviour 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``.
 
-Customize the settings
-^^^^^^^^^^^^^^^^^^^^^^
+On typical deployments, this url returns a 404 error, which is simply ignored.
 
-In order to know what stylesheets to load, the front-end requests the following
-url: ``https://your.instance/settings.json``. On typical deployments, this url
-returns a 404 error, which is simply ignored.
+Set-up
+------
 
-However, if you return the appropriate payload on this url, you can make the magic
-work. We will store the necessary files in the ``/srv/funkwhale/custom`` directory:
+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 <<EOF > custom/settings.json
     {
-      "additionalStylesheets": ["/front/custom/custom.css"]
+      "additionalStylesheets": [],
+      "defaultServerUrl": null
     }
     EOF
-    cat <<EOF > custom/custom.css
+
+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 `<https://github.com/zaach/jsonlint>`_ 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 <<EOF > custom.css
     body {
       background-color: red;
     }
     EOF
 
-By executing the previous commands, you will end up with two files in your ``/srv/funkwhale/custom``
-directory:
-
-- ``settings.json`` will tell the front-end what stylesheets you want to load (``/front/custom/custom.css`` in this example)
-- ``custom.css`` will hold your custom CSS
-
-The last step to make this work is to ensure both files are served by the reverse proxy.
+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 /settings.json {
-        alias /srv/funkwhale/custom/settings.json;
-    }
     location /custom {
         alias /srv/funkwhale/custom;
     }
 
 On apache, use the following one::
 
-    Alias /settings.json /srv/funkwhale/custom/settings.json
     Alias /custom /srv/funkwhale/custom
 
     <Directory "/srv/funkwhale/custom">
@@ -224,7 +279,7 @@ a red background.
 
 .. note::
 
-    You can reference external urls as well in ``settings.json``, simply use
+    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.
 
diff --git a/front/public/settings.json b/front/public/settings.json
index c25eb99f46e846f03099853e05b50dee8deb363f..6264b12cf851e73c57fa9670d19d5ed62997a35a 100644
--- a/front/public/settings.json
+++ b/front/public/settings.json
@@ -1,5 +1,6 @@
 {
   "additionalStylesheets": [
     "/front/custom.css"
-  ]
+  ],
+  "defaultServerUrl": null
 }
diff --git a/front/src/App.vue b/front/src/App.vue
index 116d30ed71d3473e07221347dade79c8ca6d908f..cac8477daf9b4c4811874977caf3712561138eb6 100644
--- a/front/src/App.vue
+++ b/front/src/App.vue
@@ -93,7 +93,11 @@ export default {
       self.$store.commit('ui/computeLastDate')
     }, 1000 * 60)
     if (!this.$store.state.instance.instanceUrl) {
-      let defaultInstanceUrl = process.env.VUE_APP_INSTANCE_URL || this.$store.getters['instance/defaultUrl']()
+      // we have several way to guess the API server url. By order of precedence:
+      // 1. use the url provided in settings.json, if any
+      // 2. use the url specified when building via VUE_APP_INSTANCE_URL
+      // 3. use the current url
+      let defaultInstanceUrl = this.$store.state.instance.frontSettings.defaultServerUrl || process.env.VUE_APP_INSTANCE_URL || this.$store.getters['instance/defaultUrl']()
       this.$store.commit('instance/instanceUrl', defaultInstanceUrl)
     } else {
       // needed to trigger initialization of axios
@@ -194,7 +198,11 @@ export default {
       messages: state => state.ui.messages
     }),
     suggestedInstances () {
-      let instances = [this.$store.getters['instance/defaultUrl'](), 'https://demo.funkwhale.audio']
+      let instances = []
+      if (this.$store.state.instance.frontSettings.defaultServerUrl) {
+        instances.push(this.$store.state.instance.frontSettings.defaultServerUrl)
+      }
+      instances.push(this.$store.getters['instance/defaultUrl'](), 'https://demo.funkwhale.audio')
       return instances
     },
     version () {
diff --git a/front/src/main.js b/front/src/main.js
index 4cd38a6be2a01159e8b0c0d0c65b48f2fc169259..10f125496053ad8fc23b06fb0d16e9f55484d54a 100644
--- a/front/src/main.js
+++ b/front/src/main.js
@@ -126,15 +126,15 @@ axios.interceptors.response.use(function (response) {
   return Promise.reject(error)
 })
 
-store.dispatch('instance/fetchFrontSettings')
+store.dispatch('instance/fetchFrontSettings').finally(() => {
+  /* eslint-disable no-new */
+  new Vue({
+    el: '#app',
+    router,
+    store,
+    template: '<App/>',
+    components: { App }
+  })
 
-/* eslint-disable no-new */
-new Vue({
-  el: '#app',
-  router,
-  store,
-  template: '<App/>',
-  components: { App }
+  logger.default.info('Everything loaded!')
 })
-
-logger.default.info('Everything loaded!')