summary refs log tree commit diff
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2024-08-16 12:16:21 +0200
committerRory& <root@rory.gay>2024-08-16 12:16:21 +0200
commit9778db57511950cda9d5c0f8955597d6b2282302 (patch)
treee946d27d44b425986240dd731afea7944894df1a
parentNginx log request times (diff)
downloadRory-Open-Architecture-9778db57511950cda9d5c0f8955597d6b2282302.tar.xz
Some synapse workers cleanup
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/appservice.nix38
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/auth.nix99
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/background.nix38
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/client-reader.nix69
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/federation-inbound.nix5
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/federation-reader.nix7
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/federation-sender.nix75
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/media-repo.nix5
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/module.nix114
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/pusher.nix5
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/single/appservice.nix79
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/single/background.nix79
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/single/user-dir.nix83
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/sync.nix9
-rw-r--r--host/Rory-nginx/services/matrix/synapse/workers/user-dir.nix68
15 files changed, 484 insertions, 289 deletions
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/appservice.nix b/host/Rory-nginx/services/matrix/synapse/workers/appservice.nix
deleted file mode 100644
index e3b07bc..0000000
--- a/host/Rory-nginx/services/matrix/synapse/workers/appservice.nix
+++ /dev/null
@@ -1,38 +0,0 @@
-{ config, lib, ... }:
-
-let
-  cfg = config.services.matrix-synapse;
-  workerName = "appservice";
-  workerRoutes = [ ];
-in
-{
-  services.matrix-synapse = lib.mkIf cfg.enableAppserviceWorker {
-    settings = {
-      instance_map = {
-        appservice = {
-          path = "/run/matrix-synapse/${workerName}.sock";
-        };
-      };
-
-      notify_appservices_from_worker = workerName;
-    };
-
-    workers = {
-      appservice = {
-        worker_app = "synapse.app.generic_worker";
-        worker_listeners = [
-          {
-            type = "http";
-            path = "/run/matrix-synapse/${workerName}.sock";
-            resources = [
-              {
-                names = [ "replication" ];
-                compress = false;
-              }
-            ];
-          }
-        ];
-      };
-    };
-  };
-}
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/auth.nix b/host/Rory-nginx/services/matrix/synapse/workers/auth.nix
new file mode 100644
index 0000000..e8d14b5
--- /dev/null
+++ b/host/Rory-nginx/services/matrix/synapse/workers/auth.nix
@@ -0,0 +1,99 @@
+{ config, lib, ... }:
+
+let
+  cfg = config.services.matrix-synapse;
+  dbGroup = "solo";
+  hasClientResource = false;
+  hasFederationResource = false;
+  workers = lib.range 0 (cfg.authWorkers - 1);
+  workerName = "auth";
+  workerRoutes = [
+    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/login$"
+    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/account/3pid$"
+    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/account/whoami$"
+    "~ ^/_matrix/client/versions$"
+    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/voip/turnServer$"
+    "~ ^/_matrix/client/(r0|v3|unstable)/register$"
+    "~ ^/_matrix/client/(r0|v3|unstable)/register/available$"
+    "~ ^/_matrix/client/(r0|v3|unstable)/auth/.*/fallback/web$"
+    "~ ^/_matrix/client/(r0|v3|unstable)/password_policy$"
+    "~ ^/_matrix/client/(r0|v3|unstable)/capabilities$"
+  ];
+in
+{
+  config = lib.mkIf (cfg.authWorkers > 0) {
+    services.matrix-synapse = {
+      settings = {
+        instance_map = lib.listToAttrs (
+          lib.map (index: {
+            name = "${workerName}-${toString index}";
+            value = {
+              path = "/run/matrix-synapse/${workerName}-${toString index}.sock";
+            };
+          }) workers
+        );
+      };
+
+      workers = lib.listToAttrs (
+        lib.map (index: {
+          name = "${workerName}-${toString index}";
+          value = {
+            worker_app = "synapse.app.generic_worker";
+            worker_listeners = [
+              {
+                type = "http";
+                path = "/run/matrix-synapse/${workerName}-${toString index}.sock";
+                resources = [
+                  {
+                    names = [ "replication" ];
+                    compress = false;
+                  }
+                ];
+              }
+              {
+                type = "http";
+                path = "/run/matrix-synapse/${workerName}-client-${toString index}.sock";
+                mode = "666";
+                resources = [
+                  {
+                    names = [ "client" ];
+                    compress = false;
+                  }
+                ];
+              }
+            ];
+            database = (
+              import ../db.nix {
+                inherit dbGroup;
+                workerName = "${workerName}-${toString index}";
+              }
+            );
+          };
+        }) workers
+      );
+    };
+
+    services.nginx.upstreams."${workerName}" = {
+      extraConfig = ''
+        keepalive 32;
+      '';
+      servers = lib.listToAttrs (
+        lib.map (index: {
+          name = "unix:/run/matrix-synapse/${workerName}-client-${toString index}.sock";
+          value = {
+            max_fails = 0;
+          };
+        }) workers
+      );
+    };
+
+    services.nginx.virtualHosts."${cfg.nginxVirtualHostName}".locations = lib.listToAttrs (
+      lib.map (route: {
+        name = route;
+        value = {
+          proxyPass = "http://${workerName}";
+        };
+      }) workerRoutes
+    );
+  };
+}
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/background.nix b/host/Rory-nginx/services/matrix/synapse/workers/background.nix
deleted file mode 100644
index 611f6eb..0000000
--- a/host/Rory-nginx/services/matrix/synapse/workers/background.nix
+++ /dev/null
@@ -1,38 +0,0 @@
-{ config, lib, ... }:
-
-let
-  cfg = config.services.matrix-synapse;
-  workerName = "background";
-  workerRoutes = [ ];
-in
-{
-  services.matrix-synapse = lib.mkIf cfg.enableBackgroundWorker {
-    settings = {
-      instance_map = {
-        background = {
-          path = "/run/matrix-synapse/${workerName}.sock";
-        };
-      };
-
-      run_background_tasks_on = workerName;
-    };
-
-    workers = {
-      background = {
-        worker_app = "synapse.app.generic_worker";
-        worker_listeners = [
-          {
-            type = "http";
-            path = "/run/matrix-synapse/${workerName}.sock";
-            resources = [
-              {
-                names = [ "replication" ];
-                compress = false;
-              }
-            ];
-          }
-        ];
-      };
-    };
-  };
-}
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/client-reader.nix b/host/Rory-nginx/services/matrix/synapse/workers/client-reader.nix
index c89b147..5f3acbc 100644
--- a/host/Rory-nginx/services/matrix/synapse/workers/client-reader.nix
+++ b/host/Rory-nginx/services/matrix/synapse/workers/client-reader.nix
@@ -2,37 +2,46 @@
 
 let
   cfg = config.services.matrix-synapse;
