{ config, lib, pkgs, ... }: let cfg = config.services.matrix-synapse; baseUrl = "https://${cfg.settings.server_name}"; baseClientConfig = { "m.homeserver".base_url = baseUrl; "m.identity_server".base_url = "https://vector.im"; }; livekitConfig = optionalAttrs config.services.livekit.enable { "org.matrix.msc3575.proxy".url = baseUrl; "org.matrix.msc4143.rtc_foci" = [ { type = "livekit"; livekit_service_url = baseUrl + "/livekit/jwt"; } ]; }; clientConfig = baseClientConfig // livekitConfig; serverConfig."m.server" = "${cfg.settings.server_name}:443"; mkWellKnown = data: '' default_type application/json; add_header Access-Control-Allow-Origin *; return 200 '${builtins.toJSON data}'; ''; inherit (lib) mkEnableOption mkIf mkMerge mkOption optionalAttrs types ; in { imports = [ ./bridges.nix ./livekit.nix ]; options.services.matrix-synapse = { port = mkOption { type = types.nullOr types.port; default = 8008; description = '' The port to listen for HTTP(S) requests on (will be applied to a listener). ''; }; coturn = { enable = mkEnableOption "Coturn integration for Matrix Synapse."; realm = mkOption { type = types.str; default = "turn.${config.networking.domain}"; description = "Realm for the coturn server used by Matrix Synapse."; }; listening-port = mkOption { type = types.port; default = 3478; }; tls-listening-port = mkOption { type = types.port; default = 5349; }; alt-listening-port = mkOption { type = types.port; default = 3479; }; alt-tls-listening-port = mkOption { type = types.port; default = 5350; }; }; sops = mkEnableOption "SOPS integration"; }; config = mkIf cfg.enable { services.postgresql = { enable = true; initialScript = pkgs.writeText "synapse-init.sql" '' CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse'; CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" TEMPLATE template0 LC_COLLATE = 'C' LC_CTYPE = 'C'; ''; }; services.matrix-synapse = mkMerge [ { settings = { registration_shared_secret_path = mkIf cfg.sops config.sops.secrets."matrix/registration-shared-secret".path; server_name = config.networking.domain; public_baseurl = baseUrl; listeners = [ { inherit (cfg) port; bind_addresses = [ "127.0.0.1" ]; resources = [ { compress = true; names = [ "client" ]; } { compress = false; names = [ "federation" ]; } ]; tls = false; type = "http"; x_forwarded = true; } ]; }; } (mkIf cfg.coturn.enable { settings = { turn_uris = with cfg.coturn; [ "turn:${realm}:${toString listening-port}?transport=udp" "turn:${realm}:${toString listening-port}?transport=tcp" "turn:${realm}:${toString tls-listening-port}?transport=udp" "turn:${realm}:${toString tls-listening-port}?transport=tcp" "turn:${realm}:${toString alt-listening-port}?transport=udp" "turn:${realm}:${toString alt-listening-port}?transport=tcp" "turn:${realm}:${toString alt-tls-listening-port}?transport=udp" "turn:${realm}:${toString alt-tls-listening-port}?transport=tcp" ]; extraConfigFiles = mkIf cfg.sops [ config.sops.templates."coturn/static-auth-secret.env".path ]; turn_user_lifetime = "1h"; }; }) ]; environment.shellAliases = mkIf cfg.sops { register_new_matrix_user = "${cfg.package}/bin/register_new_matrix_user -k $(sudo cat ${cfg.settings.registration_shared_secret_path})"; }; services.nginx.virtualHosts."${cfg.settings.server_name}" = { enableACME = true; forceSSL = true; locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; locations."/_matrix".proxyPass = "http://127.0.0.1:${toString cfg.port}"; locations."/_synapse".proxyPass = "http://127.0.0.1:${toString cfg.port}"; }; sops = mkIf cfg.sops { secrets = mkMerge [ { "matrix/registration-shared-secret" = { owner = "matrix-synapse"; group = "matrix-synapse"; mode = "0400"; }; } (mkIf cfg.coturn.enable { "coturn/static-auth-secret" = { owner = "turnserver"; group = "turnserver"; mode = "0400"; }; }) ]; templates = mkIf cfg.coturn.enable { "coturn/static-auth-secret.env" = { owner = "matrix-synapse"; group = "matrix-synapse"; mode = "0400"; content = '' static-auth-secret=${config.sops.placeholder."coturn/static-auth-secret"} ''; }; }; }; }; }