Starting with 1.3.0, matrix-synapse supports notifying systemd. Relevant PR: matrix-org/synapse#5732
		
			
				
	
	
		
			703 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			703 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: "/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"
 | 
						|
          "vector.im"
 | 
						|
        ];
 | 
						|
        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 = "notify";
 | 
						|
        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";
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
}
 |