+  dbGroup = "small";
+  hasClientResource = false;
+  hasFederationResource = false;
   workers = lib.range 0 (cfg.clientReaders - 1);
   workerName = "client_reader";
-  routes = [
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/publicRooms$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/joined_members$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/context/.*$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/members$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/state$"
-    "~ ^/_matrix/client/v1/rooms/.*/hierarchy$"
-    "~ ^/_matrix/client/(v1|unstable)/rooms/.*/relations/"
-    "~ ^/_matrix/client/v1/rooms/.*/threads$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/login$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/account/3pid$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/account/whoami$"
-    "~ ^/_matrix/client/versions$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/voip/turnServer$"
-    "~ ^/_matrix/client/(r0|v3|unstable)/register$"
-    "~ ^/_matrix/client/(r0|v3|unstable)/register/available$"
-    "~ ^/_matrix/client/(r0|v3|unstable)/auth/.*/fallback/web$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/messages$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/event"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/joined_rooms"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable/.*)/rooms/.*/aliases"
-    "~ ^/_matrix/client/v1/rooms/.*/timestamp_to_event$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/search"
-    "~ ^/_matrix/client/(r0|v3|unstable)/user/.*/filter(/|$)"
-    "~ ^/_matrix/client/(r0|v3|unstable)/password_policy$"
-    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/directory/room/.*$"
-    "~ ^/_matrix/client/(r0|v3|unstable)/capabilities$"
-    "~ ^/_matrix/client/(r0|v3|unstable)/notifications$"
-  ];
+  routes =
+    [
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/publicRooms$"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/joined_members$"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/context/.*$"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/members$"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/state$"
+      "~ ^/_matrix/client/v1/rooms/.*/hierarchy$"
+      "~ ^/_matrix/client/(v1|unstable)/rooms/.*/relations/"
+      "~ ^/_matrix/client/v1/rooms/.*/threads$"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/messages$"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/event"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/joined_rooms"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable/.*)/rooms/.*/aliases"
+      "~ ^/_matrix/client/v1/rooms/.*/timestamp_to_event$"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/search"
+      "~ ^/_matrix/client/(r0|v3|unstable)/user/.*/filter(/|$)"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/directory/room/.*$"
+      "~ ^/_matrix/client/(r0|v3|unstable)/notifications$"
+
+      # unstable
+      "~ ^/_matrix/client/unstable/im.nheko.summary/rooms/.*/summary$"
+    ]
+    ++ lib.optionals (cfg.authWorkers == 0) [
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/login$"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/account/3pid$"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/account/whoami$"
+      "~ ^/_matrix/client/versions$"
+      "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/voip/turnServer$"
+      "~ ^/_matrix/client/(r0|v3|unstable)/register$"
+      "~ ^/_matrix/client/(r0|v3|unstable)/register/available$"
+      "~ ^/_matrix/client/(r0|v3|unstable)/auth/.*/fallback/web$"
+      "~ ^/_matrix/client/(r0|v3|unstable)/password_policy$"
+      "~ ^/_matrix/client/(r0|v3|unstable)/capabilities$"
+    ];
 in
 {
   config = lib.mkIf (cfg.clientReaders > 0) {
@@ -78,8 +87,8 @@ in
             ];
             database = (
               import ../db.nix {
+                inherit dbGroup;
                 workerName = "${workerName}-${toString index}";
-                dbGroup = "medium";
               }
             );
           };
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/federation-inbound.nix b/host/Rory-nginx/services/matrix/synapse/workers/federation-inbound.nix
index 2e3574f..03f5576 100644
--- a/host/Rory-nginx/services/matrix/synapse/workers/federation-inbound.nix
+++ b/host/Rory-nginx/services/matrix/synapse/workers/federation-inbound.nix
@@ -2,6 +2,9 @@
 
 let
   cfg = config.services.matrix-synapse;
