about summary refs log tree commit diff
path: root/modules/nixos/matrix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/nixos/matrix')
-rw-r--r--modules/nixos/matrix/default.nix1
-rw-r--r--modules/nixos/matrix/dendrite.nix157
-rw-r--r--modules/nixos/matrix/element.nix59
-rw-r--r--modules/nixos/matrix/synapse.nix93
4 files changed, 310 insertions, 0 deletions
diff --git a/modules/nixos/matrix/default.nix b/modules/nixos/matrix/default.nix
new file mode 100644
index 0000000..bd221c4
--- /dev/null
+++ b/modules/nixos/matrix/default.nix
@@ -0,0 +1 @@
+_: {imports = [./dendrite.nix ./element.nix ./synapse.nix];}
diff --git a/modules/nixos/matrix/dendrite.nix b/modules/nixos/matrix/dendrite.nix
new file mode 100644
index 0000000..0fad5f2
--- /dev/null
+++ b/modules/nixos/matrix/dendrite.nix
@@ -0,0 +1,157 @@
+{
+  config,
+  lib,
+  inputs,
+  pkgs,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.matrix.dendrite;
+in {
+  options.nixfiles.modules.matrix.dendrite = {
+    enable = mkEnableOption "Dendrite Matrix server";
+
+    domain = mkOption {
+      type = types.str;
+      default = config.networking.domain;
+      description = "Domain name sans protocol scheme.";
+    };
+  };
+
+  config = let
+    db = "dendrite";
+  in
+    mkIf cfg.enable {
+      secrets.dendrite-private-key = {
+        file = "${inputs.self}/secrets/dendrite-private-key";
+        mode = "0444"; # The user is dynamic so the file must be world-readable.
+      };
+      secrets.dendrite-environment-file = {
+        file = "${inputs.self}/secrets/dendrite-environment-file";
+        mode = "0444"; # The user is dynamic so the file must be world-readable.
+      };
+
+      nixfiles.modules = {
+        nginx = {
+          enable = true;
+          upstreams.dendrite.servers."127.0.0.1:${toString config.services.dendrite.httpPort}" = {};
+          virtualHosts.${cfg.domain}.locations = {
+            "/_matrix".proxyPass = "http://dendrite";
+            "= /.well-known/matrix/server" = {
+              extraConfig = ''
+                add_header Content-Type application/json;
+              '';
+              return = "200 '${
+                generators.toJSON {} {"m.server" = "${cfg.domain}:443";}
+              }'";
+            };
+            "= /.well-known/matrix/client" = {
+              extraConfig = ''
+                add_header Content-Type application/json;
+                add_header Access-Control-Allow-Origin *;
+              '';
+              return = "200 '${
+                generators.toJSON {} {
+                  "m.homeserver".base_url = "https://${cfg.domain}";
+                }
+              }'";
+            };
+          };
+        };
+        postgresql = {
+          enable = true;
+          extraPostStart = [
+            ''
+              $PSQL "${db}" -tAc 'GRANT ALL ON SCHEMA "public" TO "${db}"'
+            ''
+          ];
+        };
+      };
+
+      services = {
+        dendrite = {
+          enable = true;
+          httpPort = 8008;
+          environmentFile = config.secrets.dendrite-environment-file.path;
+          settings = {
+            version = 2;
+            global = {
+              server_name = cfg.domain;
+              private_key = config.secrets.dendrite-private-key.path;
+              database = {
+                connection_string = "postgresql://${db}@/${db}?host=/run/postgresql";
+                max_open_conns = 64;
+                max_idle_connections = 8;
+              };
+              cache = {
+                max_size_estimated = "1gb";
+                max_age = "1h";
+              };
+              trusted_third_party_id_servers = [
+                "matrix.org"
+                "nixos.org"
+                "vector.im"
+              ];
+              presence = {
+                enable_inbound = false;
+                enable_outbound = false;
+              };
+            };
+            client_api = {
+              registration_disabled = true;
+              guests_disabled = true;
+              registration_shared_secret = "$REGISTRATION_SHARED_SECRET";
+            };
+            media_api = {
+              max_file_size_bytes = 0;
+              dynamic_thumbnails = true;
+              max_thumbnail_generators = 8;
+              thumbnail_sizes = [
+                {
+                  width = 32;
+                  height = 32;
+                  method = "crop";
+                }
+                {
+                  width = 96;
+                  height = 96;
+                  method = "crop";
+                }
+                {
+                  width = 640;
+                  height = 480;
+                  method = "scale";
+                }
+              ];
+            };
+            logging = [
+              {
+                type = "std";
+                level = "warn";
+              }
+            ];
+          };
+        };
+
+        postgresql = {
+          ensureDatabases = [db];
+          ensureUsers = [
+            {
+              name = db;
+              ensurePermissions."DATABASE \"${db}\"" = "ALL";
+            }
+          ];
+        };
+      };
+
+      systemd.services.dendrite.serviceConfig.ExecStart =
+        mkForce
+        (concatStringsSep " " [
+          "${pkgs.dendrite}/bin/dendrite-monolith-server"
+          "--config /run/dendrite/dendrite.yaml"
+          "--http-bind-address 127.0.0.1:${
+            toString config.services.dendrite.httpPort
+          }"
+        ]);
+    };
+}
diff --git a/modules/nixos/matrix/element.nix b/modules/nixos/matrix/element.nix
new file mode 100644
index 0000000..3d47800
--- /dev/null
+++ b/modules/nixos/matrix/element.nix
@@ -0,0 +1,59 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.matrix.element;
+in {
+  options.nixfiles.modules.matrix.element = {
+    enable = mkEnableOption "Element, a Matrix web interface";
+
+    domain = mkOption {
+      description = "Domain name sans protocol scheme.";
+      type = with types; nullOr str;
+      default = "element.${config.networking.domain}";
+    };
+
+    homeserver = mkOption {
+      description = "Default Matrix homeserver.";
+      type = with types; str;
+      default = my.domain.azahi;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    assertions = [
+      {
+        assertion = with config.nixfiles.modules.matrix;
+          (synapse.enable || dendrite.enable) && !(!synapse.enable && !dendrite.enable);
+        message = "Synapse or Dendrite must be enabled";
+      }
+    ];
+
+    nixfiles.modules.nginx = with cfg; {
+      enable = true;
+      virtualHosts.${domain}.locations."/".root = pkgs.element-web.override {
+        conf = {
+          default_server_config."m.homeserver" = {
+            base_url = "https://${homeserver}";
+            server_name = homeserver;
+          };
+          disable_custom_urls = true;
+          disable_guests = true;
+          disable_login_language_selector = true;
+          disable_3pid_login = true;
+          brand = homeserver;
+          branding.authFooterLinks = [
+            {
+              text = "Hosted on NixOS";
+              url = "https://nixos.org";
+            }
+          ];
+          default_theme = "dark";
+        };
+      };
+    };
+  };
+}
diff --git a/modules/nixos/matrix/synapse.nix b/modules/nixos/matrix/synapse.nix
new file mode 100644
index 0000000..6ff5e0d
--- /dev/null
+++ b/modules/nixos/matrix/synapse.nix
@@ -0,0 +1,93 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.matrix.synapse;
+in {
+  options.nixfiles.modules.matrix.synapse = {
+    enable = mkEnableOption "Synapse Matrix server";
+
+    domain = mkOption {
+      description = "Domain name sans protocol scheme.";
+      type = with types; str;
+      default = config.networking.domain;
+    };
+  };
+
+  config = let
+    bind_address = "127.0.0.1";
+    port = 8448;
+  in
+    mkIf cfg.enable {
+      nixfiles.modules = {
+        nginx = {
+          enable = true;
+          upstreams.synapse.servers."${bind_address}:${toString port}" = {};
+          virtualHosts.${cfg.domain}.locations = {
+            "~ ^(/_matrix|/_synapse/client)".proxyPass = "http://synapse";
+            "= /.well-known/matrix/server" = {
+              extraConfig = ''
+                add_header Content-Type application/json;
+              '';
+              return = "200 '${
+                generators.toJSON {} {"m.server" = "${cfg.domain}:443";}
+              }'";
+            };
+            "= /.well-known/matrix/client" = {
+              extraConfig = ''
+                add_header Content-Type application/json;
+                add_header Access-Control-Allow-Origin *;
+              '';
+              return = "200 '${
+                generators.toJSON {} {
+                  "m.homeserver".base_url = "https://${cfg.domain}";
+                }
+              }'";
+            };
+          };
+        };
+        postgresql.enable = true;
+      };
+
+      services = let
+        db = "synapse";
+      in {
+        matrix-synapse = {
+          enable = true;
+          server_name = config.networking.domain;
+
+          database_type = "psycopg2";
+          database_name = db;
+          database_user = db;
+
+          listeners = [
+            {
+              inherit bind_address port;
+              type = "http";
+              tls = false;
+              x_forwarded = true;
+              resources = [
+                {
+                  names = ["client" "federation"];
+                  compress = false;
+                }
+              ];
+            }
+          ];
+        };
+
+        postgresql = {
+          ensureDatabases = [db];
+          ensureUsers = [
+            {
+              name = db;
+              ensurePermissions."DATABASE \"${db}\"" = "ALL";
+            }
+          ];
+        };
+      };
+    };
+}

Consider giving Nix/NixOS a try! <3