1
2
mirror of https://github.com/dali99/nixos-matrix-modules.git synced 2026-01-18 13:38:22 +01:00

Compare commits

...

21 Commits

Author SHA1 Message Date
82959f612f Merge pull request #10 from h7x4/additional-nixpkgs-2511-stuff
Additional fixes for 25.11
2025-12-08 18:16:53 +01:00
51665e27e2 tests/nginx-pipeline: move to checks, fix nix flake show 2025-12-09 01:39:12 +09:00
700aa1b8a6 flake.nix: bump nixpkgs target from 23.11 -> 25.11 2025-12-09 01:38:41 +09:00
a82c7e2d94 treewide: toGNUCommandLineShell -> toCommandLineShellGNU 2025-12-09 01:34:24 +09:00
8493e635fa synapse-module: source kill from coreutils 2025-12-09 01:33:07 +09:00
25b9f31ef1 Update MIGRATIONS.MD for version 0.8.0 changes
Added migration notes for version 0.8.0 regarding saml2 deprecation and its alternatives.
2025-12-04 11:28:15 +01:00
19c690bb4f Remove 'saml2' from extras as it is broken 2025-12-01 01:10:31 +01:00
099db715d1 synapse: Remove removed extra feature 2025-07-22 22:35:55 +02:00
da9dc0479f sliding-sync: remove 2025-01-02 23:34:05 +01:00
ff787d410c Add documentation for new sliding-sync setup and upgrade info 2024-09-27 06:21:37 +02:00
f8843835e2 sliding-sync: deprecate 2024-09-27 06:09:23 +02:00
f4e20d0360 Update README.MD 2024-08-29 10:32:38 +02:00
d7dc42c9bb sliding-sync: make enableAcme lib.mkDefault to match synapse 2024-06-01 11:39:05 +02:00
61b366f5f6 migrate to ensureDBOwnership 2024-06-01 11:11:14 +02:00
6c9b67974b fix generating multiple upstreams of same type 2024-03-13 07:39:59 +01:00
19b85a2562 Merge pull request #7 from dali99/refactor-nginx-upstream-generation
refactor nginx upstream generation, add support for unix sockets
2024-03-13 06:23:07 +01:00
d48997cfb4 generate only one upstream per worker 2024-03-13 06:22:24 +01:00
b8d7c76a7e treewide: add support for unix sockets 2024-01-27 07:52:26 +01:00
19d50fae63 nginx-pipeline: add basic test 2024-01-27 07:52:26 +01:00
18d3b34406 nginx: refactor upstream generation 2024-01-27 07:52:25 +01:00
85804fce8d lib: fix bug where lib.throw does not exist 2024-01-27 07:40:40 +01:00
13 changed files with 306 additions and 234 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
result

View File

@@ -2,6 +2,17 @@
This is a best effort document descibing neccecary changes you might have to do when updating
## 0.8.0
`saml2` is no longer enabled, as it depends on vulnerable dependencies and isnt really built in nixpks anymore.
If you need to authenticate with saml, you should deploy some sort of saml to openid bridge, instead.
## 0.6.1
enableSlidingSync, and setting matrix-synapse.sliding-sync.environmentFile (or any other sliding-sync setting)
is no longer needed for a sliding-sync setup. Upgrading will force relogins for all users.
## 0.5.0
* The module has been renamed from `synapse` to `default`

View File

