1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.matrix-synapse;
7 pg = config.services.postgresql;
8 usePostgresql = cfg.database_type == "psycopg2";
9 logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig;
10 mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${boolToString r.compress}}'';
11 mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${boolToString l.tls}, x_forwarded: ${boolToString l.x_forwarded}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
12 pluginsEnv = cfg.package.python.buildEnv.override {
13 extraLibs = cfg.plugins;
14 };
15 configFile = pkgs.writeText "homeserver.yaml" ''
16${optionalString (cfg.tls_certificate_path != null) ''
17tls_certificate_path: "${cfg.tls_certificate_path}"
18''}
19${optionalString (cfg.tls_private_key_path != null) ''
20tls_private_key_path: "${cfg.tls_private_key_path}"
21''}
22${optionalString (cfg.tls_dh_params_path != null) ''
23tls_dh_params_path: "${cfg.tls_dh_params_path}"
24''}
25no_tls: ${boolToString cfg.no_tls}
26${optionalString (cfg.bind_port != null) ''
27bind_port: ${toString cfg.bind_port}
28''}
29${optionalString (cfg.unsecure_port != null) ''
30unsecure_port: ${toString cfg.unsecure_port}
31''}
32${optionalString (cfg.bind_host != null) ''
33bind_host: "${cfg.bind_host}"
34''}
35server_name: "${cfg.server_name}"
36pid_file: "/run/matrix-synapse.pid"
37${optionalString (cfg.public_baseurl != null) ''
38public_baseurl: "${cfg.public_baseurl}"
39''}
40listeners: [${concatStringsSep "," (map mkListener cfg.listeners)}]
41database: {
42 name: "${cfg.database_type}",
43 args: {
44 ${concatStringsSep ",\n " (
45 mapAttrsToList (n: v: "\"${n}\": ${builtins.toJSON v}") cfg.database_args
46 )}
47 }
48}
49event_cache_size: "${cfg.event_cache_size}"
50verbose: ${cfg.verbose}
51log_config: "${logConfigFile}"
52rc_messages_per_second: ${cfg.rc_messages_per_second}
53rc_message_burst_count: ${cfg.rc_message_burst_count}
54federation_rc_window_size: ${cfg.federation_rc_window_size}
55federation_rc_sleep_limit: ${cfg.federation_rc_sleep_limit}
56federation_rc_sleep_delay: ${cfg.federation_rc_sleep_delay}
57federation_rc_reject_limit: ${cfg.federation_rc_reject_limit}
58federation_rc_concurrent: ${cfg.federation_rc_concurrent}
59media_store_path: "${cfg.dataDir}/media"
60uploads_path: "${cfg.dataDir}/uploads"
61max_upload_size: "${cfg.max_upload_size}"
62max_image_pixels: "${cfg.max_image_pixels}"
63dynamic_thumbnails: ${boolToString cfg.dynamic_thumbnails}
64url_preview_enabled: ${boolToString cfg.url_preview_enabled}
65${optionalString (cfg.url_preview_enabled == true) ''
66url_preview_ip_range_blacklist: ${builtins.toJSON cfg.url_preview_ip_range_blacklist}
67url_preview_ip_range_whitelist: ${builtins.toJSON cfg.url_preview_ip_range_whitelist}
68url_preview_url_blacklist: ${builtins.toJSON cfg.url_preview_url_blacklist}
69''}
70recaptcha_private_key: "${cfg.recaptcha_private_key}"
71recaptcha_public_key: "${cfg.recaptcha_public_key}"
72enable_registration_captcha: ${boolToString cfg.enable_registration_captcha}
73turn_uris: ${builtins.toJSON cfg.turn_uris}
74turn_shared_secret: "${cfg.turn_shared_secret}"
75enable_registration: ${boolToString cfg.enable_registration}
76${optionalString (cfg.registration_shared_secret != null) ''
77registration_shared_secret: "${cfg.registration_shared_secret}"
78''}
79recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify"
80turn_user_lifetime: "${cfg.turn_user_lifetime}"
81user_creation_max_duration: ${cfg.user_creation_max_duration}
82bcrypt_rounds: ${cfg.bcrypt_rounds}
83allow_guest_access: ${boolToString cfg.allow_guest_access}
84
85account_threepid_delegates:
86 ${optionalString (cfg.account_threepid_delegates.email != null) "email: ${cfg.account_threepid_delegates.email}"}
87 ${optionalString (cfg.account_threepid_delegates.msisdn != null) "msisdn: ${cfg.account_threepid_delegates.msisdn}"}
88
89room_prejoin_state:
90 disable_default_event_types: ${boolToString cfg.room_prejoin_state.disable_default_event_types}
91 additional_event_types: ${builtins.toJSON cfg.room_prejoin_state.additional_event_types}
92${optionalString (cfg.macaroon_secret_key != null) ''
93 macaroon_secret_key: "${cfg.macaroon_secret_key}"
94''}
95expire_access_token: ${boolToString cfg.expire_access_token}
96enable_metrics: ${boolToString cfg.enable_metrics}
97report_stats: ${boolToString cfg.report_stats}
98signing_key_path: "${cfg.dataDir}/homeserver.signing.key"
99key_refresh_interval: "${cfg.key_refresh_interval}"
100perspectives:
101 servers: {
102 ${concatStringsSep "},\n" (mapAttrsToList (n: v: ''
103 "${n}": {
104 "verify_keys": {
105 ${concatStringsSep "},\n" (mapAttrsToList (n: v: ''
106 "${n}": {
107 "key": "${v}"
108 }'') v)}
109 }
110 '') cfg.servers)}
111 }
112 }
113redaction_retention_period: ${toString cfg.redaction_retention_period}
114app_service_config_files: ${builtins.toJSON cfg.app_service_config_files}
115
116${cfg.extraConfig}
117'';
118
119 hasLocalPostgresDB = let args = cfg.database_args; in
120 usePostgresql && (!(args ? host) || (elem args.host [ "localhost" "127.0.0.1" "::1" ]));
121in {
122 options = {
123 services.matrix-synapse = {
124 enable = mkEnableOption "matrix.org synapse";
125 configFile = mkOption {
126 type = types.str;
127 readOnly = true;
128 description = ''
129 Path to the configuration file on the target system. Useful to configure e.g. workers
130 that also need this.
131 '';
132 };
133 package = mkOption {
134 type = types.package;
135 default = pkgs.matrix-synapse;
136 defaultText = literalExpression "pkgs.matrix-synapse";
137 description = ''
138 Overridable attribute of the matrix synapse server package to use.
139 '';
140 };
141 plugins = mkOption {
142 type = types.listOf types.package;
143 default = [ ];
144 example = literalExpression ''
145 with config.services.matrix-synapse.package.plugins; [
146 matrix-synapse-ldap3
147 matrix-synapse-pam
148 ];
149 '';
150 description = ''
151 List of additional Matrix plugins to make available.
152 '';
153 };
154 withJemalloc = mkOption {
155 type = types.bool;
156 default = false;
157 description = ''
158 Whether to preload jemalloc to reduce memory fragmentation and overall usage.
159 '';
160 };
161 no_tls = mkOption {
162 type = types.bool;
163 default = false;
164 description = ''
165 Don't bind to the https port
166 '';
167 };
168 bind_port = mkOption {
169 type = types.nullOr types.int;
170 default = null;
171 example = 8448;
172 description = ''
173 DEPRECATED: Use listeners instead.
174 The port to listen for HTTPS requests on.
175 For when matrix traffic is sent directly to synapse.
176 '';
177 };
178 unsecure_port = mkOption {
179 type = types.nullOr types.int;
180 default = null;
181 example = 8008;
182 description = ''
183 DEPRECATED: Use listeners instead.
184 The port to listen for HTTP requests on.
185 For when matrix traffic passes through loadbalancer that unwraps TLS.
186 '';
187 };
188 bind_host = mkOption {
189 type = types.nullOr types.str;
190 default = null;
191 description = ''
192 DEPRECATED: Use listeners instead.
193 Local interface to listen on.
194 The empty string will cause synapse to listen on all interfaces.
195 '';
196 };
197 tls_certificate_path = mkOption {
198 type = types.nullOr types.str;
199 default = null;
200 example = "${cfg.dataDir}/homeserver.tls.crt";
201 description = ''
202 PEM encoded X509 certificate for TLS.
203 You can replace the self-signed certificate that synapse
204 autogenerates on launch with your own SSL certificate + key pair
205 if you like. Any required intermediary certificates can be
206 appended after the primary certificate in hierarchical order.
207 '';
208 };
209 tls_private_key_path = mkOption {
210 type = types.nullOr types.str;
211 default = null;
212 example = "${cfg.dataDir}/homeserver.tls.key";
213 description = ''
214 PEM encoded private key for TLS. Specify null if synapse is not
215 speaking TLS directly.
216 '';
217 };
218 tls_dh_params_path = mkOption {
219 type = types.nullOr types.str;
220 default = null;
221 example = "${cfg.dataDir}/homeserver.tls.dh";
222 description = ''
223 PEM dh parameters for ephemeral keys
224 '';
225 };
226 server_name = mkOption {
227 type = types.str;
228 example = "example.com";
229 default = config.networking.hostName;
230 description = ''
231 The domain name of the server, with optional explicit port.
232 This is used by remote servers to look up the server address.
233 This is also the last part of your UserID.
234
235 The server_name cannot be changed later so it is important to configure this correctly before you start Synapse.
236 '';
237 };
238 public_baseurl = mkOption {
239 type = types.nullOr types.str;
240 default = null;
241 example = "https://example.com:8448/";
242 description = ''
243 The public-facing base URL for the client API (not including _matrix/...)
244 '';
245 };
246 listeners = mkOption {
247 type = types.listOf (types.submodule {
248 options = {
249 port = mkOption {
250 type = types.port;
251 example = 8448;
252 description = ''
253 The port to listen for HTTP(S) requests on.
254 '';
255 };
256 bind_address = mkOption {
257 type = types.str;
258 default = "";
259 example = "203.0.113.42";
260 description = ''
261 Local interface to listen on.
262 The empty string will cause synapse to listen on all interfaces.
263 '';
264 };
265 type = mkOption {
266 type = types.str;
267 default = "http";
268 description = ''
269 Type of listener.
270 '';
271 };
272 tls = mkOption {
273 type = types.bool;
274 default = true;
275 description = ''
276 Whether to listen for HTTPS connections rather than HTTP.
277 '';
278 };
279 x_forwarded = mkOption {
280 type = types.bool;
281 default = false;
282 description = ''
283 Use the X-Forwarded-For (XFF) header as the client IP and not the
284 actual client IP.
285 '';
286 };
287 resources = mkOption {
288 type = types.listOf (types.submodule {
289 options = {
290 names = mkOption {
291 type = types.listOf types.str;
292 description = ''
293 List of resources to host on this listener.
294 '';
295 example = ["client" "webclient" "federation"];
296 };
297 compress = mkOption {
298 type = types.bool;
299 description = ''
300 Should synapse compress HTTP responses to clients that support it?
301 This should be disabled if running synapse behind a load balancer
302 that can do automatic compression.
303 '';
304 };
305 };
306 });
307 description = ''
308 List of HTTP resources to serve on this listener.
309 '';
310 };
311 };
312 });
313 default = [{
314 port = 8448;
315 bind_address = "";
316 type = "http";
317 tls = true;
318 x_forwarded = false;
319 resources = [
320 { names = ["client" "webclient"]; compress = true; }
321 { names = ["federation"]; compress = false; }
322 ];
323 }];
324 description = ''
325 List of ports that Synapse should listen on, their purpose and their configuration.
326 '';
327 };
328 verbose = mkOption {
329 type = types.str;
330 default = "0";
331 description = "Logging verbosity level.";
332 };
333 rc_messages_per_second = mkOption {
334 type = types.str;
335 default = "0.2";
336 description = "Number of messages a client can send per second";
337 };
338 rc_message_burst_count = mkOption {
339 type = types.str;
340 default = "10.0";
341 description = "Number of message a client can send before being throttled";
342 };
343 federation_rc_window_size = mkOption {
344 type = types.str;
345 default = "1000";
346 description = "The federation window size in milliseconds";
347 };
348 federation_rc_sleep_limit = mkOption {
349 type = types.str;
350 default = "10";
351 description = ''
352 The number of federation requests from a single server in a window
353 before the server will delay processing the request.
354 '';
355 };
356 federation_rc_sleep_delay = mkOption {
357 type = types.str;
358 default = "500";
359 description = ''
360 The duration in milliseconds to delay processing events from
361 remote servers by if they go over the sleep limit.
362 '';
363 };
364 federation_rc_reject_limit = mkOption {
365 type = types.str;
366 default = "50";
367 description = ''
368 The maximum number of concurrent federation requests allowed
369 from a single server
370 '';
371 };
372 federation_rc_concurrent = mkOption {
373 type = types.str;
374 default = "3";
375 description = "The number of federation requests to concurrently process from a single server";
376 };
377 database_type = mkOption {
378 type = types.enum [ "sqlite3" "psycopg2" ];
379 default = if versionAtLeast config.system.stateVersion "18.03"
380 then "psycopg2"
381 else "sqlite3";
382 description = ''
383 The database engine name. Can be sqlite or psycopg2.
384 '';
385 };
386 database_name = mkOption {
387 type = types.str;
388 default = "matrix-synapse";
389 description = "Database name.";
390 };
391 database_user = mkOption {
392 type = types.str;
393 default = "matrix-synapse";
394 description = "Database user name.";
395 };
396 database_args = mkOption {
397 type = types.attrs;
398 default = {
399 sqlite3 = { database = "${cfg.dataDir}/homeserver.db"; };
400 psycopg2 = {
401 user = cfg.database_user;
402 database = cfg.database_name;
403 };
404 }.${cfg.database_type};
405 description = ''
406 Arguments to pass to the engine.
407 '';
408 };
409 event_cache_size = mkOption {
410 type = types.str;
411 default = "10K";
412 description = "Number of events to cache in memory.";
413 };
414 url_preview_enabled = mkOption {
415 type = types.bool;
416 default = false;
417 description = ''
418 Is the preview URL API enabled? If enabled, you *must* specify an
419 explicit url_preview_ip_range_blacklist of IPs that the spider is
420 denied from accessing.
421 '';
422 };
423 url_preview_ip_range_blacklist = mkOption {
424 type = types.listOf types.str;
425 default = [
426 "127.0.0.0/8"
427 "10.0.0.0/8"
428 "172.16.0.0/12"
429 "192.168.0.0/16"
430 "100.64.0.0/10"
431 "169.254.0.0/16"
432 "::1/128"
433 "fe80::/64"
434 "fc00::/7"
435 ];
436 description = ''
437 List of IP address CIDR ranges that the URL preview spider is denied
438 from accessing.
439 '';
440 };
441 url_preview_ip_range_whitelist = mkOption {
442 type = types.listOf types.str;
443 default = [];
444 description = ''
445 List of IP address CIDR ranges that the URL preview spider is allowed
446 to access even if they are specified in
447 url_preview_ip_range_blacklist.
448 '';
449 };
450 url_preview_url_blacklist = mkOption {
451 type = types.listOf types.str;
452 default = [];
453 description = ''
454 Optional list of URL matches that the URL preview spider is
455 denied from accessing.
456 '';
457 };
458 recaptcha_private_key = mkOption {
459 type = types.str;
460 default = "";
461 description = ''
462 This Home Server's ReCAPTCHA private key.
463 '';
464 };
465 recaptcha_public_key = mkOption {
466 type = types.str;
467 default = "";
468 description = ''
469 This Home Server's ReCAPTCHA public key.
470 '';
471 };
472 enable_registration_captcha = mkOption {
473 type = types.bool;
474 default = false;
475 description = ''
476 Enables ReCaptcha checks when registering, preventing signup
477 unless a captcha is answered. Requires a valid ReCaptcha
478 public/private key.
479 '';
480 };
481 turn_uris = mkOption {
482 type = types.listOf types.str;
483 default = [];
484 description = ''
485 The public URIs of the TURN server to give to clients
486 '';
487 };
488 turn_shared_secret = mkOption {
489 type = types.str;
490 default = "";
491 description = ''
492 The shared secret used to compute passwords for the TURN server
493 '';
494 };
495 turn_user_lifetime = mkOption {
496 type = types.str;
497 default = "1h";
498 description = "How long generated TURN credentials last";
499 };
500 enable_registration = mkOption {
501 type = types.bool;
502 default = false;
503 description = ''
504 Enable registration for new users.
505 '';
506 };
507 registration_shared_secret = mkOption {
508 type = types.nullOr types.str;
509 default = null;
510 description = ''
511 If set, allows registration by anyone who also has the shared
512 secret, even if registration is otherwise disabled.
513 '';
514 };
515 enable_metrics = mkOption {
516 type = types.bool;
517 default = false;
518 description = ''
519 Enable collection and rendering of performance metrics
520 '';
521 };
522 report_stats = mkOption {
523 type = types.bool;
524 default = false;
525 description = "";
526 };
527 servers = mkOption {
528 type = types.attrsOf (types.attrsOf types.str);
529 default = {
530 "matrix.org" = {
531 "ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
532 };
533 };
534 description = ''
535 The trusted servers to download signing keys from.
536 '';
537 };
538 max_upload_size = mkOption {
539 type = types.str;
540 default = "10M";
541 description = "The largest allowed upload size in bytes";
542 };
543 max_image_pixels = mkOption {
544 type = types.str;
545 default = "32M";
546 description = "Maximum number of pixels that will be thumbnailed";
547 };
548 dynamic_thumbnails = mkOption {
549 type = types.bool;
550 default = false;
551 description = ''
552 Whether to generate new thumbnails on the fly to precisely match
553 the resolution requested by the client. If true then whenever
554 a new resolution is requested by the client the server will
555 generate a new thumbnail. If false the server will pick a thumbnail
556 from a precalculated list.
557 '';
558 };
559 user_creation_max_duration = mkOption {
560 type = types.str;
561 default = "1209600000";
562 description = ''
563 Sets the expiry for the short term user creation in
564 milliseconds. The default value is two weeks.
565 '';
566 };
567 bcrypt_rounds = mkOption {
568 type = types.str;
569 default = "12";
570 description = ''
571 Set the number of bcrypt rounds used to generate password hash.
572 Larger numbers increase the work factor needed to generate the hash.
573 '';
574 };
575 allow_guest_access = mkOption {
576 type = types.bool;
577 default = false;
578 description = ''
579 Allows users to register as guests without a password/email/etc, and
580 participate in rooms hosted on this server which have been made
581 accessible to anonymous users.
582 '';
583 };
584 account_threepid_delegates.email = mkOption {
585 type = types.nullOr types.str;
586 default = null;
587 description = ''
588 Delegate email sending to https://example.org
589 '';
590 };
591 account_threepid_delegates.msisdn = mkOption {
592 type = types.nullOr types.str;
593 default = null;
594 description = ''
595 Delegate SMS sending to this local process (https://localhost:8090)
596 '';
597 };
598 room_prejoin_state.additional_event_types = mkOption {
599 default = [];
600 type = types.listOf types.str;
601 description = ''
602 Additional events to share with users who received an invite.
603 '';
604 };
605 room_prejoin_state.disable_default_event_types = mkOption {
606 default = false;
607 type = types.bool;
608 description = ''
609 Whether to disable the default state-event types for users invited to a room.
610 These are:
611
612 <itemizedlist>
613 <listitem><para>m.room.join_rules</para></listitem>
614 <listitem><para>m.room.canonical_alias</para></listitem>
615 <listitem><para>m.room.avatar</para></listitem>
616 <listitem><para>m.room.encryption</para></listitem>
617 <listitem><para>m.room.name</para></listitem>
618 <listitem><para>m.room.create</para></listitem>
619 </itemizedlist>
620 '';
621 };
622 macaroon_secret_key = mkOption {
623 type = types.nullOr types.str;
624 default = null;
625 description = ''
626 Secret key for authentication tokens
627 '';
628 };
629 expire_access_token = mkOption {
630 type = types.bool;
631 default = false;
632 description = ''
633 Whether to enable access token expiration.
634 '';
635 };
636 key_refresh_interval = mkOption {
637 type = types.str;
638 default = "1d";
639 description = ''
640 How long key response published by this server is valid for.
641 Used to set the valid_until_ts in /key/v2 APIs.
642 Determines how quickly servers will query to check which keys
643 are still valid.
644 '';
645 };
646 app_service_config_files = mkOption {
647 type = types.listOf types.path;
648 default = [ ];
649 description = ''
650 A list of application service config file to use
651 '';
652 };
653 redaction_retention_period = mkOption {
654 type = types.int;
655 default = 7;
656 description = ''
657 How long to keep redacted events in unredacted form in the database.
658 '';
659 };
660 extraConfig = mkOption {
661 type = types.lines;
662 default = "";
663 description = ''
664 Extra config options for matrix-synapse.
665 '';
666 };
667 extraConfigFiles = mkOption {
668 type = types.listOf types.path;
669 default = [];
670 description = ''
671 Extra config files to include.
672
673 The configuration files will be included based on the command line
674 argument --config-path. This allows to configure secrets without
675 having to go through the Nix store, e.g. based on deployment keys if
676 NixOPS is in use.
677 '';
678 };
679 logConfig = mkOption {
680 type = types.lines;
681 default = readFile ./matrix-synapse-log_config.yaml;
682 description = ''
683 A yaml python logging config file
684 '';
685 };
686 dataDir = mkOption {
687 type = types.str;
688 default = "/var/lib/matrix-synapse";
689 description = ''
690 The directory where matrix-synapse stores its stateful data such as
691 certificates, media and uploads.
692 '';
693 };
694 };
695 };
696
697 config = mkIf cfg.enable {
698 assertions = [
699 { assertion = hasLocalPostgresDB -> config.services.postgresql.enable;
700 message = ''
701 Cannot deploy matrix-synapse with a configuration for a local postgresql database
702 and a missing postgresql service. Since 20.03 it's mandatory to manually configure the
703 database (please read the thread in https://github.com/NixOS/nixpkgs/pull/80447 for
704 further reference).
705
706 If you
707 - try to deploy a fresh synapse, you need to configure the database yourself. An example
708 for this can be found in <nixpkgs/nixos/tests/matrix-synapse.nix>
709 - update your existing matrix-synapse instance, you simply need to add `services.postgresql.enable = true`
710 to your configuration.
711
712 For further information about this update, please read the release-notes of 20.03 carefully.
713 '';
714 }
715 ];
716
717 services.matrix-synapse.configFile = "${configFile}";
718
719 users.users.matrix-synapse = {
720 group = "matrix-synapse";
721 home = cfg.dataDir;
722 createHome = true;
723 shell = "${pkgs.bash}/bin/bash";
724 uid = config.ids.uids.matrix-synapse;
725 };
726
727 users.groups.matrix-synapse = {
728 gid = config.ids.gids.matrix-synapse;
729 };
730
731 systemd.services.matrix-synapse = {
732 description = "Synapse Matrix homeserver";
733 after = [ "network.target" ] ++ optional hasLocalPostgresDB "postgresql.service";
734 wantedBy = [ "multi-user.target" ];
735 preStart = ''
736 ${cfg.package}/bin/homeserver \
737 --config-path ${configFile} \
738 --keys-directory ${cfg.dataDir} \
739 --generate-keys
740 '';
741 environment = {
742 PYTHONPATH = makeSearchPathOutput "lib" cfg.package.python.sitePackages [ pluginsEnv ];
743 } // optionalAttrs (cfg.withJemalloc) {
744 LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so";
745 };
746 serviceConfig = {
747 Type = "notify";
748 User = "matrix-synapse";
749 Group = "matrix-synapse";
750 WorkingDirectory = cfg.dataDir;
751 ExecStartPre = [ ("+" + (pkgs.writeShellScript "matrix-synapse-fix-permissions" ''
752 chown matrix-synapse:matrix-synapse ${cfg.dataDir}/homeserver.signing.key
753 chmod 0600 ${cfg.dataDir}/homeserver.signing.key
754 '')) ];
755 ExecStart = ''
756 ${cfg.package}/bin/homeserver \
757 ${ concatMapStringsSep "\n " (x: "--config-path ${x} \\") ([ configFile ] ++ cfg.extraConfigFiles) }
758 --keys-directory ${cfg.dataDir}
759 '';
760 ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID";
761 Restart = "on-failure";
762 UMask = "0077";
763 };
764 };
765 };
766
767 imports = [
768 (mkRemovedOptionModule [ "services" "matrix-synapse" "trusted_third_party_id_servers" ] ''
769 The `trusted_third_party_id_servers` option as been removed in `matrix-synapse` v1.4.0
770 as the behavior is now obsolete.
771 '')
772 (mkRemovedOptionModule [ "services" "matrix-synapse" "create_local_database" ] ''
773 Database configuration must be done manually. An exemplary setup is demonstrated in
774 <nixpkgs/nixos/tests/matrix-synapse.nix>
775 '')
776 (mkRemovedOptionModule [ "services" "matrix-synapse" "web_client" ] "")
777 (mkRemovedOptionModule [ "services" "matrix-synapse" "room_invite_state_types" ] ''
778 You may add additional event types via
779 `services.matrix-synapse.room_prejoin_state.additional_event_types` and
780 disable the default events via
781 `services.matrix-synapse.room_prejoin_state.disable_default_event_types`.
782 '')
783 ];
784
785 meta.doc = ./matrix-synapse.xml;
786 meta.maintainers = teams.matrix.members;
787
788}