 cb15d762f4
			
		
	
	
		cb15d762f4
		
	
	
	
	
		
			
			This reverts commit eb753318b3716921d3ab3b1887385a5ee92b1884. The homeserver script has been restored with commit 0c663e90326fa7d81a36643f9e43b8574939fea3.
		
			
				
	
	
		
			700 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			700 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| { config, lib, pkgs, ... }:
 | |
| 
 | |
| with lib;
 | |
| 
 | |
| let
 | |
|   cfg = config.services.matrix-synapse;
 | |
|   pg = config.services.postgresql;
 | |
|   usePostgresql = cfg.database_type == "psycopg2";
 | |
|   logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig;
 | |
|   mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${boolToString r.compress}}'';
 | |
|   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)}]}'';
 | |
|   configFile = pkgs.writeText "homeserver.yaml" ''
 | |
| ${optionalString (cfg.tls_certificate_path != null) ''
 | |
| tls_certificate_path: "${cfg.tls_certificate_path}"
 | |
| ''}
 | |
| ${optionalString (cfg.tls_private_key_path != null) ''
 | |
| tls_private_key_path: "${cfg.tls_private_key_path}"
 | |
| ''}
 | |
| ${optionalString (cfg.tls_dh_params_path != null) ''
 | |
| tls_dh_params_path: "${cfg.tls_dh_params_path}"
 | |
| ''}
 | |
| no_tls: ${boolToString cfg.no_tls}
 | |
| ${optionalString (cfg.bind_port != null) ''
 | |
| bind_port: ${toString cfg.bind_port}
 | |
| ''}
 | |
| ${optionalString (cfg.unsecure_port != null) ''
 | |
| unsecure_port: ${toString cfg.unsecure_port}
 | |
| ''}
 | |
| ${optionalString (cfg.bind_host != null) ''
 | |
| bind_host: "${cfg.bind_host}"
 | |
| ''}
 | |
| server_name: "${cfg.server_name}"
 | |
| pid_file: "/var/run/matrix-synapse.pid"
 | |
| web_client: ${boolToString cfg.web_client}
 | |
| ${optionalString (cfg.public_baseurl != null) ''
 | |
| public_baseurl: "${cfg.public_baseurl}"
 | |
| ''}
 | |
| listeners: [${concatStringsSep "," (map mkListener cfg.listeners)}]
 | |
| database: {
 | |
|   name: "${cfg.database_type}",
 | |
|   args: {
 | |
|     ${concatStringsSep ",\n    " (
 | |
|       mapAttrsToList (n: v: "\"${n}\": ${builtins.toJSON v}") cfg.database_args
 | |
|     )}
 | |
|   }
 | |
| }
 | |
| event_cache_size: "${cfg.event_cache_size}"
 | |
| verbose: ${cfg.verbose}
 | |
| log_config: "${logConfigFile}"
 | |
| rc_messages_per_second: ${cfg.rc_messages_per_second}
 | |
| rc_message_burst_count: ${cfg.rc_message_burst_count}
 | |
| federation_rc_window_size: ${cfg.federation_rc_window_size}
 | |
| federation_rc_sleep_limit: ${cfg.federation_rc_sleep_limit}
 | |
| federation_rc_sleep_delay: ${cfg.federation_rc_sleep_delay}
 | |
| federation_rc_reject_limit: ${cfg.federation_rc_reject_limit}
 | |
| federation_rc_concurrent: ${cfg.federation_rc_concurrent}
 | |
| media_store_path: "${cfg.dataDir}/media"
 | |
| uploads_path: "${cfg.dataDir}/uploads"
 | |
| max_upload_size: "${cfg.max_upload_size}"
 | |
| max_image_pixels: "${cfg.max_image_pixels}"
 | |
| dynamic_thumbnails: ${boolToString cfg.dynamic_thumbnails}
 | |
| url_preview_enabled: ${boolToString cfg.url_preview_enabled}
 | |
| ${optionalString (cfg.url_preview_enabled == true) ''
 | |
| url_preview_ip_range_blacklist: ${builtins.toJSON cfg.url_preview_ip_range_blacklist}
 | |
| url_preview_ip_range_whitelist: ${builtins.toJSON cfg.url_preview_ip_range_whitelist}
 | |
| url_preview_url_blacklist: ${builtins.toJSON cfg.url_preview_url_blacklist}
 | |
| ''}
 | |