+  dbGroup = "medium";
+  hasClientResource = false;
+  hasFederationResource = false;
   workers = lib.range 0 (cfg.federationReaders - 1);
   workerName = "federation_inbound";
   workerRoutes = [ "~ /_matrix/federation/(v1|v2)/send/" ];
@@ -50,8 +53,8 @@ in
             ];
             database = (
               import ../db.nix {
+                inherit dbGroup;
                 workerName = "${workerName}-${toString index}";
-                dbGroup = "medium";
               }
             );
           };
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/federation-reader.nix b/host/Rory-nginx/services/matrix/synapse/workers/federation-reader.nix
index 762f82c..ceefefb 100644
--- a/host/Rory-nginx/services/matrix/synapse/workers/federation-reader.nix
+++ b/host/Rory-nginx/services/matrix/synapse/workers/federation-reader.nix
@@ -2,6 +2,9 @@
 
 let
   cfg = config.services.matrix-synapse;
+  dbGroup = "medium";
+  hasClientResource = false;
+  hasFederationResource = false;
   workers = lib.range 0 (cfg.federationReaders - 1);
   workerName = "federation_reader";
   workerRoutes = [
@@ -26,6 +29,8 @@ let
     "~ ^/_matrix/federation/(v1|v2)/user/devices/"
     "~ ^/_matrix/federation/(v1|v2)/get_groups_publicised$"
     "~ ^/_matrix/key/v2/query"
+    # extra
+    "~ ^/_matrix/key/v2/server$"
   ];
 in
 {
@@ -72,8 +77,8 @@ in
             ];
             database = (
               import ../db.nix {
+                inherit dbGroup;
                 workerName = "${workerName}-${toString index}";
-                dbGroup = "medium";
               }
             );
           };
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/federation-sender.nix b/host/Rory-nginx/services/matrix/synapse/workers/federation-sender.nix
index 391e046..931d6a4 100644
--- a/host/Rory-nginx/services/matrix/synapse/workers/federation-sender.nix
+++ b/host/Rory-nginx/services/matrix/synapse/workers/federation-sender.nix
@@ -1,52 +1,57 @@
 { config, lib, ... }:
 let
   cfg = config.services.matrix-synapse;
