From 8e9b074467006c76768efe04cf1fb1ef9d652c67 Mon Sep 17 00:00:00 2001 From: sefidel Date: Wed, 24 Jan 2024 13:29:27 +0900 Subject: initial commit --- modules/services/matrix-homeserver.nix | 190 +++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 modules/services/matrix-homeserver.nix (limited to 'modules/services/matrix-homeserver.nix') diff --git a/modules/services/matrix-homeserver.nix b/modules/services/matrix-homeserver.nix new file mode 100644 index 0000000..3dc188b --- /dev/null +++ b/modules/services/matrix-homeserver.nix @@ -0,0 +1,190 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.modules.services.matrix-homeserver; + + httpPort = 8008; + slidingSyncPort = 8009; + metricsPort = 8010; +in +{ + options.modules.services.matrix-homeserver = { + enable = mkEnableOption "matrix homeserver instance"; + domain = mkOption { type = types.str; }; + realHost = mkOption { type = types.str; default = "matrix.${cfg.domain}"; }; + slidingSyncHost = mkOption { type = types.str; default = "slidingsync.${cfg.domain}"; }; + turn = { + enable = mkEnableOption "VOIP using TURN"; + domain = mkOption { type = types.str; default = "turn.${cfg.domain}"; }; + shared_secret = mkOption { type = types.str; }; + }; + secrets = { + matrix-server-key = mkOption { type = types.path; description = "path to the server key"; }; + matrix-shared-secret = mkOption { type = types.path; description = "path to the registration shared secret"; }; + extra-config-path = mkOption { type = types.nullOr types.path; description = "path to the extra configuration file to source"; }; + sliding-sync-secret = mkOption { type = types.nullOr types.path; description = "path to the sliding sync secret"; }; + }; + }; + + config = mkIf cfg.enable { + services.matrix-synapse = { + enable = true; + withJemalloc = true; + dataDir = "/var/lib/matrix-synapse"; + settings = { + server_name = cfg.domain; + public_baseurl = "https://${cfg.realHost}"; + + signing_key_path = cfg.secrets.matrix-server-key; + + allow_guest_access = false; + enable_registration = false; + registration_requires_token = true; + registration_shared_secret_path = cfg.secrets.matrix-shared-secret; + + enable_metrics = true; + url_preview_enabled = true; + + database = { + name = "psycopg2"; + args.password = "synapse"; + }; + + listeners = [ + { + port = httpPort; + resources = [ + { + compress = true; + names = [ "client" ]; + } + { + compress = false; + names = [ "federation" ]; + } + ]; + type = "http"; + tls = false; + x_forwarded = true; + } + { + port = metricsPort; + resources = [{ + compress = false; + names = [ "metrics" ]; + }]; + type = "metrics"; + tls = false; + } + ]; + + trusted_key_servers = [{ + server_name = "matrix.org"; + verify_keys = { + "ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"; + }; + }]; + # Yes, we want to use matrix.org as our trusted key server + suppress_key_server_warning = true; + } // optionalAttrs (cfg.turn.enable) { + turn_uris = [ + "turns:${cfg.turn.domain}?transport=udp" + "turns:${cfg.turn.domain}?transport=tcp" + "turn:${cfg.turn.domain}?transport=udp" + "turn:${cfg.turn.domain}?transport=tcp" + ]; + }; + }; + + services.matrix-sliding-sync = { + enable = true; + createDatabase = true; + settings = { + SYNCV3_SERVER = "https://${cfg.realHost}"; + SYNCV3_BINDADDR = "[::1]:${toString slidingSyncPort}"; + }; + environmentFile = cfg.secrets.sliding-sync-secret; + }; + + services.prometheus.scrapeConfigs = [ + { + job_name = "synapse"; + metrics_path = "/_synapse/metrics"; + static_configs = [{ + targets = [ "127.0.0.1:${toString metricsPort}" ]; + }]; + } + ]; + + modules.persistence.directories = [ + "/var/lib/matrix-synapse" + ]; + + services.postgresql.enable = true; + services.postgresql.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.nginx.virtualHosts.${cfg.realHost} = { + forceSSL = true; + useACMEHost = cfg.domain; + listen = [ + { addr = "0.0.0.0"; port = 443; ssl = true; } + { addr = "[::]"; port = 443; ssl = true; } + { addr = "0.0.0.0"; port = 8448; ssl = true; } + { addr = "[::]"; port = 8448; ssl = true; } + + ]; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 600; + client_max_body_size ${config.services.matrix-synapse.settings.max_upload_size}; + ''; + + locations."~* ^(\\/_matrix|\\/_synapse\\/client)".proxyPass = "http://[::1]:${toString httpPort}"; + }; + + services.nginx.virtualHosts.${cfg.domain} = + let + server-hello = { "m.server" = "${cfg.realHost}:443"; }; + client-hello = { + "m.homeserver"."base_url" = "https://${cfg.realHost}"; + "m.identity_server"."base_url" = "https://vector.im"; + "org.matrix.msc3575.proxy"."url" = "https://${cfg.slidingSyncHost}"; + }; + in + { + forceSSL = true; + useACMEHost = cfg.domain; + locations = { + "/.well-known/matrix/server" = { + extraConfig = '' + add_header Content-Type application/json; + return 200 '${builtins.toJSON server-hello}'; + ''; + }; + "/.well-known/matrix/client" = { + extraConfig = '' + add_header Content-Type application/json; + add_header Access-Control-Allow-Origin *; + return 200 '${builtins.toJSON client-hello}'; + ''; + }; + }; + }; + + services.nginx.virtualHosts.${cfg.slidingSyncHost} = { + forceSSL = true; + useACMEHost = cfg.domain; + locations."/".proxyPass = "http://${config.services.matrix-sliding-sync.settings.SYNCV3_BINDADDR}"; + }; + + networking.firewall.allowedTCPPorts = [ 443 8448 ]; + }; +} -- cgit 1.4.1