diff --git a/backend/app.py b/backend/app.py
index 76b3247bc1b6a841eb5d1111a2a4d2e889d125b8..9bc3812072ee48c795b29d1392e36c33f6ec8e34 100644
--- a/backend/app.py
+++ b/backend/app.py
@@ -19,6 +19,7 @@ from areas import resources
 from areas import roles
 from areas import tags
 from cliapp import cliapp
+import helpers.kubernetes
 import helpers.provision
 from web import login
 
@@ -104,16 +105,25 @@ def init_routines():
         app.logger.info(f"upgrade failed: {type(e)}: {e}")
         sys.exit(2)
 
-    # We need this app context in order to talk the database, which is managed by
-    # flask-sqlalchemy, which assumes a flask app context.
+    def reload():
+        # We need this app context in order to talk the database, which is managed by
+        # flask-sqlalchemy, which assumes a flask app context.
+        with app.app_context():
+            app.logger.info("Reloading dashboard config from cluster resources.")
+            # Load the list of apps from a configmap and store any missing ones in the
+            # database.
+            app_slugs = cluster_config.populate_apps()
+            # Same for the list of oauthclients.
+            cluster_config.populate_oauthclients()
+            # Load per-app scim config if present.
+            cluster_config.populate_scim_config(app_slugs)
+    reload()
     with app.app_context():
-        # Load the list of apps from a configmap and store any missing ones in the
-        # database.
-        app_slugs = cluster_config.populate_apps()
-        # Same for the list of oauthclients.
-        cluster_config.populate_oauthclients()
-        # Load per-app scim config if present.
-        cluster_config.populate_scim_config(app_slugs)
+        app.logger.info("Setting watch for dashboard config.")
+        try:
+            helpers.kubernetes.watch_dashboard_config(app, reload)
+        except Exception as e:
+            app.logger.error(f"Error watching: {e}")
 
     # if provisioner.enabled:
     # We define this wrapper because the SCIM provisioning code needs to access the
diff --git a/backend/cluster_config.py b/backend/cluster_config.py
index cc15b24658b82c9da0c40a3bb2d4320ce5c0e342..f5bf967c60c9e2b3f978f53267f9e9023bdacbef 100644
--- a/backend/cluster_config.py
+++ b/backend/cluster_config.py
@@ -98,17 +98,18 @@ def populate_scim_config(apps):
         if scim_config is None:
             logging.info(f"Could not find secret '{secret_name}' in namespace 'flux-system'; ignoring.")
             continue
+        logging.info(f"Processing secret stackspin-scim-{app}")
         app = App.query.filter_by(slug=app).first()
         if not app:
             logging.error(f"  could not find app with slug {app}")
             continue
         scim_url = scim_config.get("scim_url")
         if scim_url is None:
-            logging.error(f"  'url' is not set")
+            logging.error(f"  'scim_url' is not set")
             continue
         scim_token = scim_config.get("scim_token")
         if scim_token is None:
-            logging.error(f"  'token' is not set")
+            logging.error(f"  'scim_token' is not set")
             continue
         scim_url = base64.b64decode(scim_url).decode()
         # We substitute the string `$BASE` or `${BASE}` in the `scim_url` by
diff --git a/backend/helpers/kubernetes.py b/backend/helpers/kubernetes.py
index cfdcbf7d53145558fb5d636b969b698c8cf28aa1..4e8ad96405a2e67c96ce302cefc15014af11fe1d 100644
--- a/backend/helpers/kubernetes.py
+++ b/backend/helpers/kubernetes.py
@@ -2,12 +2,14 @@
 List of functions to get data from Flux Kustomizations and Helmreleases
 """
 import crypt
+import functools
 import secrets
 import string
+import threading
 
 import jinja2
 import yaml
-from kubernetes import client, config
+from kubernetes import client, config, watch
 from kubernetes.config.incluster_config import InClusterConfigLoader
 from kubernetes.client import api_client
 from kubernetes.client.exceptions import ApiException
@@ -421,3 +423,36 @@ def get_gitrepo(name, namespace='flux-system'):
         # Raise all non-404 errors
         raise error
     return resource
+
+def debounce(timeout: float):
+    def decorator(func):
+        @functools.wraps(func)
+        def wrapper(*args, **kwargs):
+            wrapper.func.cancel()
+            wrapper.func = threading.Timer(timeout, func, args, kwargs)
+            wrapper.func.start()
+        wrapper.func = threading.Timer(timeout, lambda: None)
+        return wrapper
+    return decorator
+
+def watch_dashboard_config(app, reload):
+    current_app.logger.info("Creating watch.")
+    w = watch.Watch()
+    current_app.logger.info("Creating api instance.")
+    api_client_instance = api_client.ApiClient()
+    api_instance = client.CoreV1Api(api_client_instance)
+    def p():
+        with app.app_context():
+            for event in w.stream(
+                    api_instance.list_namespaced_secret,
+                    'flux-system',
+                    label_selector="stackspin.net/scim-config=1",
+                    watch=True
+                ):
+                current_app.logger.info(f"{event['type']}: {event['object'].metadata.name}")
+                debounce(1)(reload)()
+    current_app.logger.info("Creating thread.")
+    thread = threading.Thread(target=p)
+    current_app.logger.info("Starting thread.")
+    thread.start()
+    current_app.logger.info("watch_dashboard-config finished")
diff --git a/backend/helpers/provision.py b/backend/helpers/provision.py
index d14c014f614e474b57ea8c3d514e4fe0de1e53fc..200c11cceebfde38878df0b0d91d874c8979deec 100644
--- a/backend/helpers/provision.py
+++ b/backend/helpers/provision.py
@@ -221,7 +221,7 @@ class Provision:
             if kratos_user.name is None or kratos_user.name == '':
                 data['name']['formatted'] = " "
             # Zulip doesn't support SCIM user groups, but we can set the user
-            # role directly.
+            # role as a field on the user object.
             if app_role.role_id == Role.ADMIN_ROLE_ID:
                 data['role'] = 'owner'
 
diff --git a/deployment/helmchart/templates/rbac/clusterrole.yaml b/deployment/helmchart/templates/rbac/clusterrole.yaml
index b4b8874817640a3eb0b45c8b4672bae13df31944..834c6c980c38a7174115a1e7a1eb42492f6715a3 100644
--- a/deployment/helmchart/templates/rbac/clusterrole.yaml
+++ b/deployment/helmchart/templates/rbac/clusterrole.yaml
@@ -46,6 +46,7 @@ rules:
       - configmaps
     verbs:
       - list
+      - watch
       - get
       - patch
       - delete