+  dbGroup = "solo";
+  hasClientResource = false;
+  hasFederationResource = false;
   federationSenders = lib.range 0 (cfg.federationSenders - 1);
   workerName = "federation_sender";
   workerRoutes = [ ];
 in
 {
-  services.matrix-synapse = lib.mkIf (cfg.federationSenders > 0) {
-    settings = {
-      instance_map = lib.listToAttrs (
+  config = lib.mkIf (cfg.federationSenders > 0) {
+    services.matrix-synapse = {
+      settings = {
+        instance_map = lib.listToAttrs (
+          lib.map (index: {
+            name = "${workerName}-${toString index}";
+            value = {
+              path = "/run/matrix-synapse/${workerName}-${toString index}.sock";
+            };
+          }) federationSenders
+        );
+        send_federation = false;
+        federation_sender_instances = lib.map (index: "${workerName}-${toString index}") federationSenders;
+        outbound_federation_restricted_to = lib.map (index: "${workerName}-${toString index}") federationSenders;
+        worker_replication_secret = "${workerName}_secret";
+      };
+
+      workers = lib.listToAttrs (
         lib.map (index: {
           name = "${workerName}-${toString index}";
           value = {
-            path = "/run/matrix-synapse/${workerName}-${toString index}.sock";
+            worker_app = "synapse.app.generic_worker";
+            worker_listeners = [
+              {
+                type = "http";
+                path = "/run/matrix-synapse/${workerName}-${toString index}.sock";
+                resources = [
+                  {
+                    names = [ "replication" ];
+                    compress = false;
+                  }
+                ];
+              }
+            ];
+            database = (
+              import ../db.nix {
+                inherit dbGroup;
+                workerName = "${workerName}-${toString index}";
+              }
+            );
           };
         }) federationSenders
       );
-      send_federation = false;
-      federation_sender_instances = lib.map (index: "${workerName}-${toString index}") federationSenders;
-      outbound_federation_restricted_to = lib.map (index: "${workerName}-${toString index}") federationSenders;
-      worker_replication_secret = "${workerName}_secret";
     };
-
-    workers = lib.listToAttrs (
-      lib.map (index: {
-        name = "${workerName}-${toString index}";
-        value = {
-          worker_app = "synapse.app.generic_worker";
-          worker_listeners = [
-            {
-              type = "http";
-              path = "/run/matrix-synapse/${workerName}-${toString index}.sock";
-              resources = [
-                {
-                  names = [ "replication" ];
-                  compress = false;
-                }
-              ];
-            }
-          ];
-          database = (
-            import ../db.nix {
-              workerName = "${workerName}-${toString index}";
-              dbGroup = "solo";
-            }
-          );
-        };
-      }) federationSenders
-    );
   };
 }
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/media-repo.nix b/host/Rory-nginx/services/matrix/synapse/workers/media-repo.nix
index b030706..4309a9f 100644
--- a/host/Rory-nginx/services/matrix/synapse/workers/media-repo.nix
+++ b/host/Rory-nginx/services/matrix/synapse/workers/media-repo.nix
@@ -2,6 +2,9 @@
 
 let
   cfg = config.services.matrix-synapse;
+  dbGroup = "solo";
+  hasClientResource = false;
+  hasFederationResource = false;
   workers = lib.range 0 (cfg.mediaRepoWorkers - 1);
   workerName = "media_repo";
   routes = [
@@ -62,8 +65,8 @@ in
             ];
             database = (
               import ../db.nix {
+                inherit dbGroup;
                 workerName = "${workerName}-${toString index}";
-                dbGroup = "solo";
               }
             );
             enable_media_repo = true;
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/module.nix b/host/Rory-nginx/services/matrix/synapse/workers/module.nix
index bb46aed..ca6aaec 100644
--- a/host/Rory-nginx/services/matrix/synapse/workers/module.nix
+++ b/host/Rory-nginx/services/matrix/synapse/workers/module.nix
@@ -1,12 +1,20 @@
 { config, lib, ... }:
 let
   cfg = config.services.matrix-synapse;
+  mkIntOption =
+    description:
+    lib.mkOption {
+      type = lib.types.int;
+      default = 0;
+      description = description;
+    };
 in
-
 {
   imports = [
-    ./appservice.nix
-    ./background.nix
+    ./single/appservice.nix
+    ./single/background.nix
+    ./single/user-dir.nix
+    ./auth.nix
     ./client-reader.nix
     ./federation-inbound.nix
     ./federation-reader.nix
@@ -14,86 +22,46 @@ in
     ./media-repo.nix
     ./pusher.nix
     ./sync.nix
-    ./user-dir.nix
 
     ./stream-writers/event-stream-writer.nix
   ];
-  options.services.matrix-synapse =
-    lib.listToAttrs (
-      lib.map
-        (option: {
-          name = "${option}StreamWriters";
-          value = lib.mkOption {
-            type = lib.types.int;
-            default = 0;
-            description = "Number of writers for ${option} streams";
-          };
-        })
-        [
-          "event"
-          "typing"
-          "toDevice"
-          "accountData"
-          "receipts"
-          "presence"
-          "pushRule"
-        ]
-    )
-    // {
-      enableWorkers = lib.mkEnableOption "Enable dedicated workers";
-      enableStreamWriters = lib.mkEnableOption "Enable stream writers";
-      enableAppserviceWorker = lib.mkEnableOption "Enable dedicated appservice worker";
-      enableBackgroundWorker = lib.mkEnableOption "Enable dedicated background task worker";
-      enableUserDirWorker = lib.mkEnableOption "Enable dedicated user directory worker";
+  options.services.matrix-synapse = {
+    enableWorkers = lib.mkEnableOption "Enable dedicated workers";
+    enableStreamWriters = lib.mkEnableOption "Enable stream writers";
+    enableAppserviceWorker = lib.mkEnableOption "Enable dedicated appservice worker";
+    enableBackgroundWorker = lib.mkEnableOption "Enable dedicated background task worker";
+    enableUserDirWorker = lib.mkEnableOption "Enable dedicated user directory worker";
 
-      federationSenders = lib.mkOption {
-        type = lib.types.int;
-        default = 0;
-        description = "Number of federation senders";
-      };
-      pushers = lib.mkOption {
-        type = lib.types.int;
-        default = 0;
-        description = "Number of pushers";
-      };
-      mediaRepoWorkers = lib.mkOption {
-        type = lib.types.int;
-        default = 0;
-        description = "Number of media repo workers";
-      };
-      syncWorkers = lib.mkOption {
-        type = lib.types.int;
-        default = 0;
-        description = "Number of sync workers";
-      };
-      clientReaders = lib.mkOption {
-        type = lib.types.int;
-        default = 0;
-        description = "Number of client readers";
-      };
-      federationReaders = lib.mkOption {
-        type = lib.types.int;
-        default = 0;
-        description = "Number of federation readers";
-      };
-      federationInboundWorkers = lib.mkOption {
-        type = lib.types.int;
-        default = 0;
-        description = "Number of federation inbound workers";
-      };
+    authWorkers = mkIntOption "Number of auth workers";
+    federationSenders = mkIntOption "Number of federation senders";
+    pushers = mkIntOption "Number of pushers";
+    mediaRepoWorkers = mkIntOption "Number of media repo workers";
+    syncWorkers = mkIntOption "Number of sync workers";
+    clientReaders = mkIntOption "Number of client readers";
+    federationReaders = mkIntOption "Number of federation readers";
+    federationInboundWorkers = mkIntOption "Number of federation inbound workers";
 
-      nginxVirtualHostName = lib.mkOption {
-        type = lib.types.str;
-        default = null;
-        description = "The virtual host name for the nginx server";
-      };
+    #stream writers
+    eventStreamWriters = mkIntOption "Number of event stream writers";
+    typingStreamWriters = mkIntOption "Number of typing stream writers";
+    toDeviceStreamWriters = mkIntOption "Number of to_device stream writers";
+    accountDataStreamWriters = mkIntOption "Number of account data stream writers";
+    receiptsStreamWriters = mkIntOption "Number of read receipt stream writers";
+    presenceStreamWriters = mkIntOption "Number of presence stream writers";
+    pushRuleStreamWriters = mkIntOption "Number of push rule stream writers";
+
+    nginxVirtualHostName = lib.mkOption {
+      type = lib.types.str;
+      default = null;
+      description = "The virtual host name for the nginx server";
     };
+  };
 
   config = {
     assertions = [
       {
-        assertion = cfg.enableUserDirWorker -> cfg.nginxVirtualHostName != null;
-        message = "nginxVirtualHostName must be set when enableUserDirWorker is true";
+        assertion = cfg.enableWorkers -> cfg.nginxVirtualHostName != null;
+        message = "nginxVirtualHostName must be set when enableWorkers is true";
       }
     ];
   };
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/pusher.nix b/host/Rory-nginx/services/matrix/synapse/workers/pusher.nix
index 3391171..ad0d5d6 100644
--- a/host/Rory-nginx/services/matrix/synapse/workers/pusher.nix
+++ b/host/Rory-nginx/services/matrix/synapse/workers/pusher.nix
@@ -1,6 +1,9 @@
 { config, lib, ... }:
 let
   cfg = config.services.matrix-synapse;
+  dbGroup = "small";
+  hasClientResource = false;
+  hasFederationResource = false;
   pushers = lib.range 0 (cfg.pushers - 1);
   workerName = "pusher";
   workerRoutes = [ ];
@@ -40,8 +43,8 @@ in
             ];
             database = (
               import ../db.nix {
+                inherit dbGroup;
                 workerName = "${workerName}-${toString index}";
-                dbGroup = "small";
               }
             );
           };
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/single/appservice.nix b/host/Rory-nginx/services/matrix/synapse/workers/single/appservice.nix
new file mode 100644
index 0000000..ace3bf6
--- /dev/null
+++ b/host/Rory-nginx/services/matrix/synapse/workers/single/appservice.nix
@@ -0,0 +1,79 @@
+{ config, lib, ... }:
+
+let
+  cfg = config.services.matrix-synapse;
+  dbGroup = "small";
+  hasClientResource = false;
+  hasFederationResource = false;
+  workerName = "appservice";
+  workerRoutes = [ ];
+in
+{
+  config = lib.mkIf cfg.enableAppserviceWorker {
+    services.matrix-synapse = {
+      settings = {
+        instance_map = {
+          ${workerName} = {
+            path = "/run/matrix-synapse/${workerName}.sock";
+          };
+        };
+
+        notify_appservices_from_worker = workerName;
+      };
+
+      workers = {
+        ${workerName} = {
+          worker_app = "synapse.app.generic_worker";
+          worker_listeners =
+            [
+              {
+                type = "http";
+                path = "/run/matrix-synapse/${workerName}.sock";
+                resources = [
+                  {
+                    names = [ "replication" ];
+                    compress = false;
+                  }
+                ];
+              }
+            ]
+            ++ lib.optional hasClientResource {
+              type = "http";
+              path = "/run/matrix-synapse/${workerName}-client.sock";
+              mode = "666";
+              resources = [
+                {
+                  names = [ "client" ];
+                  compress = false;
+                }
+              ];
+            }
+            ++ lib.optional hasFederationResource {
+              type = "http";
+              path = "/run/matrix-synapse/${workerName}-federation.sock";
+              mode = "666";
+              resources = [
+                {
+                  names = [ "federation" ];
+                  compress = false;
+                }
+              ];
+            };
+
+          database = (import ../../db.nix { inherit workerName dbGroup; });
+        };
+      };
+    };
+
+    services.nginx = {
+      virtualHosts."${cfg.nginxVirtualHostName}".locations = lib.listToAttrs (
+        lib.map (route: {
+          name = route;
+          value = {
+            proxyPass = "http://${workerName}";
+          };
+        }) workerRoutes
+      );
+    };
+  };
+}
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/single/background.nix b/host/Rory-nginx/services/matrix/synapse/workers/single/background.nix
new file mode 100644
index 0000000..acc423d
--- /dev/null
+++ b/host/Rory-nginx/services/matrix/synapse/workers/single/background.nix
@@ -0,0 +1,79 @@
+{ config, lib, ... }:
+
+let
+  cfg = config.services.matrix-synapse;
+  dbGroup = "small";
+  hasClientResource = false;
+  hasFederationResource = false;
+  workerName = "background";
+  workerRoutes = [ ];
+in
+{
+  config = lib.mkIf cfg.enableBackgroundWorker {
+    services.matrix-synapse = {
+      settings = {
+        instance_map = {
+          ${workerName} = {
+            path = "/run/matrix-synapse/${workerName}.sock";
+          };
+        };
+
+        run_background_tasks_on = workerName;
+      };
+
+      workers = {
+        ${workerName} = {
+          worker_app = "synapse.app.generic_worker";
+          worker_listeners =
+            [
+              {
+                type = "http";
+                path = "/run/matrix-synapse/${workerName}.sock";
+                resources = [
+                  {
+                    names = [ "replication" ];
+                    compress = false;
+                  }
+                ];
+              }
+            ]
+            ++ lib.optional hasClientResource {
+              type = "http";
+              path = "/run/matrix-synapse/${workerName}-client.sock";
+              mode = "666";
+              resources = [
+                {
+                  names = [ "client" ];
+                  compress = false;
+                }
+              ];
+            }
+            ++ lib.optional hasFederationResource {
+              type = "http";
+              path = "/run/matrix-synapse/${workerName}-federation.sock";
+              mode = "666";
+              resources = [
+                {
+                  names = [ "federation" ];
+                  compress = false;
+                }
+              ];
+            };
+
+          database = (import ../../db.nix { inherit workerName dbGroup; });
+        };
+      };
+    };
+
+    services.nginx = {
+      virtualHosts."${cfg.nginxVirtualHostName}".locations = lib.listToAttrs (
+        lib.map (route: {
+          name = route;
+          value = {
+            proxyPass = "http://${workerName}";
+          };
+        }) workerRoutes
+      );
+    };
+  };
+}
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/single/user-dir.nix b/host/Rory-nginx/services/matrix/synapse/workers/single/user-dir.nix
new file mode 100644
index 0000000..0253438
--- /dev/null
+++ b/host/Rory-nginx/services/matrix/synapse/workers/single/user-dir.nix
@@ -0,0 +1,83 @@
+{ config, lib, ... }:
+
+let
+  cfg = config.services.matrix-synapse;
+  dbGroup = "solo";
+  hasClientResource = true;
+  hasFederationResource = false;
+  workerName = "user_dir";
+  workerRoutes = [
+    "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/user_directory/search$"
+    "~ ^/_matrix/client/v3/profile/.*/(displayname|avatar_url)$"
+    "~ ^/_matrix/client/v3/profile/.*$"
+  ];
+in
+{
+  config = lib.mkIf cfg.enableUserDirWorker {
+    services.matrix-synapse = {
+      settings = {
+        instance_map = {
+          ${workerName} = {
+            path = "/run/matrix-synapse/${workerName}.sock";
+          };
+        };
+
+        update_user_directory_from_worker = workerName;
+      };
+
+      workers = {
+        ${workerName} = {
+          worker_app = "synapse.app.generic_worker";
+          worker_listeners =
+            [
+              {
+                type = "http";
+                path = "/run/matrix-synapse/${workerName}.sock";
+                resources = [
+                  {
+                    names = [ "replication" ];
+                    compress = false;
+                  }
+                ];
+              }
+            ]
+            ++ lib.optional hasClientResource {
+              type = "http";
+              path = "/run/matrix-synapse/${workerName}-client.sock";
+              mode = "666";
+              resources = [
+                {
+                  names = [ "client" ];
+                  compress = false;
+                }
+              ];
+            }
+            ++ lib.optional hasFederationResource {
+              type = "http";
+              path = "/run/matrix-synapse/${workerName}-federation.sock";
+              mode = "666";
+              resources = [
+                {
+                  names = [ "federation" ];
+                  compress = false;
+                }
+              ];
+            };
+
+          database = (import ../../db.nix { inherit workerName dbGroup; });
+        };
+      };
+    };
+
+    services.nginx = {
+      virtualHosts."${cfg.nginxVirtualHostName}".locations = lib.listToAttrs (
+        lib.map (route: {
+          name = route;
+          value = {
+            proxyPass = "http://${workerName}";
+          };
+        }) workerRoutes
+      );
+    };
+  };
+}
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/sync.nix b/host/Rory-nginx/services/matrix/synapse/workers/sync.nix
index 579e14b..2655ff3 100644
--- a/host/Rory-nginx/services/matrix/synapse/workers/sync.nix
+++ b/host/Rory-nginx/services/matrix/synapse/workers/sync.nix
@@ -2,9 +2,12 @@
 
 let
   cfg = config.services.matrix-synapse;
+  dbGroup = "small";
+  hasClientResource = false;
+  hasFederationResource = false;
   workers = lib.range 0 (cfg.syncWorkers - 1);
   workerName = "sync";
-  routes = [
+  workerRoutes = [
     "~ ^/_matrix/client/(v2_alpha|r0|v3)/sync$"
     "~ ^/_matrix/client/(api/v1|v2_alpha|r0|v3)/events$"
     "~ ^/_matrix/client/(api/v1|r0|v3)/initialSync$"
@@ -55,8 +58,8 @@ in
             ];
             database = (
               import ../db.nix {
+                inherit dbGroup;
                 workerName = "${workerName}-${toString index}";
-                dbGroup = "small";
               }
             );
           };
@@ -84,7 +87,7 @@ in
         value = {
           proxyPass = "http://${workerName}";
         };
-      }) routes
+      }) workerRoutes
     );
   };
 }