@@ -1,3 +1,5 @@
For support and requests feel free to join [#nixos-matrix-modules:dodsorf.as](https://matrix.to/#/#nixos-matrix-modules:dodsorf.as), [uri](matrix:r/nixos-matrix-modules:dodsorf.as)
With matrix.YOURDOMAIN pointing at the server:
```
@@ -36,19 +38,3 @@ With matrix.YOURDOMAIN pointing at the server:
```
is ~enough to get a functional matrix-server running with some workers
## Sliding Sync (Element X)
Just add the following to your config and point `slidingsync.YOURDOMAIN` at the server
```
services.matrix-synapse-next = {
enableSlidingSync = true;
};
services.matrix-synapse.sliding-sync.environmentFile = "/some/file/containing/SYNCV3_SECRET=<some secret>";
```
If using [well-known delagation](https://matrix-org.github.io/synapse/v1.37/delegate.html) make sure `YOURDOMAIN/.well-known/matrix/client` matches
what's in `matrix.YOURDOMAIN/.well-known/matrix/client`

20
flake.lock generated
View File

@@ -1,23 +1,23 @@
{
"nodes": {
"nixpkgs-lib": {
"nixpkgs": {
"locked": {
"lastModified": 1673743903,
"narHash": "sha256-sloY6KYyVOozJ1CkbgJPpZ99TKIjIvM+04V48C04sMQ=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "7555e2dfcbac1533f047021f1744ac8871150f9f",
"lastModified": 1764983851,
"narHash": "sha256-y7RPKl/jJ/KAP/VKLMghMgXTlvNIJMHKskl8/Uuar7o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d9bc5c7dceb30d8d6fafa10aeb6aa8a48c218454",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
"id": "nixpkgs",
"ref": "nixos-25.11",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
"nixpkgs": "nixpkgs"
}
}
},

View File

@@ -2,13 +2,31 @@
description = "NixOS modules for matrix related services";
inputs = {
nixpkgs-lib.url = github:nix-community/nixpkgs.lib;
nixpkgs.url = "nixpkgs/nixos-25.11";
};
outputs = { self, nixpkgs-lib }: {
outputs = { self, nixpkgs }: {
nixosModules = {
default = import ./module.nix;
};
lib = import ./lib.nix { lib = nixpkgs-lib.lib; };
lib = import ./lib.nix { lib = nixpkgs.lib; };
checks = let
forAllSystems = f:
nixpkgs.lib.genAttrs [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
] (system: f nixpkgs.legacyPackages.${system});
in forAllSystems (pkgs: let
tests = import ./tests {
inherit nixpkgs pkgs;
matrix-lib = self.lib;
};
in {
inherit (tests) nginx-pipeline-eval;
});
};
}

62
lib.nix
View File

@@ -4,7 +4,7 @@ rec {
isListenerType = type: l: lib.any (r: lib.any (n: n == type) r.names) l.resources;
# Get the first listener that includes the given resource from worker
firstListenerOfType = type: ls: lib.lists.findFirst (isListenerType type)
(lib.throw "No listener with resource: ${type} configured")
(throw "No listener with resource: ${type} configured")
ls;
# Get an attrset of the host and port from a listener
connectionInfo = l: {
@@ -17,4 +17,64 @@ rec {
l = firstListenerOfType r w.settings.worker_listeners;
in connectionInfo l;
mapWorkersToUpstreamsByType = workerInstances:
lib.pipe workerInstances [
lib.attrValues
# Index by worker type
(lib.foldl (acc: worker: acc // {
${worker.type} = (acc.${worker.type} or [ ]) ++ [ worker ];
}) { })
# Subindex by resource names, listener types, and convert to upstreams
(lib.mapAttrs (_: workers: lib.pipe workers [
(lib.concatMap (worker: [ (lib.lists.head worker.settings.worker_listeners) ]))
lib.flatten
mapListenersToUpstreamsByType
]))
];
mapListenersToUpstreamsByType = listenerInstances:
lib.pipe listenerInstances [
# Index by resource names
(lib.concatMap (listener: lib.pipe listener [
(listener: let
allResourceNames = lib.pipe listener.resources [
(map (resource: resource.names))
lib.flatten
lib.unique
];
in if allResourceNames == [ ]
then { "empty" = listener; }
else lib.genAttrs allResourceNames (_: listener))
lib.attrsToList
]))
(lib.foldl (acc: listener: acc // {
${listener.name} = (acc.${listener.name} or [ ]) ++ [ listener.value ];
}) { })
# Index by listener type
(lib.mapAttrs (_:
(lib.foldl (acc: listener: acc // {
${listener.type} = (acc.${listener.type} or [ ]) ++ [ listener ];
}) { })
))
# Convert listeners to upstream URIs
(lib.mapAttrs (_:
(lib.mapAttrs (_: listeners:
lib.pipe listeners [
(lib.concatMap (listener:
if listener.path != null
then [ "unix:${listener.path}" ]
else (map (addr: "${addr}:${toString listener.port}") listener.bind_addresses)
))
# NOTE: Adding ` = { }` to every upstream might seem unnecessary in isolation,
# but it makes it easier to set upstreams in the nginx module.
(uris: lib.genAttrs uris (_: { }))
]
))
))
];
}

View File

@@ -1,8 +1,14 @@
{ ... }:
{ lib, ... }:
{
imports = [
./synapse-module
./sliding-sync
# TODO: Remove after 25.05
(lib.mkRemovedOptionModule [ "services" "matrix-synapse" "sliding-sync" ] ''
`services.matrix-synapse.sliding-sync` is no longer necessary to use sliding-sync with synapse.
As synapse now includes this in itself, if you have a manually managed `.well-known/matrix/client` file
remove the proxy url from it.
'')
];
}

View File

@@ -1,117 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.matrix-synapse.sliding-sync;
in
{
disabledModules = [ "services/matrix/matrix-sliding-sync.nix" ];
options.services.matrix-synapse.sliding-sync = {
enable = lib.mkEnableOption (lib.mdDoc "sliding sync");
package = lib.mkOption {
type = lib.types.package;
default = pkgs.matrix-sliding-sync;
description = "What package to use for the sliding-sync proxy.";
};
enableNginx = lib.mkEnableOption (lib.mdDoc "autogenerated nginx config");
publicBaseUrl = lib.mkOption {
type = lib.types.str;
description = "The domain where clients connect, only has an effect with enableNginx";
example = "slidingsync.matrix.org";
};
settings = lib.mkOption {
type = lib.types.submodule {
freeformType = with lib.types; attrsOf str;
options = {
SYNCV3_SERVER = lib.mkOption {
type = lib.types.str;
description = lib.mdDoc ''
The destination homeserver to talk to not including `/_matrix/` e.g `https://matrix.example.org`.
'';
};
SYNCV3_DB = lib.mkOption {
type = lib.types.str;
default = "postgresql:///matrix-sliding-sync?host=/run/postgresql";
description = lib.mdDoc ''
The postgres connection string.
Refer to <https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING>.
'';
};
SYNCV3_BINDADDR = lib.mkOption {
type = lib.types.str;
default = "127.0.0.1:8009";
example = "[::]:8008";
description = lib.mdDoc "The interface and port to listen on.";
};
SYNCV3_LOG_LEVEL = lib.mkOption {
type = lib.types.enum [ "trace" "debug" "info" "warn" "error" "fatal" ];
default = "info";
description = lib.mdDoc "The level of verbosity for messages logged.";
};
};
};
default = { };
description = ''
Freeform environment variables passed to the sliding sync proxy.
Refer to <https://github.com/matrix-org/sliding-sync#setup> for all supported values.
'';
};
createDatabase = lib.mkOption {
type = lib.types.bool;
default = true;
description = lib.mdDoc ''
Whether to enable and configure `services.postgres` to ensure that the database user `matrix-sliding-sync`
and the database `matrix-sliding-sync` exist.
'';
};
environmentFile = lib.mkOption {
type = lib.types.str;
description = lib.mdDoc ''
Environment file as defined in {manpage}`systemd.exec(5)`.
This must contain the {env}`SYNCV3_SECRET` variable which should
be generated with {command}`openssl rand -hex 32`.
'';
};
};
config = lib.mkIf cfg.enable {
services.postgresql = lib.optionalAttrs cfg.createDatabase {
enable = true;
ensureDatabases = [ "matrix-sliding-sync" ];
ensureUsers = [ rec {
name = "matrix-sliding-sync";
ensurePermissions."DATABASE \"${name}\"" = "ALL PRIVILEGES";
} ];
};
systemd.services.matrix-sliding-sync = {
after = lib.optional cfg.createDatabase "postgresql.service";
wantedBy = [ "multi-user.target" ];
environment = cfg.settings;
serviceConfig = {
DynamicUser = true;
EnvironmentFile = cfg.environmentFile;
ExecStart = lib.getExe cfg.package;
StateDirectory = "matrix-sliding-sync";
WorkingDirectory = "%S/matrix-sliding-sync";
};
};
services.nginx.virtualHosts.${cfg.publicBaseUrl} = lib.mkIf cfg.enableNginx {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = lib.replaceStrings [ "0.0.0.0" "::" ] [ "127.0.0.1" "::1" ] "http://${cfg.settings.SYNCV3_BINDADDR}";
};
};
};
}

View File

@@ -10,14 +10,15 @@ let
wcfgText = "config.services.matrix-synapse-next.workers";
format = pkgs.formats.yaml {};
matrix-synapse-common-config = format.generate "matrix-synapse-common-config.yaml" cfg.settings;
matrix-synapse-common-config = format.generate "matrix-synapse-common-config.yaml" (cfg.settings // {
listeners = map (lib.filterAttrsRecursive (_: v: v != null)) cfg.settings.listeners;
});
# TODO: Align better with the upstream module
wrapped = cfg.package.override {
inherit (cfg) plugins;
extras = [
"postgres"
"saml2"
"oidc"
"systemd"
"url-preview"
@@ -25,7 +26,6 @@ let
"jwt"
"redis"
"cache-memory"
"user-search"
];
};
@@ -79,6 +79,15 @@ in
'';
};
socketDir = mkOption {
type = types.path;
default = "/run/matrix-synapse";
description = ''
The directory where matrix-synapse by default stores the sockets of
all listeners that bind to UNIX sockets.
'';
};
enableNginx = mkEnableOption "The synapse module managing nginx";
public_baseurl = mkOption {
@@ -135,14 +144,42 @@ in
type = types.listOf (types.submodule {
options = {
port = mkOption {
type = types.port;
description = "The TCP port to bind to";
type = with types; nullOr types.port;
default = null;
description = ''
The TCP port to bind to.
::: {.note}
This option will be ignored if {option}`path` is set to a non-null value.
:::
'';
example = 8448;
};
path = mkOption {
type = with types; nullOr path;
default = null;
description = ''
The UNIX socket to bind to.
::: {.note}
This option will override {option}`bind_addresses` and {option}`port`
if set to a non-null value.
:::
'';
example = literalExpression ''''${${cfgText}.socketDir}/matrix-synapse.sock'';
};
bind_addresses = mkOption {
type = types.listOf types.str;
description = "A list of local addresses to listen on";
default = [ ];
description = ''
A list of local addresses to listen on.
::: {.note}
This option will be ignored if {option}`path` is set to a non-null value.
:::
'';
};
type = mkOption {
@@ -201,16 +238,14 @@ in
# TODO: add defaultText
default = [
{
port = 8008;
bind_addresses = [ "127.0.0.1" ];
path = "${cfg.socketDir}/matrix-synapse.sock";
resources = [
{ names = [ "client" ]; compress = true; }
{ names = [ "federation" ]; compress = false; }
];
}
(mkIf (wcfg.instances != { }) {
port = 9093;
bind_addresses = [ "127.0.0.1" ];
path = "${cfg.socketDir}/matrix-synapse-replication.sock";
resources = [
{ names = [ "replication" ]; }
];
@@ -352,6 +387,15 @@ in
};
config = mkIf cfg.enable {
assertions = [ ]
++ (map (l: {
assertion = l.path == null -> (l.bind_addresses != [ ] && l.port != null);
message = "Some listeners are missing either a socket path or a bind_address + port to listen on";
}) cfg.settings.listeners);
warnings = [ ] ++ lib.optional cfg.enableSlidingSync
"the option services.matrix-synapse-next.enableSlidingSync no longer has any effect (and is enabled by default)";
users.users.matrix-synapse = {
group = "matrix-synapse";
home = cfg.dataDir;
@@ -383,7 +427,7 @@ in
wantedBy = [ "matrix-synapse.target" ];
preStart = let
flags = lib.cli.toGNUCommandLineShell {} {
flags = lib.cli.toCommandLineShellGNU {} {
config-path = [ matrix-synapse-common-config ] ++ cfg.extraConfigFiles;
keys-directory = cfg.dataDir;
generate-keys = true;
@@ -396,30 +440,18 @@ in
Group = "matrix-synapse";
Slice = "system-matrix-synapse.slice";
WorkingDirectory = cfg.dataDir;
StateDirectory = "matrix-synapse";
RuntimeDirectory = "matrix-synapse";
ExecStart = let
flags = lib.cli.toGNUCommandLineShell {} {
flags = lib.cli.toCommandLineShellGNU {} {
config-path = [ matrix-synapse-common-config ] ++ cfg.extraConfigFiles;
keys-directory = cfg.dataDir;
};
in "${wrapped}/bin/synapse_homeserver ${flags}";
ExecReload = "${pkgs.utillinux}/bin/kill -HUP $MAINPID";
ExecReload = "${lib.getExe' pkgs.coreutils "kill"} -HUP $MAINPID";
Restart = "on-failure";
};
};
};
services.matrix-synapse-next.settings.extra_well_known_client_content."org.matrix.msc3575.proxy" = mkIf cfg.enableSlidingSync {
url = "https://${config.services.matrix-synapse.sliding-sync.publicBaseUrl}";
};
services.matrix-synapse.sliding-sync = mkIf cfg.enableSlidingSync {
enable = true;
enableNginx = lib.mkDefault cfg.enableNginx;
publicBaseUrl = lib.mkDefault "slidingsync.${cfg.settings.server_name}";
settings = {
SYNCV3_SERVER = lib.mkDefault "https://${cfg.public_baseurl}";
SYNCV3_PROM = lib.mkIf cfg.settings.enable_metrics (lib.mkDefault "127.0.0.1:9001");
};
};
};
}

View File

@@ -2,13 +2,10 @@
let
cfg = config.services.matrix-synapse-next;
getWorkersOfType = type: lib.filterAttrs (_: w: w.type == type) cfg.workers.instances;
isListenerType = type: listener: lib.lists.any (r: lib.lists.any (n: n == type) r.names) listener.resources;
firstListenerOfType = type: worker: lib.lists.findFirst (isListenerType type) (throw "No federation endpoint on receiver") worker.settings.worker_listeners;
wAddressOfType = type: w: lib.lists.findFirst (_: true) (throw "No address in receiver") (firstListenerOfType type w).bind_addresses;
wPortOfType = type: w: (firstListenerOfType type w).port;
wSocketAddressOfType = type: w: "${wAddressOfType type w}:${builtins.toString (wPortOfType type w)}";
generateSocketAddresses = type: workers: lib.mapAttrsToList (_: w: "${wSocketAddressOfType type w}") workers;
matrix-lib = (import ../lib.nix { inherit lib; });
workerUpstreams = matrix-lib.mapWorkersToUpstreamsByType cfg.workers.instances;
listenerUpstreams = matrix-lib.mapListenersToUpstreamsByType cfg.settings.listeners;
in
{
config = lib.mkIf cfg.enableNginx {
@@ -138,24 +135,17 @@ in
'';
services.nginx.upstreams.synapse_master.servers = let
isMainListener = l: isListenerType "client" l && isListenerType "federation" l;
firstMainListener = lib.findFirst isMainListener
(throw "No catch-all listener configured") cfg.settings.listeners;
address = lib.findFirst (_: true) (throw "No address in main listener") firstMainListener.bind_addresses;
port = firstMainListener.port;
socketAddress = "${address}:${builtins.toString port}";
in {
"${socketAddress}" = { };
};
mainListeners = builtins.intersectAttrs
(listenerUpstreams.client.http or { })
(listenerUpstreams.federation.http or { });
in
assert lib.assertMsg (mainListeners != { })
"No catch-all listener configured, or listener is not bound to an address";
mainListeners;
services.nginx.upstreams.synapse_worker_federation = {
servers = let
fedReceivers = getWorkersOfType "fed-receiver";
socketAddresses = generateSocketAddresses "federation" fedReceivers;
in if fedReceivers != { } then
lib.genAttrs socketAddresses (_: { })
else config.services.nginx.upstreams.synapse_master.servers;
servers = workerUpstreams.fed-receiver.federation.http or config.services.nginx.upstreams.synapse_master.servers;
extraConfig = ''
ip_hash;
'';
@@ -163,12 +153,7 @@ in
services.nginx.upstreams.synapse_worker_initial_sync = {
servers = let
initialSyncers = getWorkersOfType "initial-sync";
socketAddresses = generateSocketAddresses "client" initialSyncers;
in if initialSyncers != { } then
lib.genAttrs socketAddresses (_: { })
else config.services.nginx.upstreams.synapse_master.servers;
servers = workerUpstreams.initial-sync.client.http or config.services.nginx.upstreams.synapse_master.servers;
extraConfig = ''
hash $mxid_localpart consistent;
'';
@@ -176,12 +161,7 @@ in
services.nginx.upstreams.synapse_worker_normal_sync = {
servers = let
normalSyncers = getWorkersOfType "normal-sync";
socketAddresses = generateSocketAddresses "client" normalSyncers;
in if normalSyncers != { } then
lib.genAttrs socketAddresses (_: { })
else config.services.nginx.upstreams.synapse_master.servers;
servers = workerUpstreams.normal-sync.client.http or config.services.nginx.upstreams.synapse_master.servers;
extraConfig = ''
hash $mxid_localpart consistent;
'';
@@ -189,12 +169,7 @@ in
services.nginx.upstreams.synapse_worker_user-dir = {
servers = let
workers = getWorkersOfType "user-dir";
socketAddresses = generateSocketAddresses "client" workers;
in if workers != { } then
lib.genAttrs socketAddresses (_: { })
else config.services.nginx.upstreams.synapse_master.servers;
servers = workerUpstreams.user-dir.client.http or config.services.nginx.upstreams.synapse_master.servers;
};
services.nginx.virtualHosts."${cfg.public_baseurl}" = {

View File

@@ -86,10 +86,17 @@ in {
};
port = mkOption {
type = types.port;
type = with types; nullOr port;
default = null;
description = "The TCP port to bind to";
};
path = mkOption {
type = with types; nullOr path;
default = null;
description = "The UNIX socket to bind to";
};
bind_addresses = mkOption {
type = with types; listOf str;
description = "A list of local addresses to listen on";
@@ -161,7 +168,7 @@ in {
};
in {
mainReplicationHost = mkOption {
type = types.str;
type = with types; nullOr str;
default = let
host = (matrix-lib.connectionInfo mainReplicationListener).host;
in
@@ -174,18 +181,32 @@ in {
};
mainReplicationPort = mkOption {
type = types.port;
type = with types; nullOr port;
default = mainReplicationListener.port;
# TODO: add defaultText
description = "Port for the main synapse instance's replication listener";
};
mainReplicationPath = mkOption {
type = with types; nullOr path;
default = mainReplicationListener.path;
# TODO: add defaultText
description = "Path to the UNIX socket of the main synapse instance's replication listener";
};
defaultListenerAddress = mkOption {
type = types.str;
default = "127.0.0.1";
description = "The default listener address for the worker";
};
workersUsePath = mkOption {
type = types.bool;
description = "Whether to enable UNIX sockets for all automatically generated workers";
default = true;
example = false;
};
workerStartingPort = mkOption {
type = types.port;
description = "What port should the automatically configured workers start enumerating from";
@@ -233,22 +254,32 @@ in {
};
config = {
assertions = [ ]
++ (lib.concatMap (worker:
(map (l: {
assertion = l.path == null -> (l.bind_addresses != [ ] && l.port != null);
message = "At least one worker listener is missing either a socket path or a bind_address + port to listen on";
}) worker.settings.worker_listeners)
) (lib.attrValues wcfg.instances));
services.matrix-synapse-next.settings = {
federation_sender_instances =
lib.genList (i: "auto-fed-sender${toString (i + 1)}") wcfg.federationSenders;
instance_map = (lib.mkIf (cfg.workers.instances != { }) ({
main = let
host = lib.head mainReplicationListener.bind_addresses;
in {
host = if builtins.elem host [ "0.0.0.0" "::"] then "127.0.0.1" else host;
port = mainReplicationListener.port;
main = if wcfg.mainReplicationPath != null then {
path = wcfg.mainReplicationPath;
} else {
host = wcfg.mainReplicationHost;
port = wcfg.mainReplicationPort;
};
} // genAttrs' (lib.lists.range 1 wcfg.eventPersisters)
(i: "auto-event-persist${toString i}")
(i: let
wRL = matrix-lib.firstListenerOfType "replication" wcfg.instances."auto-event-persist${toString i}".settings.worker_listeners;
in matrix-lib.connectionInfo wRL)));
in if wRL.path != null then {
inherit (wRL) path;
} else matrix-lib.connectionInfo wRL)));
stream_writers.events =
mkIf (wcfg.eventPersisters > 0)
@@ -260,10 +291,15 @@ in {
services.matrix-synapse-next.workers.instances = let
sum = lib.foldl lib.add 0;
workerListenersWithMetrics = portOffset:
lib.singleton ({
port = wcfg.workerStartingPort + portOffset - 1;
})
workerListenersWithMetrics = portOffset: name:
[(if wcfg.workersUsePath
then {
path = "${cfg.socketDir}/matrix-synapse-worker-${name}.sock";
}
else {
port = wcfg.workerStartingPort + portOffset - 1;
}
)]
++ lib.optional wcfg.enableMetrics {
port = wcfg.metricsStartingPort + portOffset;
resources = [ { names = [ "metrics" ]; } ];
@@ -274,7 +310,7 @@ in {
numberOfWorkers,
portOffset ? 0,
nameFn ? i: "auto-${type}${toString i}",
workerListenerFn ? i: workerListenersWithMetrics (portOffset + i)
workerListenerFn ? i: name: workerListenersWithMetrics (portOffset + i) name
}: genAttrs'
(lib.lists.range 1 numberOfWorkers)
nameFn
@@ -282,7 +318,7 @@ in {
isAuto = true;
inherit type;
index = i;
settings.worker_listeners = workerListenerFn i;
settings.worker_listeners = workerListenerFn i (nameFn i);
});
workerInstances = {
@@ -323,8 +359,13 @@ in {
systemd.services = let
workerList = lib.mapAttrsToList lib.nameValuePair wcfg.instances;
workerConfig = worker: format.generate "matrix-synapse-worker-${worker.name}-config.yaml"
(worker.value.settings // { worker_name = worker.name; });
workerConfig = worker:
format.generate "matrix-synapse-worker-${worker.name}-config.yaml"
(worker.value.settings // {
worker_name = worker.name;
worker_listeners =
map (lib.filterAttrsRecursive (_: v: v != null)) worker.value.settings.worker_listeners;
});
in builtins.listToAttrs (lib.flip map workerList (worker: {
name = "matrix-synapse-worker-${worker.name}";
value = {
@@ -339,6 +380,8 @@ in {
Group = "matrix-synapse";
Slice = "system-matrix-synapse.slice";
WorkingDirectory = cfg.dataDir;
RuntimeDirectory = "matrix-synapse";
StateDirectory = "matrix-synapse";
ExecStartPre = pkgs.writers.writeBash "wait-for-synapse" ''
# From https://md.darmstadt.ccc.de/synapse-at-work
while ! systemctl is-active -q matrix-synapse.service; do
@@ -346,7 +389,7 @@ in {
done
'';
ExecStart = let
flags = lib.cli.toGNUCommandLineShell {} {
flags = lib.cli.toCommandLineShellGNU {} {
config-path = [ matrix-synapse-common-config (workerConfig worker) ] ++ cfg.extraConfigFiles;
keys-directory = cfg.dataDir;
};

4
tests/default.nix Normal file
View File

@@ -0,0 +1,4 @@
{ nixpkgs, pkgs, matrix-lib, ... }:
{
nginx-pipeline-eval = pkgs.callPackage ./nginx-pipeline { inherit nixpkgs matrix-lib; };
}

View File

@@ -0,0 +1,53 @@
{ nixpkgs, lib, matrix-lib, writeText, ... }:
let
nixosConfig = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
../../module.nix
{
system.stateVersion = "25.11";
boot.isContainer = true;
services.matrix-synapse-next = {
enable = true;
enableNginx = true;
workers = {
enableMetrics = true;
federationSenders = 3;
federationReceivers = 3;
initialSyncers = 1;
normalSyncers = 1;
eventPersisters = 1;
useUserDirectoryWorker = true;
instances.auto-fed-receiver1.settings.worker_listeners = [
{
bind_addresses = [
"127.0.0.2"
];
port = 1337;
resources = [
{ compress = false;
names = [ "federation" ];
}
];
}
];
};
settings.server_name = "example.com";
};
}
];
};
inherit (nixosConfig.config.services.matrix-synapse-next.workers) instances;
in
writeText "matrix-synapse-next-nginx-pipeline-test.txt" ''
${(lib.generators.toPretty {}) instances}
====================================================
${(lib.generators.toPretty {}) (matrix-lib.mapWorkersToUpstreamsByType instances)}
''