Replace dendrite with synapse
diff --git a/modules/matrix.nix b/modules/matrix.nix
index f669943..967e9d9 100644
--- a/modules/matrix.nix
+++ b/modules/matrix.nix
@@ -1,71 +1,48 @@
{ base, config, lib, pkgs, ... }:
-let
- postgresUrlFor = service:
- "postgres://dendrite:!!dendrite_db_password!!@localhost:${toString config.services.postgresql.port}/dendrite_${service}?sslmode=disable";
-in
{
- services.dendrite = {
+ services.matrix-synapse = {
enable = true;
- httpPort = 4527;
- settings = {
- global = {
- server_name = "coded.codes";
- private_key = config.sops.secrets.matrix_private_key.path;
- };
- user_api = {
- account_database.connection_string = postgresUrlFor "account_database";
- device_database.connection_string = postgresUrlFor "device_database";
- };
- sync_api = {
- search.enable = true;
- database.connection_string = postgresUrlFor "sync_api";
- };
- room_server.database.connection_string = postgresUrlFor "room_server";
- mscs.database.connection_string = postgresUrlFor "mscs";
- media_api.database.connection_string = postgresUrlFor "media_api";
- key_server.database.connection_string = postgresUrlFor "key_server";
- federation_api.database.connection_string = postgresUrlFor "federation_api";
- app_service_api.database.connection_string = postgresUrlFor "app_service_api";
+ withJemalloc = true;
- client_api.registration_shared_secret = "!!registration_shared_secret!!";
+ settings = {
+ server_name = "coded.codes";
+ enable_registration = true;
+ registration_requires_token = true;
+ registration_shared_secret = "!!registration_shared_secret!!";
+ public_baseurl = "https://matrix-backend.coded.codes/";
+ max_upload_size = "100M";
+ listeners = [{
+ x_forwarded = true;
+ tls = false;
+ resources = [{
+ names = [
+ "client"
+ "federation"
+ ];
+ compress = true;
+ }];
+ port = 4527;
+ }];
+ enable_metrics = true;
+ database.args.database = "synapse";
};
};
- users.users.dendrite = {
- isSystemUser = true;
- createHome = true;
- home = config.systemd.services.dendrite.serviceConfig.WorkingDirectory;
- group = "clicks";
- shell = pkgs.bashInteractive;
- };
-
- systemd.services.dendrite.serviceConfig = {
- DynamicUser = lib.mkForce false;
- User = lib.mkForce config.users.users.dendrite.name;
- Group = lib.mkForce config.users.users.dendrite.group;
- };
-
- sops.secrets = (lib.pipe [
- "registration_shared_secret"
- ] [
- (map (name: {
- inherit name;
- value = {
- mode = "0400";
- owner = config.users.users.root.name;
- group = config.users.users.nobody.group;
- sopsFile = ../secrets/matrix.json;
- format = "json";
- };
- }))
- builtins.listToAttrs
- ]) // {
- matrix_private_key = {
+ sops.secrets = {
+ registration_shared_secret = {
mode = "0400";
- owner = config.users.users.dendrite.name;
- group = config.users.users.dendrite.group;
+ owner = config.users.users.root.name;
+ group = config.users.users.nobody.group;
+ sopsFile = ../secrets/matrix.json;
+ format = "json";
+ };
+ matrix_private_key = {
+ mode = "0600";
+ owner = config.users.users.matrix-synapse.name;
+ group = config.users.users.matrix-synapse.group;
sopsFile = ../secrets/matrix_private_key.pem;
format = "binary";
+ path = config.services.matrix-synapse.settings.signing_key_path;
};
};
} // (
@@ -77,27 +54,77 @@
# Given we use base as an attrset, mkIf will error if base is null in here
then
let
- ExecStartPre = "${base.config.systemd.services.dendrite.serviceConfig.ExecStartPre}";
- dendrite_cfgfile = builtins.head (builtins.match ".*-i ([^[:space:]]+).*" "${ExecStartPre}");
+ synapse_cfgfile = config.services.matrix-synapse.configFile;
in
{
- scalpel.trafos."dendrite.yaml" = {
- source = dendrite_cfgfile;
- matchers."dendrite_db_password".secret =
- config.sops.secrets.dendrite_db_password.path; # Defined in postgres.nix
+ scalpel.trafos."synapse.yaml" = {
+ source = toString synapse_cfgfile;
matchers."registration_shared_secret".secret =
config.sops.secrets.registration_shared_secret.path;
- owner = config.users.users.dendrite.name;
- group = config.users.users.dendrite.group;
+ owner = config.users.users.matrix-synapse.name;
+ group = config.users.users.matrix-synapse.group;
mode = "0400";
};
- systemd.services.dendrite.serviceConfig.ExecStartPre = lib.mkForce (
+ systemd.services.matrix-synapse.serviceConfig.ExecStart = lib.mkForce (
builtins.replaceStrings
- [ "${dendrite_cfgfile}" ]
- [ "${config.scalpel.trafos."dendrite.yaml".destination}" ]
- "${ExecStartPre}"
+ [ "${synapse_cfgfile}" ]
+ [ "${config.scalpel.trafos."synapse.yaml".destination}" ]
+ "${base.config.systemd.services.matrix-synapse.serviceConfig.ExecStart}"
);
+
+ systemd.services.matrix-synapse.preStart = lib.mkForce (
+ builtins.replaceStrings
+ [ "${synapse_cfgfile}" ]
+ [ "${config.scalpel.trafos."synapse.yaml".destination}" ]
+ "${base.config.systemd.services.matrix-synapse.preStart}"
+ );
+
+ environment.systemPackages =
+ with lib; let
+ cfg = config.services.matrix-synapse;
+ registerNewMatrixUser =
+ let
+ isIpv6 = x: lib.length (lib.splitString ":" x) > 1;
+ listener =
+ lib.findFirst
+ (
+ listener: lib.any
+ (
+ resource: lib.any
+ (
+ name: name == "client"
+ )
+ resource.names
+ )
+ listener.resources
+ )
+ (lib.last cfg.settings.listeners)
+ cfg.settings.listeners;
+ # FIXME: Handle cases with missing client listener properly,
+ # don't rely on lib.last, this will not work.
+
+ # add a tail, so that without any bind_addresses we still have a useable address
+ bindAddress = head (listener.bind_addresses ++ [ "127.0.0.1" ]);
+ listenerProtocol =
+ if listener.tls
+ then "https"
+ else "http";
+ in
+ pkgs.writeShellScriptBin "matrix-synapse-register_new_matrix_user" ''
+ exec ${cfg.package}/bin/register_new_matrix_user \
+ $@ \
+ ${lib.concatMapStringsSep " " (x: "-c ${x}") ([
+ config.scalpel.trafos."synapse.yaml".destination ] ++ cfg.extraConfigFiles)} \
+ "${listenerProtocol}://${
+ if (isIpv6 bindAddress) then
+ "[${bindAddress}]"
+ else
+ "${bindAddress}"
+ }:${builtins.toString listener.port}/"
+ '';
+ in
+ [ (lib.meta.hiPrio registerNewMatrixUser) ];
}
else { }
)
diff --git a/modules/postgres.nix b/modules/postgres.nix
index 63e7697..742e3d4 100644
--- a/modules/postgres.nix
+++ b/modules/postgres.nix
@@ -5,7 +5,6 @@
package = pkgs.postgresql;
settings = {
log_connections = true;
- log_statement = "all";
logging_collector = true;
log_disconnections = true;
log_destination = lib.mkForce "syslog";
@@ -20,17 +19,9 @@
};
}
{
- name = "dendrite";
+ name = "synapse";
ensurePermissions = {
- "DATABASE dendrite_account_database" = "ALL PRIVILEGES";
- "DATABASE dendrite_device_database" = "ALL PRIVILEGES";
- "DATABASE dendrite_sync_api" = "ALL PRIVILEGES";
- "DATABASE dendrite_room_server" = "ALL PRIVILEGES";
- "DATABASE dendrite_mscs" = "ALL PRIVILEGES";
- "DATABASE dendrite_media_api" = "ALL PRIVILEGES";
- "DATABASE dendrite_key_server" = "ALL PRIVILEGES";
- "DATABASE dendrite_federation_api" = "ALL PRIVILEGES";
- "DATABASE dendrite_app_service_api" = "ALL PRIVILEGES";
+ "DATABASE synapse" = "ALL PRIVILEGES";
};
}
] ++ (map
@@ -41,33 +32,39 @@
}
)) [ "minion" "coded" "pinea" ]);
- ensureDatabases = [
- "dendrite_account_database"
- "dendrite_device_database"
- "dendrite_sync_api"
- "dendrite_sync_api"
- "dendrite_room_server"
- "dendrite_mscs"
- "dendrite_media_api"
- "dendrite_key_server"
- "dendrite_federation_api"
- "dendrite_app_service_api"
- ];
};
- systemd.services.postgresql.postStart = lib.mkAfter (lib.pipe [
- { user = "clicks_grafana"; passwordFile = config.sops.secrets.clicks_grafana_db_password.path; }
- { user = "dendrite"; passwordFile = config.sops.secrets.dendrite_db_password.path; }
- ] [
- (map (userData: ''
- $PSQL -tAc "ALTER USER ${userData.user} PASSWORD '$(cat ${userData.passwordFile})';"
- ''))
- (lib.concatStringsSep "\n")
- ]);
+ systemd.services.postgresql.postStart = lib.mkMerge [
+ (
+ let
+ database = "synapse";
+ cfg = config.services.postgresql;
+ in
+ lib.mkBefore (
+ ''
+ PSQL="psql --port=${toString cfg.port}"
+
+ while ! $PSQL -d postgres -c "" 2> /dev/null; do
+ if ! kill -0 "$MAINPID"; then exit 1; fi
+ sleep 0.1
+ done
+
+ $PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${database}'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "${database}" WITH LC_CTYPE="C" LC_COLLATE="C" TEMPLATE="template0"'
+ ''
+ ) # synapse needs C collation, so we can't use ensureDatabases for it
+ )
+ (lib.mkAfter (lib.pipe [
+ { user = "clicks_grafana"; passwordFile = config.sops.secrets.clicks_grafana_db_password.path; }
+ ] [
+ (map (userData: ''
+ $PSQL -tAc "ALTER USER ${userData.user} PASSWORD '$(cat ${userData.passwordFile})';"
+ ''))
+ (lib.concatStringsSep "\n")
+ ]))
+ ];
sops.secrets = lib.pipe [
"clicks_grafana_db_password"
- "dendrite_db_password"
] [
(map (name: {
inherit name;