summaryrefslogtreecommitdiffstats
path: root/nixos/modules/services/matrix
diff options
context:
space:
mode:
authorMartin Weinelt <hexa@darmstadt.ccc.de>2024-02-03 23:19:58 +0100
committerMartin Weinelt <hexa@darmstadt.ccc.de>2024-02-09 16:05:05 +0100
commit143d266f0db386af987d19e0de79128bc8669714 (patch)
treee92edb8babb273402298c0e9b5e3409f4e4abcfc /nixos/modules/services/matrix
parent2565ab7b53ae6966bd08e68203a89645961849b3 (diff)
nixos/matrix-synapse: add UNIX domain socket listener support
Exposes two options, `path` and `mode`, to configure the location and permissions on the socket file. The `mode` needs to be specified as string in octal and will be converted into a decimal integer, so it correctly passes through the YAML parser and arrives at the `os.chmod` call in the Twisted codebase. What a fun detour. Adds an assertion, that either `path` or `bind_addresses` and `port` are configured on every listener. Migrates the default replication listener of the main instance to a UNIX domain socket, because it is more efficient. Introduces the `enableRegistrationScript` option, to gracefully disable the user registration script, when the client listener listens on a UNIX domain socket, which is something the script does not support.
Diffstat (limited to 'nixos/modules/services/matrix')
-rw-r--r--nixos/modules/services/matrix/synapse.md5
-rw-r--r--nixos/modules/services/matrix/synapse.nix156
2 files changed, 140 insertions, 21 deletions
diff --git a/nixos/modules/services/matrix/synapse.md b/nixos/modules/services/matrix/synapse.md
index f270be8c8d78..9c9c025fc5f5 100644
--- a/nixos/modules/services/matrix/synapse.md
+++ b/nixos/modules/services/matrix/synapse.md
@@ -126,8 +126,9 @@ then enable `services.matrix-synapse.settings.enable_registration = true;`.
Otherwise, or you can generate a registration secret with
{command}`pwgen -s 64 1` and set it with
[](#opt-services.matrix-synapse.settings.registration_shared_secret).
-To create a new user or admin, run the following after you have set the secret
-and have rebuilt NixOS:
+To create a new user or admin from the terminal your client listener
+must be configured to use TCP sockets. Then you can run the following
+after you have set the secret and have rebuilt NixOS:
```ShellSession
$ nix-shell -p matrix-synapse
$ register_new_matrix_user -k your-registration-shared-secret http://localhost:8008
diff --git a/nixos/modules/services/matrix/synapse.nix b/nixos/modules/services/matrix/synapse.nix
index 4c1c396eac05..a6304d353387 100644
--- a/nixos/modules/services/matrix/synapse.nix
+++ b/nixos/modules/services/matrix/synapse.nix
@@ -105,6 +105,19 @@ let
SYSLOG_IDENTIFIER = logName;
};
});
+
+ toIntBase8 = str:
+ lib.pipe str [
+ lib.stringToCharacters
+ (map lib.toInt)
+ (lib.foldl (acc: digit: acc * 8 + digit) 0)
+ ];
+
+ toDecimalFilePermission = value:
+ if value == null then
+ null
+ else
+ toIntBase8 value;
in {
imports = [
@@ -192,10 +205,11 @@ in {
];
options = let
- listenerType = workerContext: types.submodule {
+ listenerType = workerContext: types.submodule ({ config, ... }: {
options = {
port = mkOption {
- type = types.port;
+ type = types.nullOr types.port;
+ default = null;
example = 8448;
description = lib.mdDoc ''
The port to listen for HTTP(S) requests on.
@@ -203,11 +217,20 @@ in {
};
bind_addresses = mkOption {
- type = types.listOf types.str;
- default = [
+ type = types.nullOr (types.listOf types.str);
+ default = if config.path != null then null else [
"::1"
"127.0.0.1"
];
+ defaultText = literalExpression ''
+ if path != null then
+ null
+ else
+ [
+ "::1"
+ "127.0.0.1"
+ ]
+ '';
example = literalExpression ''
[
"::"
@@ -219,6 +242,35 @@ in {
'';
};
+ path = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = ''
+ Unix domain socket path to bind this listener to.
+
+ ::: {.note}
+ This option is incompatible with {option}`bind_addresses`, {option}`port`, {option}`tls`
+ and also does not support the `metrics` and `manhole` listener {option}`type`.
+ :::
+ '';
+ };
+
+ mode = mkOption {
+ type = types.nullOr (types.strMatching "^[0,2-7]{3,4}$");
+ default = if config.path != null then "660" else null;
+ defaultText = literalExpression ''
+ if path != null then
+ "660"
+ else
+ null
+ '';
+ example = "660";
+ description = ''
+ File permissions on the UNIX domain socket.
+ '';
+ apply = toDecimalFilePermission;
+ };
+
type = mkOption {
type = types.enum [
"http"
@@ -234,17 +286,30 @@ in {
};
tls = mkOption {
- type = types.bool;
- default = !workerContext;
+ type = types.nullOr types.bool;
+ default = if config.path != null then
+ null
+ else
+ !workerContext;
+ defaultText = ''
+ Enabled for the main instance listener, unless it is configured with a UNIX domain socket path.
+ '';
example = false;
description = lib.mdDoc ''
Whether to enable TLS on the listener socket.
+
+ ::: {.note}
+ This option will be ignored for UNIX domain sockets.
+ :::
'';
};
x_forwarded = mkOption {
type = types.bool;
- default = false;
+ default = config.path != null;
+ defaultText = ''
+ Enabled if the listener is configured with a UNIX domain socket path
+ '';
example = true;
description = lib.mdDoc ''
Use the X-Forwarded-For (XFF) header as the client IP and not the
@@ -291,11 +356,28 @@ in {
'';
};
};
- };
+ });
in {
services.matrix-synapse = {
enable = mkEnableOption (lib.mdDoc "matrix.org synapse");
+ enableRegistrationScript = mkOption {
+ type = types.bool;
+ default = clientListener.bind_addresses != [];
+ example = false;
+ defaultText = ''
+ Enabled if the client listener uses TCP sockets
+ '';
+ description = ''
+ Whether to install the `register_new_matrix_user` script, that
+ allows account creation on the terminal.
+
+ ::: {.note}
+ This script does not work when the client listener uses UNIX domain sockets
+ :::
+ '';
+ };
+
serviceUnit = lib.mkOption {
type = lib.types.str;
readOnly = true;
@@ -616,11 +698,8 @@ in {
compress = false;
}];
}] ++ lib.optional hasWorkers {
- port = 9093;
- bind_addresses = [ "127.0.0.1" ];
+ path = "/run/matrix-synapse/main_replication.sock";
type = "http";
- tls = false;
- x_forwarded = false;
resources = [{
names = [ "replication" ];
compress = false;
@@ -630,7 +709,7 @@ in {
List of ports that Synapse should listen on, their purpose and their configuration.
By default, synapse will be configured for client and federation traffic on port 8008, and
- for worker replication traffic on port 9093. See [`services.matrix-synapse.workers`](#opt-services.matrix-synapse.workers)
+ use a UNIX domain socket for worker replication. See [`services.matrix-synapse.workers`](#opt-services.matrix-synapse.workers)
for more details.
'';
};
@@ -1006,9 +1085,15 @@ in {
listener = lib.findFirst
(
listener:
- listener.port == main.port
+ (
+ lib.hasAttr "port" main && listener.port or null == main.port
+ || lib.hasAttr "path" main && listener.path or null == main.path
+ )
&& listenerSupportsResource "replication" listener
- && (lib.any (bind: bind == main.host || bind == "0.0.0.0" || bind == "::") listener.bind_addresses)
+ && (
+ lib.hasAttr "host" main && lib.any (bind: bind == main.host || bind == "0.0.0.0" || bind == "::") listener.bind_addresses
+ || lib.hasAttr "path" main
+ )
)
null
cfg.settings.listeners;
@@ -1022,15 +1107,44 @@ in {
This is done by default unless you manually configure either of those settings.
'';
}
- ];
+ {
+ assertion = cfg.enableRegistrationScript -> clientListener.path == null;
+ message = ''
+ The client listener on matrix-synapse is configured to use UNIX domain sockets.
+ This configuration is incompatible with the `register_new_matrix_user` script.
+
+ Disable `services.mastrix-synapse.enableRegistrationScript` to continue.
+ '';
+ }
+ ]
+ ++ (map (listener: {
+ assertion = (listener.path == null) != (listener.bind_addresses == null);
+ message = ''
+ Listeners require either a UNIX domain socket `path` or `bind_addresses` for a TCP socket.
+ '';
+ }) cfg.settings.listeners)
+ ++ (map (listener: {
+ assertion = listener.path != null -> (listener.bind_addresses == null && listener.port == null && listener.tls == null);
+ message = let
+ formatKeyValue = key: value: lib.optionalString (value != null) " - ${key}=${toString value}\n";
+ in ''
+ Listener configured with UNIX domain socket (${toString listener.path}) ignores the following options:
+ ${formatKeyValue "bind_addresses" listener.bind_addresses}${formatKeyValue "port" listener.port}${formatKeyValue "tls" listener.tls}
+ '';
+ }) cfg.settings.listeners)
+ ++ (map (listener: {
+ assertion = listener.path == null || listener.type == "http";
+ message = ''
+ Listener configured with UNIX domain socket (${toString listener.path}) only supports the "http" listener type.
+ '';
+ }) cfg.settings.listeners);
services.matrix-synapse.settings.redis = lib.mkIf cfg.configureRedisLocally {
enabled = true;
path = config.services.redis.servers.matrix-synapse.unixSocket;
};
services.matrix-synapse.settings.instance_map.main = lib.mkIf hasWorkers (lib.mkDefault {
- host = "127.0.0.1";
- port = 9093;
+ path = "/run/matrix-synapse/main_replication.sock";
});
services.matrix-synapse.serviceUnit = if hasWorkers then "matrix-synapse.target" else "matrix-synapse.service";
@@ -1086,6 +1200,8 @@ in {
User = "matrix-synapse";
Group = "matrix-synapse";
WorkingDirectory = cfg.dataDir;
+ RuntimeDirectory = "matrix-synapse";
+ RuntimeDirectoryPreserve = true;
ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID";
Restart = "on-failure";
UMask = "0077";
@@ -1178,7 +1294,9 @@ in {
user = "matrix-synapse";
};
- environment.systemPackages = [ registerNewMatrixUser ];
+ environment.systemPackages = lib.optionals cfg.enableRegistrationScript [
+ registerNewMatrixUser
+ ];
};
meta = {