aboutsummaryrefslogtreecommitdiff
path: root/modules/services/matrix-homeserver.nix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/services/matrix-homeserver.nix')
-rw-r--r--modules/services/matrix-homeserver.nix190
1 files changed, 190 insertions, 0 deletions
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 ];
+ };
+}