| recaptcha_private_key: "${cfg.recaptcha_private_key}"
 | |
| recaptcha_public_key: "${cfg.recaptcha_public_key}"
 | |
| enable_registration_captcha: ${boolToString cfg.enable_registration_captcha}
 | |
| turn_uris: ${builtins.toJSON cfg.turn_uris}
 | |
| turn_shared_secret: "${cfg.turn_shared_secret}"
 | |
| enable_registration: ${boolToString cfg.enable_registration}
 | |
| ${optionalString (cfg.registration_shared_secret != null) ''
 | |
| registration_shared_secret: "${cfg.registration_shared_secret}"
 | |
| ''}
 | |
| recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify"
 | |
| turn_user_lifetime: "${cfg.turn_user_lifetime}"
 | |
| user_creation_max_duration: ${cfg.user_creation_max_duration}
 | |
| bcrypt_rounds: ${cfg.bcrypt_rounds}
 | |
| allow_guest_access: ${boolToString cfg.allow_guest_access}
 | |
| trusted_third_party_id_servers: ${builtins.toJSON cfg.trusted_third_party_id_servers}
 | |
| room_invite_state_types: ${builtins.toJSON cfg.room_invite_state_types}
 | |
| ${optionalString (cfg.macaroon_secret_key != null) ''
 | |
|   macaroon_secret_key: "${cfg.macaroon_secret_key}"
 | |
| ''}
 | |
| expire_access_token: ${boolToString cfg.expire_access_token}
 | |
| enable_metrics: ${boolToString cfg.enable_metrics}
 | |
| report_stats: ${boolToString cfg.report_stats}
 | |
| signing_key_path: "${cfg.dataDir}/homeserver.signing.key"
 | |
| key_refresh_interval: "${cfg.key_refresh_interval}"
 | |
| perspectives:
 | |
|   servers: {
 | |
|     ${concatStringsSep "},\n" (mapAttrsToList (n: v: ''
 | |
|     "${n}": {
 | |
|       "verify_keys": {
 | |
|         ${concatStringsSep "},\n" (mapAttrsToList (n: v: ''
 | |
|         "${n}": {
 | |
|           "key": "${v}"
 | |
|         }'') v)}
 | |
|       }
 | |
|     '') cfg.servers)}
 | |
|     }
 | |
|   }
 | |
| app_service_config_files: ${builtins.toJSON cfg.app_service_config_files}
 | |
| 
 | |
| ${cfg.extraConfig}
 | |
| '';
 | |
