{ lib, config, inputs, pkgs, ... }: let root_host = "grimmauld.de"; matrix_host = "matrix.${root_host}"; in { services.postgresql = { enable = true; # CREATE DATABASE synapse ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' template=template0 OWNER synapse; ensureDatabases = [ "synapse" ]; package = pkgs.postgresql_15; ensureUsers = [ { name = "synapse"; ensureDBOwnership = true; } ]; authentication = pkgs.lib.mkOverride 10 '' #type database DBuser auth-method local all postgres peer local all all peer host all all 127.0.0.1/32 md5 host synapse matrix-synapse ::1/128 md5 host all all ::1/128 md5 local replication all peer host replication all 127.0.0.1/32 md5 host replication all ::1/128 md5 ''; identMap = '' # ArbitraryMapName systemUser DBUser superuser_map root postgres superuser_map matrix-synapse synapse superuser_map postgres postgres # Let other names login as themselves superuser_map /^(.*)$ \1 ''; }; systemd.services.postgresql.postStart = let password_file_path = config.age.secrets.synapse_db_pass.path; in '' $PSQL -tA <<'EOF' DO $$ DECLARE password TEXT; BEGIN password := trim(both from replace(pg_read_file('${password_file_path}'), E'\n', ''')); EXECUTE format('ALTER ROLE synapse WITH PASSWORD '''%s''';', password); END $$; EOF ''; services.matrix-synapse-next = { enable = true; workers.federationSenders = 1; workers.federationReceivers = 1; workers.initialSyncers = 1; workers.normalSyncers = 1; workers.eventPersisters = 2; workers.useUserDirectoryWorker = true; enableNginx = true; enableSlidingSync = false; settings = { server_name = root_host; public_baseurl = "https://${root_host}"; enable_registration = false; enable_registration_without_verification = true; # registrations_require_3pid = [ "email" ]; database = { name = "psycopg2"; args = { host = "localhost"; port = 5432; dbname = "synapse"; user = "synapse"; cp_min = 5; cp_max = 10; client_encoding = "auto"; passfile = config.age.secrets.synapse_db_pass_prepared.path; }; }; }; }; services.redis.servers."".enable = true; age.secrets.synapse_db_pass = { file = ../secrets/synapse_db_pass.age; owner = "postgres"; group = "postgres"; }; age.secrets.synapse_db_pass_prepared = { file = ../secrets/synapse_db_pass_prepared.age; owner = "matrix-synapse"; group = "matrix-synapse"; mode = "0600"; }; services.nginx = { enable = true; virtualHosts."${root_host}" = { forceSSL = true; enableACME = false; # use the cert above, not some weird one that matrix-synapse module supplies useACMEHost = root_host; locations."/.well-known/matrix/server" = { return = "200 '{\"m.server\":\"${matrix_host}:443\"}'"; extraConfig = '' default_type application/json; add_header Access-Control-Allow-Origin *; add_header Accept-Ranges bytes;''; }; locations."/.well-known/matrix/client" = { return = "200 '{\"m.homeserver\": {\"base_url\": \"https://${matrix_host}\"}}'"; extraConfig = '' add_header Access-Control-Allow-Origin *; default_type application/json; ''; }; locations."/_matrix" = { proxyPass = "http://$synapse_backend"; extraConfig = '' add_header X-debug-backend $synapse_backend; add_header X-debug-group $synapse_uri_group; client_max_body_size ${config.services.matrix-synapse-next.settings.max_upload_size}; proxy_read_timeout 10m; ''; }; locations."~ ^/_matrix/client/(r0|v3)/sync$" = { proxyPass = "http://$synapse_backend"; extraConfig = '' proxy_read_timeout 1h; ''; }; locations."~ ^/_matrix/client/(api/v1|r0|v3)/initialSync$" = { proxyPass = "http://synapse_worker_initial_sync"; extraConfig = '' proxy_read_timeout 1h; ''; }; locations."~ ^/_matrix/client/(api/v1|r0|v3)/rooms/[^/]+/initialSync$" = { proxyPass = "http://synapse_worker_initial_sync"; extraConfig = '' proxy_read_timeout 1h; ''; }; locations."/_synapse/client" = { proxyPass = "http://$synapse_backend"; }; locations."/.well-known/matrix" = { proxyPass = "http://$synapse_backend"; }; }; }; # networking.firewall.allowedTCPPorts = [ 8448 8008 ]; }