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.nix231
1 files changed, 231 insertions, 0 deletions
diff --git a/modules/services/matrix-homeserver.nix b/modules/services/matrix-homeserver.nix
new file mode 100644
index 0000000..6af8f7f
--- /dev/null
+++ b/modules/services/matrix-homeserver.nix
@@ -0,0 +1,231 @@
+{ config, lib, ... }:
+
+with lib;
+let
+ cfg = config.modules.services.matrix-homeserver;
+
+ database = {
+ connection_string = "postgres:///dendrite?host=/run/postgresql";
+ max_open_conns = 100;
+ max_idle_conns = 5;
+ conn_max_lifetime = -1;
+ };
+in
+{
+ imports = [
+ ../../overlays/sliding-sync-module.nix
+ ];
+
+ 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.str; description = "path to the server key"; };
+ dendrite-envs = mkOption { type = types.nullOr types.str; description = "path for the environment file to source"; };
+ sliding-sync-secret = mkOption { type = types.nullOr types.str; description = "path to the sliding sync secret"; };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ # Adapted from Mic92/dotfiles, (C) 2021 Jörg Thalheim (MIT)
+ services.dendrite = {
+ enable = true;
+ settings = {
+ global = {
+ server_name = cfg.domain;
+ # `private_key` has the type `path`
+ # prefix a `/` to make `path` happy
+ private_key = "/$CREDENTIALS_DIRECTORY/matrix-server-key";
+ jetstream.storage_path = "/var/lib/dendrite/jetstream";
+ trusted_third_party_id_servers = [
+ "matrix.org"
+ "vector.im"
+ ];
+ metrics.enabled = true;
+ };
+ logging = [
+ {
+ type = "std";
+ level = "info"; # "warn" on public release
+ }
+ ];
+ app_service_api = {
+ inherit database;
+ config_files = [ ];
+ };
+ client_api = {
+ registration_disabled = true;
+ rate_limiting.enabled = false;
+ rate_limiting.exempt_user_ids = [
+ "@abuse:${cfg.domain}"
+ ];
+ # registration_shared_secret = ""; # Initially set this option to configure the admin user.
+ } // optionalAttrs cfg.turn.enable {
+ turn = {
+ turn_user_lifetime = "24h";
+ 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"
+ ];
+ turn_shared_secret = cfg.turn.shared_secret;
+ };
+ };
+ media_api = {
+ inherit database;
+ dynamic_thumbnails = true;
+ };
+ room_server = {
+ inherit database;
+ };
+ push_server = {
+ inherit database;
+ };
+ mscs = {
+ inherit database;
+ mscs = [ "msc2836" "msc2946" ];
+ };
+ sync_api = {
+ inherit database;
+ real_ip_header = "X-Real-IP";
+ # The NixOS option is 'enable', which doesn't exist in Dendrite.
+ search.enabled = true;
+ };
+ key_server = {
+ inherit database;
+ };
+ federation_api = {
+ inherit database;
+ key_perspectives = [
+ {
+ server_name = "matrix.org";
+ keys = [
+ {
+ key_id = "ed25519:auto";
+ public_key = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
+ }
+ {
+ key_id = "ed25519:a_RXGa";
+ public_key = "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ";
+ }
+ ];
+ }
+ ];
+ prefer_direct_fetch = false;
+ };
+ user_api = {
+ account_database = database;
+ device_database = database;
+ };
+ };
+ loadCredential = [ "matrix-server-key:${cfg.secrets.matrix-server-key}" ];
+ } // optionalAttrs (cfg.secrets.dendrite-envs != null) {
+ environmentFile = cfg.secrets.dendrite-envs;
+ };
+
+ services.prometheus.scrapeConfigs = [
+ {
+ job_name = "dendrite";
+ static_configs = [{
+ targets = [ "127.0.0.1:${toString config.services.dendrite.httpPort}" ];
+ }];
+ }
+ ];
+
+ systemd.services.dendrite = {
+ after = [ "postgresql.service" ];
+ };
+
+ environment.persistence."/persist".directories = [
+ "/var/lib/private/dendrite"
+ ];
+
+ services.sliding-sync = {
+ enable = true;
+ server = "https://${cfg.realHost}";
+ bindAddr = "[::1]:8009";
+ db = "postgres:///syncv3?host=/run/postgresql";
+ secret = cfg.secrets.sliding-sync-secret;
+ after = [ "dendrite.service" ];
+ };
+
+ services.postgresql.enable = true;
+ services.postgresql.ensureDatabases = [ "dendrite" "syncv3" ];
+ services.postgresql.ensureUsers = [
+ {
+ name = "dendrite";
+ ensurePermissions."DATABASE dendrite" = "ALL PRIVILEGES";
+ }
+ {
+ name = "sliding-sync";
+ ensurePermissions."DATABASE syncv3" = "ALL PRIVILEGES";
+ }
+ ];
+
+ 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-Real-IP $remote_addr;
+ proxy_read_timeout 600;
+ client_max_body_size 50M;
+ '';
+ locations."/_matrix".proxyPass = "http://[::1]:${toString config.services.dendrite.httpPort}";
+ locations."/_dendrite".proxyPass = "http://[::1]:${toString config.services.dendrite.httpPort}";
+ locations."/_synapse".proxyPass = "http://[::1]:${toString config.services.dendrite.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.sliding-sync.bindAddr}";
+ };
+
+ networking.firewall.allowedTCPPorts = [ 443 8448 ];
+ };
+}