diff --git a/host/Rory-nginx/services/matrix/synapse/workers/user-dir.nix b/host/Rory-nginx/services/matrix/synapse/workers/user-dir.nix
deleted file mode 100644
index f8d118e..0000000
--- a/host/Rory-nginx/services/matrix/synapse/workers/user-dir.nix
+++ /dev/null
@@ -1,68 +0,0 @@
-{
-  config,
-  pkgs,
-  lib,
-  ...
-}:
-
-let
-  cfg = config.services.matrix-synapse;
-  workerName = "user_dir";
-  workerRoutes = [ "~ ^/_matrix/client/(api/v1|r0|v3|unstable)/user_directory/search$" ];
-in
-{
-  config = lib.mkIf cfg.enableUserDirWorker {
-    services.matrix-synapse = {
-      settings = {
-        instance_map = {
-          user_dir = {
-            path = "/run/matrix-synapse/user_dir.sock";
-          };
-        };
-
-        update_user_directory_from_worker = workerName;
-      };
-
-      workers = {
-        user_dir = {
-          worker_app = "synapse.app.generic_worker";
-          worker_listeners = [
-            {
-              type = "http";
-              path = "/run/matrix-synapse/${workerName}.sock";
-              resources = [
-                {
-                  names = [ "replication" ];
-                  compress = false;
-                }
-              ];
-            }
-            {
-              type = "http";
-              path = "/run/matrix-synapse/${workerName}-client.sock";
-              mode = "666";
-              resources = [
-                {
-                  names = [ "client" ];
-                  compress = false;
-                }
-              ];
-            }
-          ];
-          database = (
-            import ../db.nix {
-              workerName = "user_dir";
-              dbGroup = "small";
-            }
-          );
-        };
-      };
-    };
-
-    services.nginx.virtualHosts."${cfg.nginxVirtualHostName}" = {
-      locations."~ ^/_matrix/client/(api/v1|r0|v3|unstable)/user_directory/search$" = {
-        proxyPass = "http://unix:/run/matrix-synapse/user_dir-client.sock";
-      };
-    };
-  };
-}