Merge pull request #286172 from mweinelt/matrix-uds-listeners
nixos/matrix-synapse: Add UNIX domain socket listener support
This commit is contained in:
commit
bd8acd0141
3 changed files with 152 additions and 22 deletions
|
@ -246,6 +246,9 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
|
|||
- `services.postgresql.extraPlugins` changed its type from just a list of packages to also a function that returns such a list.
|
||||
For example a config line like ``services.postgresql.extraPlugins = with pkgs.postgresql_11.pkgs; [ postgis ];`` is recommended to be changed to ``services.postgresql.extraPlugins = ps: with ps; [ postgis ];``;
|
||||
|
||||
- The Matrix homeserver [Synapse](https://element-hq.github.io/synapse/) module now supports configuring UNIX domain socket [listeners](#opt-services.matrix-synapse.settings.listeners) through the `path` option.
|
||||
The default replication worker on the main instance has been migrated away from TCP sockets to UNIX domain sockets.
|
||||
|
||||
- Programs written in [Nim](https://nim-lang.org/) are built with libraries selected by lockfiles.
|
||||
The `nimPackages` and `nim2Packages` sets have been removed.
|
||||
See https://nixos.org/manual/nixpkgs/unstable#nim for more information.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -6,8 +6,16 @@ let
|
|||
cfg = config.services.matrix-synapse;
|
||||
format = pkgs.formats.yaml { };
|
||||
|
||||
filterRecursiveNull = o:
|
||||
if isAttrs o then
|
||||
mapAttrs (_: v: filterRecursiveNull v) (filterAttrs (_: v: v != null) o)
|
||||
else if isList o then
|
||||
map filterRecursiveNull (filter (v: v != null) o)
|
||||
else
|
||||
o;
|
||||
|
||||
# remove null values from the final configuration
|
||||
finalSettings = lib.filterAttrsRecursive (_: v: v != null) cfg.settings;
|
||||
finalSettings = filterRecursiveNull cfg.settings;
|
||||
configFile = format.generate "homeserver.yaml" finalSettings;
|
||||
|
||||
usePostgresql = cfg.settings.database.name == "psycopg2";
|
||||
|
@ -105,6 +113,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 +213,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 +225,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 +250,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 +294,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 +364,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 +706,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 +717,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 +1093,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 +1115,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 +1208,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 +1302,9 @@ in {
|
|||
user = "matrix-synapse";
|
||||
};
|
||||
|
||||
environment.systemPackages = [ registerNewMatrixUser ];
|
||||
environment.systemPackages = lib.optionals cfg.enableRegistrationScript [
|
||||
registerNewMatrixUser
|
||||
];
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
|
Loading…
Reference in a new issue