| in {
 | |
|   options = {
 | |
|     services.matrix-synapse = {
 | |
|       enable = mkEnableOption "matrix.org synapse";
 | |
|       package = mkOption {
 | |
|         type = types.package;
 | |
|         default = pkgs.matrix-synapse;
 | |
|         defaultText = "pkgs.matrix-synapse";
 | |
|         description = ''
 | |
|           Overridable attribute of the matrix synapse server package to use.
 | |
|         '';
 | |
|       };
 | |
|       no_tls = mkOption {
 | |
|         type = types.bool;
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Don't bind to the https port
 | |
|         '';
 | |
|       };
 | |
|       bind_port = mkOption {
 | |
|         type = types.nullOr types.int;
 | |
|         default = null;
 | |
|         example = 8448;
 | |
|         description = ''
 | |
|           DEPRECATED: Use listeners instead.
 | |
|           The port to listen for HTTPS requests on.
 | |
|           For when matrix traffic is sent directly to synapse.
 | |
|         '';
 | |
|       };
 | |
|       unsecure_port = mkOption {
 | |
|         type = types.nullOr types.int;
 | |
|         default = null;
 | |
|         example = 8008;
 | |
|         description = ''
 | |
|           DEPRECATED: Use listeners instead.
 | |
|           The port to listen for HTTP requests on.
 | |
|           For when matrix traffic passes through loadbalancer that unwraps TLS.
 | |
|         '';
 | |
|       };
 | |
|       bind_host = mkOption {
 | |
|         type = types.nullOr types.str;
 | |
|         default = null;
 | |
|         description = ''
 | |
|           DEPRECATED: Use listeners instead.
 | |
|           Local interface to listen on.
 | |
|           The empty string will cause synapse to listen on all interfaces.
 | |
|         '';
 | |
|       };
 | |
|       tls_certificate_path = mkOption {
 | |
|         type = types.nullOr types.str;
 | |
|         default = null;
 | |
|         example = "${cfg.dataDir}/homeserver.tls.crt";
 | |
|         description = ''
 | |
|           PEM encoded X509 certificate for TLS.
 | |
|           You can replace the self-signed certificate that synapse
 | |
|           autogenerates on launch with your own SSL certificate + key pair
 | |
|           if you like.  Any required intermediary certificates can be
 | |
|           appended after the primary certificate in hierarchical order.
 | |
|         '';
 | |
|       };
 | |
|       tls_private_key_path = mkOption {
 | |
|         type = types.nullOr types.str;
 | |
|         default = null;
 | |
|         example = "${cfg.dataDir}/homeserver.tls.key";
 | |
|         description = ''
 | |
|           PEM encoded private key for TLS. Specify null if synapse is not
 | |
|           speaking TLS directly.
 | |
|         '';
 | |
|       };
 | |
|       tls_dh_params_path = mkOption {
 | |
|         type = types.nullOr types.str;
 | |
|         default = null;
 | |
|         example = "${cfg.dataDir}/homeserver.tls.dh";
 | |
|         description = ''
 | |
|           PEM dh parameters for ephemeral keys
 | |
|         '';
 | |
|       };
 | |
|       server_name = mkOption {
 | |
|         type = types.str;
 | |
|         example = "example.com";
 | |
|         default = config.networking.hostName;
 | |
|         description = ''
 | |
|           The domain name of the server, with optional explicit port.
 | |
|           This is used by remote servers to connect to this server,
 | |
|           e.g. matrix.org, localhost:8080, etc.
 | |
|           This is also the last part of your UserID.
 | |
|         '';
 | |
|       };
 | |
|       web_client = mkOption {
 | |
|         type = types.bool;
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Whether to serve a web client from the HTTP/HTTPS root resource.
 | |
|         '';
 | |
|       };
 | |
|       public_baseurl = mkOption {
 | |
|         type = types.nullOr types.str;
 | |
|         default = null;
 | |
|         example = "https://example.com:8448/";
 | |
|         description = ''
 | |
|           The public-facing base URL for the client API (not including _matrix/...)
 | |
|         '';
 | |
|       };
 | |
|       listeners = mkOption {
 | |
|         type = types.listOf (types.submodule {
 | |
|           options = {
 | |
|             port = mkOption {
 | |
|               type = types.int;
 | |
|               example = 8448;
 | |
|               description = ''
 | |
|                 The port to listen for HTTP(S) requests on.
 | |
|               '';
 | |
|             };
 | |
|             bind_address = mkOption {
 | |
|               type = types.str;
 | |
|               default = "";
 | |
|               example = "203.0.113.42";
 | |
|               description = ''
 | |
|                 Local interface to listen on.
 | |
|                 The empty string will cause synapse to listen on all interfaces.
 | |
|               '';
 | |
|             };
 | |
|             type = mkOption {
 | |
|               type = types.str;
 | |
|               default = "http";
 | |
|               description = ''
 | |
|                 Type of listener.
 | |
|               '';
 | |
|             };
 | |
|             tls = mkOption {
 | |
|               type = types.bool;
 | |
|               default = true;
 | |
|               description = ''
 | |
|                 Whether to listen for HTTPS connections rather than HTTP.
 | |
|               '';
 | |
|             };
 | |
|             x_forwarded = mkOption {
 | |
|               type = types.bool;
 | |
|               default = false;
 | |
|               description = ''
 | |
|                 Use the X-Forwarded-For (XFF) header as the client IP and not the
 | |
|                 actual client IP.
 | |
|               '';
 | |
|             };
 | |
|             resources = mkOption {
 | |
|               type = types.listOf (types.submodule {
 | |
|                 options = {
 | |
|                   names = mkOption {
 | |
|                     type = types.listOf types.str;
 | |
|                     description = ''
 | |
|                       List of resources to host on this listener.
 | |
|                     '';
 | |
|                     example = ["client" "webclient" "federation"];
 | |
|                   };
 | |
|                   compress = mkOption {
 | |
|                     type = types.bool;
 | |
|                     description = ''
 | |
|                       Should synapse compress HTTP responses to clients that support it?
 | |
|                       This should be disabled if running synapse behind a load balancer
 | |
|                       that can do automatic compression.
 | |
|                     '';
 | |
|                   };
 | |
|                 };
 | |
|               });
 | |
|               description = ''
 | |
|                 List of HTTP resources to serve on this listener.
 | |
|               '';
 | |
|             };
 | |
|           };
 | |
|         });
 | |
|         default = [{
 | |
|           port = 8448;
 | |
|           bind_address = "";
 | |
|           type = "http";
 | |
|           tls = true;
 | |
|           x_forwarded = false;
 | |
|           resources = [
 | |
|             { names = ["client" "webclient"]; compress = true; }
 | |
|             { names = ["federation"]; compress = false; }
 | |
|           ];
 | |
|         }];
 | |
|         description = ''
 | |
|           List of ports that Synapse should listen on, their purpose and their configuration.
 | |
|         '';
 | |
|       };
 | |
|       verbose = mkOption {
 | |
|         type = types.str;
 | |
|         default = "0";
 | |
|         description = "Logging verbosity level.";
 | |
|       };
 | |
|       rc_messages_per_second = mkOption {
 | |
|         type = types.str;
 | |
|         default = "0.2";
 | |
|         description = "Number of messages a client can send per second";
 | |
|       };
 | |
|       rc_message_burst_count = mkOption {
 | |
|         type = types.str;
 | |
|         default = "10.0";
 | |
|         description = "Number of message a client can send before being throttled";
 | |
|       };
 | |
|       federation_rc_window_size = mkOption {
 | |
|         type = types.str;
 | |
|         default = "1000";
 | |
|         description = "The federation window size in milliseconds";
 | |
|       };
 | |
|       federation_rc_sleep_limit = mkOption {
 | |
|         type = types.str;
 | |
|         default = "10";
 | |
|         description = ''
 | |
|           The number of federation requests from a single server in a window
 | |
|           before the server will delay processing the request.
 | |
|         '';
 | |
|       };
 | |
|       federation_rc_sleep_delay = mkOption {
 | |
|         type = types.str;
 | |
|         default = "500";
 | |
|         description = ''
 | |
|           The duration in milliseconds to delay processing events from
 | |
|           remote servers by if they go over the sleep limit.
 | |
|         '';
 | |
|       };
 | |
|       federation_rc_reject_limit = mkOption {
 | |
|         type = types.str;
 | |
|         default = "50";
 | |
|         description = ''
 | |
|           The maximum number of concurrent federation requests allowed
 | |
|           from a single server
 | |
|         '';
 | |
|       };
 | |
|       federation_rc_concurrent = mkOption {
 | |
|         type = types.str;
 | |
|         default = "3";
 | |
|         description = "The number of federation requests to concurrently process from a single server";
 | |
|       };
 | |
|       database_type = mkOption {
 | |
|         type = types.enum [ "sqlite3" "psycopg2" ];
 | |
|         default = if versionAtLeast config.system.stateVersion "18.03"
 | |
|           then "psycopg2"
 | |
|           else "sqlite3";
 | |
|         description = ''
 | |
|           The database engine name. Can be sqlite or psycopg2.
 | |
|         '';
 | |
|       };
 | |
|       create_local_database = mkOption {
 | |
|         type = types.bool;
 | |
|         default = true;
 | |
|         description = ''
 | |
|           Whether to create a local database automatically.
 | |
|         '';
 | |
|       };
 | |
|       database_name = mkOption {
 | |
|         type = types.str;
 | |
|         default = "matrix-synapse";
 | |
|         description = "Database name.";
 | |
|       };
 | |
|       database_user = mkOption {
 | |
|         type = types.str;
 | |
|         default = "matrix-synapse";
 | |
|         description = "Database user name.";
 | |
|       };
 | |
|       database_args = mkOption {
 | |
|         type = types.attrs;
 | |
|         default = {
 | |
|           sqlite3 = { database = "${cfg.dataDir}/homeserver.db"; };
 | |
|           psycopg2 = {
 | |
|             user = cfg.database_user;
 | |
|             database = cfg.database_name;
 | |
|           };
 | |
|         }."${cfg.database_type}";
 | |
|         description = ''
 | |
|           Arguments to pass to the engine.
 | |
|         '';
 | |
|       };
 | |
|       event_cache_size = mkOption {
 | |
|         type = types.str;
 | |
|         default = "10K";
 | |
|         description = "Number of events to cache in memory.";
 | |
|       };
 | |
|       url_preview_enabled = mkOption {
 | |
|         type = types.bool;
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Is the preview URL API enabled?  If enabled, you *must* specify an
 | |
|           explicit url_preview_ip_range_blacklist of IPs that the spider is
 | |
|           denied from accessing.
 | |
|         '';
 | |
|       };
 | |
|       url_preview_ip_range_blacklist = mkOption {
 | |
|         type = types.listOf types.str;
 | |
|         default = [
 | |
|           "127.0.0.0/8"
 | |
|           "10.0.0.0/8"
 | |
|           "172.16.0.0/12"
 | |
|           "192.168.0.0/16"
 | |
|           "100.64.0.0/10"
 | |
|           "169.254.0.0/16"
 | |
|         ];
 | |
|         description = ''
 | |
|           List of IP address CIDR ranges that the URL preview spider is denied
 | |
|           from accessing.
 | |
|         '';
 | |
|       };
 | |
|       url_preview_ip_range_whitelist = mkOption {
 | |
|         type = types.listOf types.str;
 | |
|         default = [];
 | |
|         description = ''
 | |
|           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.
 | |
|         '';
 | |
|       };
 | |
|       url_preview_url_blacklist = mkOption {
 | |
|         type = types.listOf types.str;
 | |
|         default = [];
 | |
|         description = ''
 | |
|           Optional list of URL matches that the URL preview spider is
 | |
|           denied from accessing.
 | |
|         '';
 | |
|       };
 | |
|       recaptcha_private_key = mkOption {
 | |
|         type = types.str;
 | |
|         default = "";
 | |
|         description = ''
 | |
|           This Home Server's ReCAPTCHA private key.
 | |
|         '';
 | |
|       };
 | |
|       recaptcha_public_key = mkOption {
 | |
|         type = types.str;
 | |
|         default = "";
 | |
|         description = ''
 | |
|           This Home Server's ReCAPTCHA public key.
 | |
|         '';
 | |
|       };
 | |
|       enable_registration_captcha = mkOption {
 | |
|         type = types.bool;
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Enables ReCaptcha checks when registering, preventing signup
 | |
|           unless a captcha is answered. Requires a valid ReCaptcha
 | |
|           public/private key.
 | |
|         '';
 | |
|       };
 | |
|       turn_uris = mkOption {
 | |
|         type = types.listOf types.str;
 | |
|         default = [];
 | |
|         description = ''
 | |
|           The public URIs of the TURN server to give to clients
 | |
|         '';
 | |
|       };
 | |
|       turn_shared_secret = mkOption {
 | |
|         type = types.str;
 | |
|         default = "";
 | |
|         description = ''
 | |
|           The shared secret used to compute passwords for the TURN server
 | |
|         '';
 | |
|       };
 | |
|       turn_user_lifetime = mkOption {
 | |
|         type = types.str;
 | |
|         default = "1h";
 | |
|         description = "How long generated TURN credentials last";
 | |
|       };
 | |
|       enable_registration = mkOption {
 | |
|         type = types.bool;
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Enable registration for new users.
 | |
|         '';
 | |
|       };
 | |
|       registration_shared_secret = mkOption {
 | |
|         type = types.nullOr types.str;
 | |
|         default = null;
 | |
|         description = ''
 | |
|           If set, allows registration by anyone who also has the shared
 | |
|           secret, even if registration is otherwise disabled.
 | |
|         '';
 | |
|       };
 | |
|       enable_metrics = mkOption {
 | |
|         type = types.bool;
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Enable collection and rendering of performance metrics
 | |
|         '';
 | |
|       };
 | |
|       report_stats = mkOption {
 | |
|         type = types.bool;
 | |
|         default = false;
 | |
|         description = ''
 | |
|         '';
 | |
|       };
 | |
|       servers = mkOption {
 | |
|         type = types.attrsOf (types.attrsOf types.str);
 | |
|         default = {
 | |
|           "matrix.org" = {
 | |
|             "ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
 | |
|           };
 | |
|         };
 | |
|         description = ''
 | |
|           The trusted servers to download signing keys from.
 | |
|         '';
 | |
|       };
 | |
|       max_upload_size = mkOption {
 | |
|         type = types.str;
 | |
|         default = "10M";
 | |
|         description = "The largest allowed upload size in bytes";
 | |
|       };
 | |
|       max_image_pixels = mkOption {
 | |
|         type = types.str;
 | |
|         default = "32M";
 | |
|         description = "Maximum number of pixels that will be thumbnailed";
 | |
|       };
 | |
|       dynamic_thumbnails = mkOption {
 | |
|         type = types.bool;
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Whether to generate new thumbnails on the fly to precisely match
 | |
|           the resolution requested by the client. If true then whenever
 | |
|           a new resolution is requested by the client the server will
 | |
|           generate a new thumbnail. If false the server will pick a thumbnail
 | |
|           from a precalculated list.
 | |
|         '';
 | |
|       };
 | |
|       user_creation_max_duration = mkOption {
 | |
|         type = types.str;
 | |
|         default = "1209600000";
 | |
|         description = ''
 | |
|           Sets the expiry for the short term user creation in
 | |
|           milliseconds. The default value is two weeks.
 | |
|         '';
 | |
|       };
 | |
|       bcrypt_rounds = mkOption {
 | |
|         type = types.str;
 | |
|         default = "12";
 | |
|         description = ''
 | |
|           Set the number of bcrypt rounds used to generate password hash.
 | |
|           Larger numbers increase the work factor needed to generate the hash.
 | |
|         '';
 | |
|       };
 | |
|       allow_guest_access = mkOption {
 | |
|         type = types.bool;
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Allows users to register as guests without a password/email/etc, and
 | |
|           participate in rooms hosted on this server which have been made
 | |
|           accessible to anonymous users.
 | |
|         '';
 | |
|       };
 | |
|       trusted_third_party_id_servers = mkOption {
 | |
|         type = types.listOf types.str;
 | |
|         default = ["matrix.org"];
 | |
|         description = ''
 | |
|           The list of identity servers trusted to verify third party identifiers by this server.
 | |
|         '';
 | |
|       };
 | |
|       room_invite_state_types = mkOption {
 | |
|         type = types.listOf types.str;
 | |
|         default = ["m.room.join_rules" "m.room.canonical_alias" "m.room.avatar" "m.room.name"];
 | |
|         description = ''
 | |
|           A list of event types that will be included in the room_invite_state
 | |
|         '';
 | |
|       };
 | |
|       macaroon_secret_key = mkOption {
 | |
|         type = types.nullOr types.str;
 | |
|         default = null;
 | |
|         description = ''
 | |
|           Secret key for authentication tokens
 | |
|         '';
 | |
|       };
 | |
|       expire_access_token = mkOption {
 | |
|         type = types.bool;
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Whether to enable access token expiration.
 | |
|         '';
 | |
|       };
 | |
|       key_refresh_interval = mkOption {
 | |
|         type = types.str;
 | |
|         default = "1d";
 | |
|         description = ''
 | |
|           How long key response published by this server is valid for.
 | |
|           Used to set the valid_until_ts in /key/v2 APIs.
 | |
|           Determines how quickly servers will query to check which keys
 | |
|           are still valid.
 | |
|         '';
 | |
|       };
 | |
|       app_service_config_files = mkOption {
 | |
|         type = types.listOf types.path;
 | |
|         default = [ ];
 | |
|         description = ''
 | |
|           A list of application service config file to use
 | |
|         '';
 | |
|       };
 | |
|       extraConfig = mkOption {
 | |
|         type = types.lines;
 | |
|         default = "";
 | |
|         description = ''
 | |
|           Extra config options for matrix-synapse.
 | |
|         '';
 | |
|       };
 | |
|       extraConfigFiles = mkOption {
 | |
|         type = types.listOf types.path;
 | |
|         default = [];
 | |
|         description = ''
 | |
|           Extra config files to include.
 | |
| 
 | |
|           The configuration files will be included based on the command line
 | |
|           argument --config-path. This allows to configure secrets without
 | |
|           having to go through the Nix store, e.g. based on deployment keys if
 | |
|           NixOPS is in use.
 | |
|         '';
 | |
|       };
 | |
|       logConfig = mkOption {
 | |
|         type = types.lines;
 | |
|         default = readFile ./matrix-synapse-log_config.yaml;
 | |
|         description = ''
 | |
|           A yaml python logging config file
 | |
|         '';
 | |
|       };
 | |
|       dataDir = mkOption {
 | |
|         type = types.str;
 | |
|         default = "/var/lib/matrix-synapse";
 | |
|         description = ''
 | |
|           The directory where matrix-synapse stores its stateful data such as
 | |
|           certificates, media and uploads.
 | |
|         '';
 | |
|       };
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   config = mkIf cfg.enable {
 | |
|     users.users = [
 | |
|       { name = "matrix-synapse";
 | |
|         group = "matrix-synapse";
 | |
|         home = cfg.dataDir;
 | |
|         createHome = true;
 | |
|         shell = "${pkgs.bash}/bin/bash";
 | |
|         uid = config.ids.uids.matrix-synapse;
 | |
|       } ];
 | |
| 
 | |
|     users.groups = [
 | |
|       { name = "matrix-synapse";
 | |
|         gid = config.ids.gids.matrix-synapse;
 | |
|       } ];
 | |
| 
 | |
|     services.postgresql.enable = mkIf usePostgresql (mkDefault true);
 | |
| 
 | |
|     systemd.services.matrix-synapse = {
 | |
|       description = "Synapse Matrix homeserver";
 | |
|       after = [ "network.target" "postgresql.service" ];
 | |
|       wantedBy = [ "multi-user.target" ];
 | |
|       preStart = ''
 | |
|         ${cfg.package}/bin/homeserver \
 | |
|           --config-path ${configFile} \
 | |
|           --keys-directory ${cfg.dataDir} \
 | |
|           --generate-keys
 | |
|       '' + optionalString (usePostgresql && cfg.create_local_database) ''
 | |
|         if ! test -e "${cfg.dataDir}/db-created"; then
 | |
|           ${pkgs.sudo}/bin/sudo -u ${pg.superUser} \
 | |
|             ${pg.package}/bin/createuser \
 | |
|             --login \
 | |
|             --no-createdb \
 | |
|             --no-createrole \
 | |
|             --encrypted \
 | |
|             ${cfg.database_user}
 | |
|           ${pkgs.sudo}/bin/sudo -u ${pg.superUser} \
 | |
|             ${pg.package}/bin/createdb \
 | |
|             --owner=${cfg.database_user} \
 | |
|             --encoding=UTF8 \
 | |
|             --lc-collate=C \
 | |
|             --lc-ctype=C \
 | |
|             --template=template0 \
 | |
|             ${cfg.database_name}
 | |
|           touch "${cfg.dataDir}/db-created"
 | |
|         fi
 | |
|       '';
 | |
|       serviceConfig = {
 | |
|         Type = "simple";
 | |
|         User = "matrix-synapse";
 | |
|         Group = "matrix-synapse";
 | |
|         WorkingDirectory = cfg.dataDir;
 | |
|         PermissionsStartOnly = true;
 | |
|         ExecStart = ''
 | |
|           ${cfg.package}/bin/homeserver \
 | |
|             ${ concatMapStringsSep "\n  " (x: "--config-path ${x} \\") ([ configFile ] ++ cfg.extraConfigFiles) }
 | |
|             --keys-directory ${cfg.dataDir}
 | |
|         '';
 | |
|         ExecReload = "${pkgs.utillinux}/bin/kill -HUP $MAINPID";
 | |
|         Restart = "on-failure";
 | |
|       };
 | |
|     };
 | |
|   };
 | |
| }
 |