···
cfg = config.services.matrix-synapse;
7
-
format = pkgs.formats.yaml {};
7
+
format = pkgs.formats.yaml { };
# remove null values from the final configuration
finalSettings = lib.filterAttrsRecursive (_: v: v != null) cfg.settings;
···
usePostgresql = cfg.settings.database.name == "psycopg2";
hasLocalPostgresDB = let args = cfg.settings.database.args; in
usePostgresql && (!(args ? host) || (elem args.host [ "localhost" "127.0.0.1" "::1" ]));
16
+
hasWorkers = cfg.workers != { };
···
73
+
logConfig = logName: {
75
+
formatters.journal_fmt.format = "%(name)s: [%(request)s] %(message)s";
76
+
handlers.journal = {
77
+
class = "systemd.journal.JournalHandler";
78
+
formatter = "journal_fmt";
79
+
SYSLOG_IDENTIFIER = logName;
83
+
handlers = [ "journal" ];
85
+
disable_existing_loggers = false;
87
+
logConfigText = logName:
92
+
formatters.journal_fmt.format = "%(name)s: [%(request)s] %(message)s";
93
+
handlers.journal = {
94
+
class = "systemd.journal.JournalHandler";
95
+
formatter = "journal_fmt";
96
+
SYSLOG_IDENTIFIER = "${logName}";
100
+
handlers = [ "journal" ];
102
+
disable_existing_loggers = false;
107
+
Path to a yaml file generated from this Nix expression:
113
+
genLogConfigFile = logName: format.generate "synapse-log-${logName}.yaml" (logConfig logName);
···
201
+
listenerType = workerContext: types.submodule {
206
+
description = lib.mdDoc ''
207
+
The port to listen for HTTP(S) requests on.
211
+
bind_addresses = mkOption {
212
+
type = types.listOf types.str;
217
+
example = literalExpression ''
223
+
description = lib.mdDoc ''
224
+
IP addresses to bind the listener to.
229
+
type = types.enum [
236
+
example = "metrics";
237
+
description = lib.mdDoc ''
238
+
The type of the listener, usually http.
244
+
default = !workerContext;
246
+
description = lib.mdDoc ''
247
+
Whether to enable TLS on the listener socket.
251
+
x_forwarded = mkOption {
255
+
description = lib.mdDoc ''
256
+
Use the X-Forwarded-For (XFF) header as the client IP and not the
261
+
resources = mkOption {
262
+
type = types.listOf (types.submodule {
265
+
type = types.listOf (types.enum [
277
+
description = lib.mdDoc ''
278
+
List of resources to host on this listener.
284
+
compress = mkOption {
287
+
description = lib.mdDoc ''
288
+
Whether synapse should compress HTTP responses to clients that support it.
289
+
This should be disabled if running synapse behind a load balancer
290
+
that can do automatic compression.
295
+
description = lib.mdDoc ''
296
+
List of HTTP resources to serve on this listener.
services.matrix-synapse = {
enable = mkEnableOption (lib.mdDoc "matrix.org synapse");
···
The primary synapse configuration. See the
[sample configuration](https://github.com/matrix-org/synapse/blob/v${pkgs.matrix-synapse-unwrapped.version}/docs/sample_config.yaml)
···
349
-
default = ./synapse-log_config.yaml;
350
-
defaultText = lib.literalExpression "nixos/modules/services/matrix/synapse-log_config.yaml";
493
+
default = genLogConfigFile "synapse";
494
+
defaultText = logConfigText "synapse";
description = lib.mdDoc ''
The file that holds the logging configuration.
···
412
-
type = types.listOf (types.submodule {
417
-
description = lib.mdDoc ''
418
-
The port to listen for HTTP(S) requests on.
422
-
bind_addresses = mkOption {
423
-
type = types.listOf types.str;
428
-
example = literalExpression ''
434
-
description = lib.mdDoc ''
435
-
IP addresses to bind the listener to.
440
-
type = types.enum [
447
-
example = "metrics";
448
-
description = lib.mdDoc ''
449
-
The type of the listener, usually http.
457
-
description = lib.mdDoc ''
458
-
Whether to enable TLS on the listener socket.
462
-
x_forwarded = mkOption {
466
-
description = lib.mdDoc ''
467
-
Use the X-Forwarded-For (XFF) header as the client IP and not the
472
-
resources = mkOption {
473
-
type = types.listOf (types.submodule {
476
-
type = types.listOf (types.enum [
487
-
description = lib.mdDoc ''
488
-
List of resources to host on this listener.
494
-
compress = mkOption {
496
-
description = lib.mdDoc ''
497
-
Should synapse compress HTTP responses to clients that support it?
498
-
This should be disabled if running synapse behind a load balancer
499
-
that can do automatic compression.
504
-
description = lib.mdDoc ''
505
-
List of HTTP resources to serve on this listener.
556
+
type = types.listOf (listenerType false);
bind_addresses = [ "127.0.0.1" ];
names = [ "federation" ];
570
+
}] ++ lib.optional hasWorkers {
572
+
bind_addresses = [ "127.0.0.1" ];
575
+
x_forwarded = false;
577
+
names = [ "replication" ];
description = lib.mdDoc ''
List of ports that Synapse should listen on, their purpose and their configuration.
584
+
By default, synapse will be configured for client and federation traffic on port 8008, and
585
+
for worker replication traffic on port 9093. See [`services.matrix-synapse.workers`](#opt-services.matrix-synapse.workers)
···
default = if versionAtLeast config.system.stateVersion "18.03"
537
-
defaultText = literalExpression ''
598
+
defaultText = literalExpression ''
if versionAtLeast config.system.stateVersion "18.03"
···
psycopg2 = "matrix-synapse";
}.${cfg.settings.database.name};
defaultText = literalExpression ''
555
-
sqlite3 = "''${${options.services.matrix-synapse.dataDir}}/homeserver.db";
556
-
psycopg2 = "matrix-synapse";
557
-
}.''${${options.services.matrix-synapse.settings}.database.name};
616
+
sqlite3 = "''${${options.services.matrix-synapse.dataDir}}/homeserver.db";
617
+
psycopg2 = "matrix-synapse";
618
+
}.''${${options.services.matrix-synapse.settings}.database.name};
description = lib.mdDoc ''
Name of the database when using the psycopg2 backend,
···
url_preview_ip_range_whitelist = mkOption {
type = types.listOf types.str;
description = lib.mdDoc ''
List of IP address CIDR ranges that the URL preview spider is allowed
to access even if they are specified in url_preview_ip_range_blacklist.
···
on how to configure it properly.
(types.attrsOf types.str));
example = literalExpression ''
{ scheme = "http"; } # no http previews
···
type = types.listOf types.str;
"turn:turn.example.com:3487?transport=udp"
"turn:turn.example.com:3487?transport=tcp"
···
server_name = "matrix.org";
"ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
description = lib.mdDoc ''
The trusted servers to download signing keys from.
···
810
+
redis = lib.mkOption {
811
+
type = types.submodule {
812
+
freeformType = format.type;
814
+
enabled = lib.mkOption {
817
+
description = lib.mdDoc ''
818
+
Whether to use redis support
824
+
description = lib.mdDoc ''
825
+
Redis configuration for synapse.
828
+
[upstream documentation](https://github.com/matrix-org/synapse/blob/v${pkgs.matrix-synapse-unwrapped.version}/usage/configuration/config_documentation.md#redis)
829
+
for available options.
836
+
workers = lib.mkOption {
838
+
description = lib.mdDoc ''
839
+
Options for configuring workers. Worker support will be enabled if at least one worker is configured here.
841
+
See the [worker documention](https://matrix-org.github.io/synapse/latest/workers.html#worker-configuration)
842
+
for possible options for each worker. Worker-specific options overriding the shared homeserver configuration can be
843
+
specified here for each worker.
846
+
Worker support will add a replication listener on port 9093 to the main synapse process using the default
847
+
value of [`services.matrix-synapse.settings.listeners`](#opt-services.matrix-synapse.settings.listeners) and configure that
848
+
listener as `services.matrix-synapse.settings.instance_map.main`.
849
+
If you set either of those options, make sure to configure a replication listener yourself.
851
+
A redis server is required for running workers. A local one can be enabled
852
+
using [`services.matrix-synapse.configureRedisLocally`](#opt-services.matrix-synapse.configureRedisLocally).
854
+
Workers also require a proper reverse proxy setup to direct incoming requests to the appropriate process. See
855
+
the [reverse proxy documentation](https://matrix-org.github.io/synapse/latest/reverse_proxy.html) for a
856
+
general reverse proxying setup and
857
+
the [worker documentation](https://matrix-org.github.io/synapse/latest/workers.html#available-worker-applications)
858
+
for the available endpoints per worker application.
861
+
type = types.attrsOf (types.submodule ({name, ...}: {
862
+
freeformType = format.type;
864
+
worker_app = lib.mkOption {
865
+
type = types.enum [
866
+
"synapse.app.generic_worker"
867
+
"synapse.app.media_repository"
869
+
description = "Type of this worker";
870
+
default = "synapse.app.generic_worker";
872
+
worker_listeners = lib.mkOption {
874
+
type = types.listOf (listenerType true);
875
+
description = lib.mdDoc ''
876
+
List of ports that this worker should listen on, their purpose and their configuration.
879
+
worker_log_config = lib.mkOption {
881
+
default = genLogConfigFile "synapse-${name}";
882
+
defaultText = logConfigText "synapse-${name}";
883
+
description = lib.mdDoc ''
884
+
The file for log configuration.
886
+
See the [python documentation](https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema)
887
+
for the schema and the [upstream repository](https://github.com/matrix-org/synapse/blob/v${pkgs.matrix-synapse-unwrapped.version}/docs/sample_log_config.yaml)
894
+
example = lib.literalExpression ''
896
+
"federation_sender" = { };
897
+
"federation_receiver" = {
898
+
worker_listeners = [
902
+
bind_addresses = [ "127.0.0.1" ];
904
+
x_forwarded = true;
906
+
names = [ "federation" ];
extraConfigFiles = mkOption {
type = types.listOf types.path;
description = lib.mdDoc ''
Extra config files to include.
···
928
+
configureRedisLocally = lib.mkOption {
931
+
description = lib.mdDoc ''
932
+
Whether to automatically configure a local redis server for matrix-synapse.
config = mkIf cfg.enable {
770
-
{ assertion = hasLocalPostgresDB -> config.services.postgresql.enable;
941
+
assertion = hasLocalPostgresDB -> config.services.postgresql.enable;
Cannot deploy matrix-synapse with a configuration for a local postgresql database
and a missing postgresql service. Since 20.03 it's mandatory to manually configure the
···
For further information about this update, please read the release-notes of 20.03 carefully.
958
+
assertion = hasWorkers -> cfg.settings.redis.enabled;
960
+
Workers for matrix-synapse require configuring a redis instance. This can be done
961
+
automatically by setting `services.matrix-synapse.configureRedisLocally = true`.
967
+
main = cfg.settings.instance_map.main;
968
+
listener = lib.findFirst
971
+
listener.port == main.port
972
+
&& (lib.any (resource: builtins.elem "replication" resource.names) listener.resources)
973
+
&& (lib.any (bind: bind == main.host || bind == "0.0.0.0" || bind == "::") listener.bind_addresses)
976
+
cfg.settings.listeners;
978
+
hasWorkers -> (listener != null);
980
+
Workers for matrix-synapse require setting `services.matrix-synapse.settings.instance_map.main`
981
+
to any listener configured in `services.matrix-synapse.settings.listeners` with a `"replication"`
984
+
This is done by default unless you manually configure either of those settings.
989
+
services.matrix-synapse.settings.redis = lib.mkIf cfg.configureRedisLocally {
991
+
path = config.services.redis.servers.matrix-synapse.unixSocket;
993
+
services.matrix-synapse.settings.instance_map.main = lib.mkIf hasWorkers (lib.mkDefault {
994
+
host = "127.0.0.1";
services.matrix-synapse.configFile = configFile;
services.matrix-synapse.package = wrapped;
···
gid = config.ids.gids.matrix-synapse;
806
-
systemd.services.matrix-synapse = {
807
-
description = "Synapse Matrix homeserver";
1016
+
systemd.targets.matrix-synapse = lib.mkIf hasWorkers {
1017
+
description = "Synapse Matrix parent target";
after = [ "network.target" ] ++ optional hasLocalPostgresDB "postgresql.service";
wantedBy = [ "multi-user.target" ];
811
-
${cfg.package}/bin/synapse_homeserver \
812
-
--config-path ${configFile} \
813
-
--keys-directory ${cfg.dataDir} \
816
-
environment = optionalAttrs (cfg.withJemalloc) {
817
-
LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so";
821
-
User = "matrix-synapse";
822
-
Group = "matrix-synapse";
823
-
WorkingDirectory = cfg.dataDir;
824
-
ExecStartPre = [ ("+" + (pkgs.writeShellScript "matrix-synapse-fix-permissions" ''
825
-
chown matrix-synapse:matrix-synapse ${cfg.settings.signing_key_path}
826
-
chmod 0600 ${cfg.settings.signing_key_path}
829
-
${cfg.package}/bin/synapse_homeserver \
830
-
${ concatMapStringsSep "\n " (x: "--config-path ${x} \\") ([ configFile ] ++ cfg.extraConfigFiles) }
831
-
--keys-directory ${cfg.dataDir}
833
-
ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID";
834
-
Restart = "on-failure";
1022
+
systemd.services =
1027
+
partOf = [ "matrix-synapse.target" ];
1028
+
wantedBy = [ "matrix-synapse.target" ];
1029
+
unitConfig.ReloadPropagatedFrom = "matrix-synapse.target";
1032
+
after = [ "network.target" ] ++ optional hasLocalPostgresDB "postgresql.service";
1033
+
wantedBy = [ "multi-user.target" ];
1035
+
baseServiceConfig = {
1036
+
environment = optionalAttrs (cfg.withJemalloc) {
1037
+
LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so";
1041
+
User = "matrix-synapse";
1042
+
Group = "matrix-synapse";
1043
+
WorkingDirectory = cfg.dataDir;
1044
+
ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID";
1045
+
Restart = "on-failure";
837
-
# Security Hardening
838
-
# Refer to systemd.exec(5) for option descriptions.
839
-
CapabilityBoundingSet = [ "" ];
840
-
LockPersonality = true;
841
-
NoNewPrivileges = true;
842
-
PrivateDevices = true;
844
-
PrivateUsers = true;
845
-
ProcSubset = "pid";
846
-
ProtectClock = true;
847
-
ProtectControlGroups = true;
848
-
ProtectHome = true;
849
-
ProtectHostname = true;
850
-
ProtectKernelLogs = true;
851
-
ProtectKernelModules = true;
852
-
ProtectKernelTunables = true;
853
-
ProtectProc = "invisible";
854
-
ProtectSystem = "strict";
855
-
ReadWritePaths = [ cfg.dataDir ];
857
-
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
858
-
RestrictNamespaces = true;
859
-
RestrictRealtime = true;
860
-
RestrictSUIDSGID = true;
861
-
SystemCallArchitectures = "native";
862
-
SystemCallFilter = [ "@system-service" "~@resources" "~@privileged" ];
1048
+
# Security Hardening
1049
+
# Refer to systemd.exec(5) for option descriptions.
1050
+
CapabilityBoundingSet = [ "" ];
1051
+
LockPersonality = true;
1052
+
NoNewPrivileges = true;
1053
+
PrivateDevices = true;
1054
+
PrivateTmp = true;
1055
+
PrivateUsers = true;
1056
+
ProcSubset = "pid";
1057
+
ProtectClock = true;
1058
+
ProtectControlGroups = true;
1059
+
ProtectHome = true;
1060
+
ProtectHostname = true;
1061
+
ProtectKernelLogs = true;
1062
+
ProtectKernelModules = true;
1063
+
ProtectKernelTunables = true;
1064
+
ProtectProc = "invisible";
1065
+
ProtectSystem = "strict";
1066
+
ReadWritePaths = [ cfg.dataDir ];
1068
+
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
1069
+
RestrictNamespaces = true;
1070
+
RestrictRealtime = true;
1071
+
RestrictSUIDSGID = true;
1072
+
SystemCallArchitectures = "native";
1073
+
SystemCallFilter = [ "@system-service" "~@resources" "~@privileged" ];
1077
+
genWorkerService = name: workerCfg:
1079
+
finalWorkerCfg = workerCfg // { worker_name = name; };
1080
+
workerConfigFile = format.generate "worker-${name}.yaml" finalWorkerCfg;
1083
+
name = "matrix-synapse-worker-${name}";
1084
+
value = lib.mkMerge [
1087
+
description = "Synapse Matrix worker ${name}";
1088
+
# make sure the main process starts first for potential database migrations
1089
+
after = [ "matrix-synapse.service" ];
1090
+
requires = [ "matrix-synapse.service" ];
1093
+
${cfg.package}/bin/synapse_worker \
1094
+
${ concatMapStringsSep "\n " (x: "--config-path ${x} \\") ([ configFile workerConfigFile ] ++ cfg.extraConfigFiles) }
1095
+
--keys-directory ${cfg.dataDir}
1103
+
matrix-synapse = lib.mkMerge [
1106
+
description = "Synapse Matrix homeserver";
1108
+
${cfg.package}/bin/synapse_homeserver \
1109
+
--config-path ${configFile} \
1110
+
--keys-directory ${cfg.dataDir} \
1115
+
("+" + (pkgs.writeShellScript "matrix-synapse-fix-permissions" ''
1116
+
chown matrix-synapse:matrix-synapse ${cfg.settings.signing_key_path}
1117
+
chmod 0600 ${cfg.settings.signing_key_path}
1121
+
${cfg.package}/bin/synapse_homeserver \
1122
+
${ concatMapStringsSep "\n " (x: "--config-path ${x} \\") ([ configFile ] ++ cfg.extraConfigFiles) }
1123
+
--keys-directory ${cfg.dataDir}
1129
+
// (lib.mapAttrs' genWorkerService cfg.workers);
1131
+
services.redis.servers.matrix-synapse = lib.mkIf cfg.configureRedisLocally {
1133
+
user = "matrix-synapse";
environment.systemPackages = [ registerNewMatrixUser ];