at 23.11-pre 34 kB view raw
1{ config, lib, options, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.matrix-synapse; 7 format = pkgs.formats.yaml {}; 8 9 # remove null values from the final configuration 10 finalSettings = lib.filterAttrsRecursive (_: v: v != null) cfg.settings; 11 configFile = format.generate "homeserver.yaml" finalSettings; 12 logConfigFile = format.generate "log_config.yaml" cfg.logConfig; 13 14 pluginsEnv = cfg.package.python.buildEnv.override { 15 extraLibs = cfg.plugins; 16 }; 17 18 usePostgresql = cfg.settings.database.name == "psycopg2"; 19 hasLocalPostgresDB = let args = cfg.settings.database.args; in 20 usePostgresql && (!(args ? host) || (elem args.host [ "localhost" "127.0.0.1" "::1" ])); 21 22 registerNewMatrixUser = 23 let 24 isIpv6 = x: lib.length (lib.splitString ":" x) > 1; 25 listener = 26 lib.findFirst ( 27 listener: lib.any ( 28 resource: lib.any ( 29 name: name == "client" 30 ) resource.names 31 ) listener.resources 32 ) (lib.last cfg.settings.listeners) cfg.settings.listeners; 33 # FIXME: Handle cases with missing client listener properly, 34 # don't rely on lib.last, this will not work. 35 36 # add a tail, so that without any bind_addresses we still have a useable address 37 bindAddress = head (listener.bind_addresses ++ [ "127.0.0.1" ]); 38 listenerProtocol = if listener.tls 39 then "https" 40 else "http"; 41 in 42 pkgs.writeShellScriptBin "matrix-synapse-register_new_matrix_user" '' 43 exec ${cfg.package}/bin/register_new_matrix_user \ 44 $@ \ 45 ${lib.concatMapStringsSep " " (x: "-c ${x}") ([ configFile ] ++ cfg.extraConfigFiles)} \ 46 "${listenerProtocol}://${ 47 if (isIpv6 bindAddress) then 48 "[${bindAddress}]" 49 else 50 "${bindAddress}" 51 }:${builtins.toString listener.port}/" 52 ''; 53in { 54 55 imports = [ 56 57 (mkRemovedOptionModule [ "services" "matrix-synapse" "trusted_third_party_id_servers" ] '' 58 The `trusted_third_party_id_servers` option as been removed in `matrix-synapse` v1.4.0 59 as the behavior is now obsolete. 60 '') 61 (mkRemovedOptionModule [ "services" "matrix-synapse" "create_local_database" ] '' 62 Database configuration must be done manually. An exemplary setup is demonstrated in 63 <nixpkgs/nixos/tests/matrix/synapse.nix> 64 '') 65 (mkRemovedOptionModule [ "services" "matrix-synapse" "web_client" ] "") 66 (mkRemovedOptionModule [ "services" "matrix-synapse" "room_invite_state_types" ] '' 67 You may add additional event types via 68 `services.matrix-synapse.room_prejoin_state.additional_event_types` and 69 disable the default events via 70 `services.matrix-synapse.room_prejoin_state.disable_default_event_types`. 71 '') 72 73 # options that don't exist in synapse anymore 74 (mkRemovedOptionModule [ "services" "matrix-synapse" "bind_host" ] "Use listener settings instead." ) 75 (mkRemovedOptionModule [ "services" "matrix-synapse" "bind_port" ] "Use listener settings instead." ) 76 (mkRemovedOptionModule [ "services" "matrix-synapse" "expire_access_tokens" ] "" ) 77 (mkRemovedOptionModule [ "services" "matrix-synapse" "no_tls" ] "It is no longer supported by synapse." ) 78 (mkRemovedOptionModule [ "services" "matrix-synapse" "tls_dh_param_path" ] "It was removed from synapse." ) 79 (mkRemovedOptionModule [ "services" "matrix-synapse" "unsecure_port" ] "Use settings.listeners instead." ) 80 (mkRemovedOptionModule [ "services" "matrix-synapse" "user_creation_max_duration" ] "It is no longer supported by synapse." ) 81 (mkRemovedOptionModule [ "services" "matrix-synapse" "verbose" ] "Use a log config instead." ) 82 83 # options that were moved into rfc42 style settings 84 (mkRemovedOptionModule [ "services" "matrix-synapse" "app_service_config_files" ] "Use settings.app_service_config_files instead" ) 85 (mkRemovedOptionModule [ "services" "matrix-synapse" "database_args" ] "Use settings.database.args instead" ) 86 (mkRemovedOptionModule [ "services" "matrix-synapse" "database_name" ] "Use settings.database.args.database instead" ) 87 (mkRemovedOptionModule [ "services" "matrix-synapse" "database_type" ] "Use settings.database.name instead" ) 88 (mkRemovedOptionModule [ "services" "matrix-synapse" "database_user" ] "Use settings.database.args.user instead" ) 89 (mkRemovedOptionModule [ "services" "matrix-synapse" "dynamic_thumbnails" ] "Use settings.dynamic_thumbnails instead" ) 90 (mkRemovedOptionModule [ "services" "matrix-synapse" "enable_metrics" ] "Use settings.enable_metrics instead" ) 91 (mkRemovedOptionModule [ "services" "matrix-synapse" "enable_registration" ] "Use settings.enable_registration instead" ) 92 (mkRemovedOptionModule [ "services" "matrix-synapse" "extraConfig" ] "Use settings instead." ) 93 (mkRemovedOptionModule [ "services" "matrix-synapse" "listeners" ] "Use settings.listeners instead" ) 94 (mkRemovedOptionModule [ "services" "matrix-synapse" "logConfig" ] "Use settings.log_config instead" ) 95 (mkRemovedOptionModule [ "services" "matrix-synapse" "max_image_pixels" ] "Use settings.max_image_pixels instead" ) 96 (mkRemovedOptionModule [ "services" "matrix-synapse" "max_upload_size" ] "Use settings.max_upload_size instead" ) 97 (mkRemovedOptionModule [ "services" "matrix-synapse" "presence" "enabled" ] "Use settings.presence.enabled instead" ) 98 (mkRemovedOptionModule [ "services" "matrix-synapse" "public_baseurl" ] "Use settings.public_baseurl instead" ) 99 (mkRemovedOptionModule [ "services" "matrix-synapse" "report_stats" ] "Use settings.report_stats instead" ) 100 (mkRemovedOptionModule [ "services" "matrix-synapse" "server_name" ] "Use settings.server_name instead" ) 101 (mkRemovedOptionModule [ "services" "matrix-synapse" "servers" ] "Use settings.trusted_key_servers instead." ) 102 (mkRemovedOptionModule [ "services" "matrix-synapse" "tls_certificate_path" ] "Use settings.tls_certificate_path instead" ) 103 (mkRemovedOptionModule [ "services" "matrix-synapse" "tls_private_key_path" ] "Use settings.tls_private_key_path instead" ) 104 (mkRemovedOptionModule [ "services" "matrix-synapse" "turn_shared_secret" ] "Use settings.turn_shared_secret instead" ) 105 (mkRemovedOptionModule [ "services" "matrix-synapse" "turn_uris" ] "Use settings.turn_uris instead" ) 106 (mkRemovedOptionModule [ "services" "matrix-synapse" "turn_user_lifetime" ] "Use settings.turn_user_lifetime instead" ) 107 (mkRemovedOptionModule [ "services" "matrix-synapse" "url_preview_enabled" ] "Use settings.url_preview_enabled instead" ) 108 (mkRemovedOptionModule [ "services" "matrix-synapse" "url_preview_ip_range_blacklist" ] "Use settings.url_preview_ip_range_blacklist instead" ) 109 (mkRemovedOptionModule [ "services" "matrix-synapse" "url_preview_ip_range_whitelist" ] "Use settings.url_preview_ip_range_whitelist instead" ) 110 (mkRemovedOptionModule [ "services" "matrix-synapse" "url_preview_url_blacklist" ] "Use settings.url_preview_url_blacklist instead" ) 111 112 # options that are too specific to mention them explicitly in settings 113 (mkRemovedOptionModule [ "services" "matrix-synapse" "account_threepid_delegates" "email" ] "Use settings.account_threepid_delegates.email instead" ) 114 (mkRemovedOptionModule [ "services" "matrix-synapse" "account_threepid_delegates" "msisdn" ] "Use settings.account_threepid_delegates.msisdn instead" ) 115 (mkRemovedOptionModule [ "services" "matrix-synapse" "allow_guest_access" ] "Use settings.allow_guest_access instead" ) 116 (mkRemovedOptionModule [ "services" "matrix-synapse" "bcrypt_rounds" ] "Use settings.bcrypt_rounds instead" ) 117 (mkRemovedOptionModule [ "services" "matrix-synapse" "enable_registration_captcha" ] "Use settings.enable_registration_captcha instead" ) 118 (mkRemovedOptionModule [ "services" "matrix-synapse" "event_cache_size" ] "Use settings.event_cache_size instead" ) 119 (mkRemovedOptionModule [ "services" "matrix-synapse" "federation_rc_concurrent" ] "Use settings.rc_federation.concurrent instead" ) 120 (mkRemovedOptionModule [ "services" "matrix-synapse" "federation_rc_reject_limit" ] "Use settings.rc_federation.reject_limit instead" ) 121 (mkRemovedOptionModule [ "services" "matrix-synapse" "federation_rc_sleep_delay" ] "Use settings.rc_federation.sleep_delay instead" ) 122 (mkRemovedOptionModule [ "services" "matrix-synapse" "federation_rc_sleep_limit" ] "Use settings.rc_federation.sleep_limit instead" ) 123 (mkRemovedOptionModule [ "services" "matrix-synapse" "federation_rc_window_size" ] "Use settings.rc_federation.window_size instead" ) 124 (mkRemovedOptionModule [ "services" "matrix-synapse" "key_refresh_interval" ] "Use settings.key_refresh_interval instead" ) 125 (mkRemovedOptionModule [ "services" "matrix-synapse" "rc_messages_burst_count" ] "Use settings.rc_messages.burst_count instead" ) 126 (mkRemovedOptionModule [ "services" "matrix-synapse" "rc_messages_per_second" ] "Use settings.rc_messages.per_second instead" ) 127 (mkRemovedOptionModule [ "services" "matrix-synapse" "recaptcha_private_key" ] "Use settings.recaptcha_private_key instead" ) 128 (mkRemovedOptionModule [ "services" "matrix-synapse" "recaptcha_public_key" ] "Use settings.recaptcha_public_key instead" ) 129 (mkRemovedOptionModule [ "services" "matrix-synapse" "redaction_retention_period" ] "Use settings.redaction_retention_period instead" ) 130 (mkRemovedOptionModule [ "services" "matrix-synapse" "room_prejoin_state" "additional_event_types" ] "Use settings.room_prejoin_state.additional_event_types instead" ) 131 (mkRemovedOptionModule [ "services" "matrix-synapse" "room_prejoin_state" "disable_default_event_types" ] "Use settings.room_prejoin-state.disable_default_event_types instead" ) 132 133 # Options that should be passed via extraConfigFiles, so they are not persisted into the nix store 134 (mkRemovedOptionModule [ "services" "matrix-synapse" "macaroon_secret_key" ] "Pass this value via extraConfigFiles instead" ) 135 (mkRemovedOptionModule [ "services" "matrix-synapse" "registration_shared_secret" ] "Pass this value via extraConfigFiles instead" ) 136 137 ]; 138 139 options = { 140 services.matrix-synapse = { 141 enable = mkEnableOption (lib.mdDoc "matrix.org synapse"); 142 143 configFile = mkOption { 144 type = types.path; 145 readOnly = true; 146 description = lib.mdDoc '' 147 Path to the configuration file on the target system. Useful to configure e.g. workers 148 that also need this. 149 ''; 150 }; 151 152 package = mkOption { 153 type = types.package; 154 default = pkgs.matrix-synapse; 155 defaultText = literalExpression "pkgs.matrix-synapse"; 156 description = lib.mdDoc '' 157 Overridable attribute of the matrix synapse server package to use. 158 ''; 159 }; 160 161 plugins = mkOption { 162 type = types.listOf types.package; 163 default = [ ]; 164 example = literalExpression '' 165 with config.services.matrix-synapse.package.plugins; [ 166 matrix-synapse-ldap3 167 matrix-synapse-pam 168 ]; 169 ''; 170 description = lib.mdDoc '' 171 List of additional Matrix plugins to make available. 172 ''; 173 }; 174 175 withJemalloc = mkOption { 176 type = types.bool; 177 default = false; 178 description = lib.mdDoc '' 179 Whether to preload jemalloc to reduce memory fragmentation and overall usage. 180 ''; 181 }; 182 183 dataDir = mkOption { 184 type = types.str; 185 default = "/var/lib/matrix-synapse"; 186 description = lib.mdDoc '' 187 The directory where matrix-synapse stores its stateful data such as 188 certificates, media and uploads. 189 ''; 190 }; 191 192 settings = mkOption { 193 default = {}; 194 description = mdDoc '' 195 The primary synapse configuration. See the 196 [sample configuration](https://github.com/matrix-org/synapse/blob/v${cfg.package.version}/docs/sample_config.yaml) 197 for possible values. 198 199 Secrets should be passed in by using the `extraConfigFiles` option. 200 ''; 201 type = with types; submodule { 202 freeformType = format.type; 203 options = { 204 # This is a reduced set of popular options and defaults 205 # Do not add every available option here, they can be specified 206 # by the user at their own discretion. This is a freeform type! 207 208 server_name = mkOption { 209 type = types.str; 210 example = "example.com"; 211 default = config.networking.hostName; 212 defaultText = literalExpression "config.networking.hostName"; 213 description = lib.mdDoc '' 214 The domain name of the server, with optional explicit port. 215 This is used by remote servers to look up the server address. 216 This is also the last part of your UserID. 217 218 The server_name cannot be changed later so it is important to configure this correctly before you start Synapse. 219 ''; 220 }; 221 222 enable_registration = mkOption { 223 type = types.bool; 224 default = false; 225 description = lib.mdDoc '' 226 Enable registration for new users. 227 ''; 228 }; 229 230 registration_shared_secret = mkOption { 231 type = types.nullOr types.str; 232 default = null; 233 description = mdDoc '' 234 If set, allows registration by anyone who also has the shared 235 secret, even if registration is otherwise disabled. 236 237 Secrets should be passed in via `extraConfigFiles`! 238 ''; 239 }; 240 241 macaroon_secret_key = mkOption { 242 type = types.nullOr types.str; 243 default = null; 244 description = mdDoc '' 245 Secret key for authentication tokens. If none is specified, 246 the registration_shared_secret is used, if one is given; otherwise, 247 a secret key is derived from the signing key. 248 249 Secrets should be passed in via `extraConfigFiles`! 250 ''; 251 }; 252 253 enable_metrics = mkOption { 254 type = types.bool; 255 default = false; 256 description = lib.mdDoc '' 257 Enable collection and rendering of performance metrics 258 ''; 259 }; 260 261 report_stats = mkOption { 262 type = types.bool; 263 default = false; 264 description = lib.mdDoc '' 265 Whether or not to report anonymized homeserver usage statistics. 266 ''; 267 }; 268 269 signing_key_path = mkOption { 270 type = types.path; 271 default = "${cfg.dataDir}/homeserver.signing.key"; 272 description = lib.mdDoc '' 273 Path to the signing key to sign messages with. 274 ''; 275 }; 276 277 pid_file = mkOption { 278 type = types.path; 279 default = "/run/matrix-synapse.pid"; 280 readOnly = true; 281 description = lib.mdDoc '' 282 The file to store the PID in. 283 ''; 284 }; 285 286 log_config = mkOption { 287 type = types.path; 288 default = ./synapse-log_config.yaml; 289 defaultText = lib.literalExpression "nixos/modules/services/matrix/synapse-log_config.yaml"; 290 description = lib.mdDoc '' 291 The file that holds the logging configuration. 292 ''; 293 }; 294 295 media_store_path = mkOption { 296 type = types.path; 297 default = if lib.versionAtLeast config.system.stateVersion "22.05" 298 then "${cfg.dataDir}/media_store" 299 else "${cfg.dataDir}/media"; 300 defaultText = "${cfg.dataDir}/media_store for when system.stateVersion is at least 22.05, ${cfg.dataDir}/media when lower than 22.05"; 301 description = lib.mdDoc '' 302 Directory where uploaded images and attachments are stored. 303 ''; 304 }; 305 306 public_baseurl = mkOption { 307 type = types.nullOr types.str; 308 default = null; 309 example = "https://example.com:8448/"; 310 description = lib.mdDoc '' 311 The public-facing base URL for the client API (not including _matrix/...) 312 ''; 313 }; 314 315 tls_certificate_path = mkOption { 316 type = types.nullOr types.str; 317 default = null; 318 example = "/var/lib/acme/example.com/fullchain.pem"; 319 description = lib.mdDoc '' 320 PEM encoded X509 certificate for TLS. 321 You can replace the self-signed certificate that synapse 322 autogenerates on launch with your own SSL certificate + key pair 323 if you like. Any required intermediary certificates can be 324 appended after the primary certificate in hierarchical order. 325 ''; 326 }; 327 328 tls_private_key_path = mkOption { 329 type = types.nullOr types.str; 330 default = null; 331 example = "/var/lib/acme/example.com/key.pem"; 332 description = lib.mdDoc '' 333 PEM encoded private key for TLS. Specify null if synapse is not 334 speaking TLS directly. 335 ''; 336 }; 337 338 presence.enabled = mkOption { 339 type = types.bool; 340 default = true; 341 example = false; 342 description = lib.mdDoc '' 343 Whether to enable presence tracking. 344 345 Presence tracking allows users to see the state (e.g online/offline) 346 of other local and remote users. 347 ''; 348 }; 349 350 listeners = mkOption { 351 type = types.listOf (types.submodule { 352 options = { 353 port = mkOption { 354 type = types.port; 355 example = 8448; 356 description = lib.mdDoc '' 357 The port to listen for HTTP(S) requests on. 358 ''; 359 }; 360 361 bind_addresses = mkOption { 362 type = types.listOf types.str; 363 default = [ 364 "::1" 365 "127.0.0.1" 366 ]; 367 example = literalExpression '' 368 [ 369 "::" 370 "0.0.0.0" 371 ] 372 ''; 373 description = lib.mdDoc '' 374 IP addresses to bind the listener to. 375 ''; 376 }; 377 378 type = mkOption { 379 type = types.enum [ 380 "http" 381 "manhole" 382 "metrics" 383 "replication" 384 ]; 385 default = "http"; 386 example = "metrics"; 387 description = lib.mdDoc '' 388 The type of the listener, usually http. 389 ''; 390 }; 391 392 tls = mkOption { 393 type = types.bool; 394 default = true; 395 example = false; 396 description = lib.mdDoc '' 397 Whether to enable TLS on the listener socket. 398 ''; 399 }; 400 401 x_forwarded = mkOption { 402 type = types.bool; 403 default = false; 404 example = true; 405 description = lib.mdDoc '' 406 Use the X-Forwarded-For (XFF) header as the client IP and not the 407 actual client IP. 408 ''; 409 }; 410 411 resources = mkOption { 412 type = types.listOf (types.submodule { 413 options = { 414 names = mkOption { 415 type = types.listOf (types.enum [ 416 "client" 417 "consent" 418 "federation" 419 "keys" 420 "media" 421 "metrics" 422 "openid" 423 "replication" 424 "static" 425 ]); 426 description = lib.mdDoc '' 427 List of resources to host on this listener. 428 ''; 429 example = [ 430 "client" 431 ]; 432 }; 433 compress = mkOption { 434 type = types.bool; 435 description = lib.mdDoc '' 436 Should synapse compress HTTP responses to clients that support it? 437 This should be disabled if running synapse behind a load balancer 438 that can do automatic compression. 439 ''; 440 }; 441 }; 442 }); 443 description = lib.mdDoc '' 444 List of HTTP resources to serve on this listener. 445 ''; 446 }; 447 }; 448 }); 449 default = [ { 450 port = 8008; 451 bind_addresses = [ "127.0.0.1" ]; 452 type = "http"; 453 tls = false; 454 x_forwarded = true; 455 resources = [ { 456 names = [ "client" ]; 457 compress = true; 458 } { 459 names = [ "federation" ]; 460 compress = false; 461 } ]; 462 } ]; 463 description = lib.mdDoc '' 464 List of ports that Synapse should listen on, their purpose and their configuration. 465 ''; 466 }; 467 468 database.name = mkOption { 469 type = types.enum [ 470 "sqlite3" 471 "psycopg2" 472 ]; 473 default = if versionAtLeast config.system.stateVersion "18.03" 474 then "psycopg2" 475 else "sqlite3"; 476 defaultText = literalExpression '' 477 if versionAtLeast config.system.stateVersion "18.03" 478 then "psycopg2" 479 else "sqlite3" 480 ''; 481 description = lib.mdDoc '' 482 The database engine name. Can be sqlite3 or psycopg2. 483 ''; 484 }; 485 486 database.args.database = mkOption { 487 type = types.str; 488 default = { 489 sqlite3 = "${cfg.dataDir}/homeserver.db"; 490 psycopg2 = "matrix-synapse"; 491 }.${cfg.settings.database.name}; 492 defaultText = literalExpression '' 493 { 494 sqlite3 = "''${${options.services.matrix-synapse.dataDir}}/homeserver.db"; 495 psycopg2 = "matrix-synapse"; 496 }.''${${options.services.matrix-synapse.settings}.database.name}; 497 ''; 498 description = lib.mdDoc '' 499 Name of the database when using the psycopg2 backend, 500 path to the database location when using sqlite3. 501 ''; 502 }; 503 504 database.args.user = mkOption { 505 type = types.nullOr types.str; 506 default = { 507 sqlite3 = null; 508 psycopg2 = "matrix-synapse"; 509 }.${cfg.settings.database.name}; 510 defaultText = lib.literalExpression '' 511 { 512 sqlite3 = null; 513 psycopg2 = "matrix-synapse"; 514 }.''${cfg.settings.database.name}; 515 ''; 516 description = lib.mdDoc '' 517 Username to connect with psycopg2, set to null 518 when using sqlite3. 519 ''; 520 }; 521 522 url_preview_enabled = mkOption { 523 type = types.bool; 524 default = true; 525 example = false; 526 description = lib.mdDoc '' 527 Is the preview URL API enabled? If enabled, you *must* specify an 528 explicit url_preview_ip_range_blacklist of IPs that the spider is 529 denied from accessing. 530 ''; 531 }; 532 533 url_preview_ip_range_blacklist = mkOption { 534 type = types.listOf types.str; 535 default = [ 536 "10.0.0.0/8" 537 "100.64.0.0/10" 538 "127.0.0.0/8" 539 "169.254.0.0/16" 540 "172.16.0.0/12" 541 "192.0.0.0/24" 542 "192.0.2.0/24" 543 "192.168.0.0/16" 544 "192.88.99.0/24" 545 "198.18.0.0/15" 546 "198.51.100.0/24" 547 "2001:db8::/32" 548 "203.0.113.0/24" 549 "224.0.0.0/4" 550 "::1/128" 551 "fc00::/7" 552 "fe80::/10" 553 "fec0::/10" 554 "ff00::/8" 555 ]; 556 description = lib.mdDoc '' 557 List of IP address CIDR ranges that the URL preview spider is denied 558 from accessing. 559 ''; 560 }; 561 562 url_preview_ip_range_whitelist = mkOption { 563 type = types.listOf types.str; 564 default = []; 565 description = lib.mdDoc '' 566 List of IP address CIDR ranges that the URL preview spider is allowed 567 to access even if they are specified in url_preview_ip_range_blacklist. 568 ''; 569 }; 570 571 url_preview_url_blacklist = mkOption { 572 type = types.listOf types.str; 573 default = []; 574 description = lib.mdDoc '' 575 Optional list of URL matches that the URL preview spider is 576 denied from accessing. 577 ''; 578 }; 579 580 max_upload_size = mkOption { 581 type = types.str; 582 default = "50M"; 583 example = "100M"; 584 description = lib.mdDoc '' 585 The largest allowed upload size in bytes 586 ''; 587 }; 588 589 max_image_pixels = mkOption { 590 type = types.str; 591 default = "32M"; 592 example = "64M"; 593 description = lib.mdDoc '' 594 Maximum number of pixels that will be thumbnailed 595 ''; 596 }; 597 598 dynamic_thumbnails = mkOption { 599 type = types.bool; 600 default = false; 601 example = true; 602 description = lib.mdDoc '' 603 Whether to generate new thumbnails on the fly to precisely match 604 the resolution requested by the client. If true then whenever 605 a new resolution is requested by the client the server will 606 generate a new thumbnail. If false the server will pick a thumbnail 607 from a precalculated list. 608 ''; 609 }; 610 611 turn_uris = mkOption { 612 type = types.listOf types.str; 613 default = []; 614 example = [ 615 "turn:turn.example.com:3487?transport=udp" 616 "turn:turn.example.com:3487?transport=tcp" 617 "turns:turn.example.com:5349?transport=udp" 618 "turns:turn.example.com:5349?transport=tcp" 619 ]; 620 description = lib.mdDoc '' 621 The public URIs of the TURN server to give to clients 622 ''; 623 }; 624 turn_shared_secret = mkOption { 625 type = types.str; 626 default = ""; 627 example = literalExpression '' 628 config.services.coturn.static-auth-secret 629 ''; 630 description = mdDoc '' 631 The shared secret used to compute passwords for the TURN server. 632 633 Secrets should be passed in via `extraConfigFiles`! 634 ''; 635 }; 636 637 trusted_key_servers = mkOption { 638 type = types.listOf (types.submodule { 639 options = { 640 server_name = mkOption { 641 type = types.str; 642 example = "matrix.org"; 643 description = lib.mdDoc '' 644 Hostname of the trusted server. 645 ''; 646 }; 647 648 verify_keys = mkOption { 649 type = types.nullOr (types.attrsOf types.str); 650 default = null; 651 example = literalExpression '' 652 { 653 "ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"; 654 } 655 ''; 656 description = lib.mdDoc '' 657 Attribute set from key id to base64 encoded public key. 658 659 If specified synapse will check that the response is signed 660 by at least one of the given keys. 661 ''; 662 }; 663 }; 664 }); 665 default = [ { 666 server_name = "matrix.org"; 667 verify_keys = { 668 "ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"; 669 }; 670 } ]; 671 description = lib.mdDoc '' 672 The trusted servers to download signing keys from. 673 ''; 674 }; 675 676 app_service_config_files = mkOption { 677 type = types.listOf types.path; 678 default = [ ]; 679 description = lib.mdDoc '' 680 A list of application service config file to use 681 ''; 682 }; 683 684 }; 685 }; 686 }; 687 688 extraConfigFiles = mkOption { 689 type = types.listOf types.path; 690 default = []; 691 description = lib.mdDoc '' 692 Extra config files to include. 693 694 The configuration files will be included based on the command line 695 argument --config-path. This allows to configure secrets without 696 having to go through the Nix store, e.g. based on deployment keys if 697 NixOps is in use. 698 ''; 699 }; 700 }; 701 }; 702 703 config = mkIf cfg.enable { 704 assertions = [ 705 { assertion = hasLocalPostgresDB -> config.services.postgresql.enable; 706 message = '' 707 Cannot deploy matrix-synapse with a configuration for a local postgresql database 708 and a missing postgresql service. Since 20.03 it's mandatory to manually configure the 709 database (please read the thread in https://github.com/NixOS/nixpkgs/pull/80447 for 710 further reference). 711 712 If you 713 - try to deploy a fresh synapse, you need to configure the database yourself. An example 714 for this can be found in <nixpkgs/nixos/tests/matrix/synapse.nix> 715 - update your existing matrix-synapse instance, you simply need to add `services.postgresql.enable = true` 716 to your configuration. 717 718 For further information about this update, please read the release-notes of 20.03 carefully. 719 ''; 720 } 721 ]; 722 723 services.matrix-synapse.configFile = configFile; 724 725 users.users.matrix-synapse = { 726 group = "matrix-synapse"; 727 home = cfg.dataDir; 728 createHome = true; 729 shell = "${pkgs.bash}/bin/bash"; 730 uid = config.ids.uids.matrix-synapse; 731 }; 732 733 users.groups.matrix-synapse = { 734 gid = config.ids.gids.matrix-synapse; 735 }; 736 737 systemd.services.matrix-synapse = { 738 description = "Synapse Matrix homeserver"; 739 after = [ "network.target" ] ++ optional hasLocalPostgresDB "postgresql.service"; 740 wantedBy = [ "multi-user.target" ]; 741 preStart = '' 742 ${cfg.package}/bin/synapse_homeserver \ 743 --config-path ${configFile} \ 744 --keys-directory ${cfg.dataDir} \ 745 --generate-keys 746 ''; 747 environment = { 748 PYTHONPATH = makeSearchPathOutput "lib" cfg.package.python.sitePackages [ pluginsEnv ]; 749 } // optionalAttrs (cfg.withJemalloc) { 750 LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so"; 751 }; 752 serviceConfig = { 753 Type = "notify"; 754 User = "matrix-synapse"; 755 Group = "matrix-synapse"; 756 WorkingDirectory = cfg.dataDir; 757 ExecStartPre = [ ("+" + (pkgs.writeShellScript "matrix-synapse-fix-permissions" '' 758 chown matrix-synapse:matrix-synapse ${cfg.settings.signing_key_path} 759 chmod 0600 ${cfg.settings.signing_key_path} 760 '')) ]; 761 ExecStart = '' 762 ${cfg.package}/bin/synapse_homeserver \ 763 ${ concatMapStringsSep "\n " (x: "--config-path ${x} \\") ([ configFile ] ++ cfg.extraConfigFiles) } 764 --keys-directory ${cfg.dataDir} 765 ''; 766 ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID"; 767 Restart = "on-failure"; 768 UMask = "0077"; 769 770 # Security Hardening 771 # Refer to systemd.exec(5) for option descriptions. 772 CapabilityBoundingSet = [ "" ]; 773 LockPersonality = true; 774 NoNewPrivileges = true; 775 PrivateDevices = true; 776 PrivateTmp = true; 777 PrivateUsers = true; 778 ProcSubset = "pid"; 779 ProtectClock = true; 780 ProtectControlGroups = true; 781 ProtectHome = true; 782 ProtectHostname = true; 783 ProtectKernelLogs = true; 784 ProtectKernelModules = true; 785 ProtectKernelTunables = true; 786 ProtectProc = "invisible"; 787 ProtectSystem = "strict"; 788 ReadWritePaths = [ cfg.dataDir ]; 789 RemoveIPC = true; 790 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; 791 RestrictNamespaces = true; 792 RestrictRealtime = true; 793 RestrictSUIDSGID = true; 794 SystemCallArchitectures = "native"; 795 SystemCallFilter = [ "@system-service" "~@resources" "~@privileged" ]; 796 }; 797 }; 798 799 environment.systemPackages = [ registerNewMatrixUser ]; 800 }; 801 802 meta = { 803 buildDocsInSandbox = false; 804 doc = ./synapse.md; 805 maintainers = teams.matrix.members; 806 }; 807 808}