{ config, lib, pkgs, ... }: let cfg = config.services.matrix-synapse; fqdn = "matrix.sbruder.de"; domain = "sbruder.de"; in { sops.secrets = { synapse-registration-shared-secret = { owner = "matrix-synapse"; sopsFile = ../../secrets.yaml; }; synapse-turn-shared-secret = { owner = "matrix-synapse"; sopsFile = ../../secrets.yaml; }; }; systemd.services.matrix-synapse.serviceConfig.SupplementaryGroups = lib.singleton "keys"; services.matrix-synapse = { enable = true; server_name = domain; public_baseurl = "https://${fqdn}"; listeners = lib.singleton { port = 8008; bind_address = "127.0.0.1"; type = "http"; tls = false; x_forwarded = true; resources = lib.singleton { names = [ "client" "federation" "metrics" ]; compress = false; }; }; dataDir = "/data/matrix/synapse"; turn_uris = [ "turns:turn.sbruder.de:5349?transport=udp" "turns:turn.sbruder.de:5349?transport=tcp" "turn:turn.sbruder.de:3478?transport=udp" "turn:turn.sbruder.de:3478?transport=tcp" ]; turn_user_lifetime = "3600000"; # 1h enable_metrics = true; # adapted from https://github.com/NixOS/nixpkgs/blob/7e10bf4327491a6ebccbe1aaa8e6c6c0aca4663a/nixos/modules/services/misc/matrix-synapse-log_config.yaml # - set root.level to WARNING instead of INFO logConfig = builtins.toJSON { version = 1; formatters.journal_fmt.format = "%(name)s: [%(request)s] %(message)s"; filters.context = { "()" = "synapse.util.logcontext.LoggingContextFilter"; request = ""; }; handlers.journal = { class = "systemd.journal.JournalHandler"; formatter = "journal_fmt"; filters = [ "context" ]; SYSLOG_IDENTIFIER = "synapse"; }; root = { level = "WARNING"; handlers = [ "journal" ]; }; disable_existing_loggers = false; }; max_upload_size = "50M"; extraConfig = '' # I’m okay with using matrix.org as trusted key server suppress_key_server_warning: true ''; extraConfigFiles = with config.sops.secrets; [ synapse-registration-shared-secret.path synapse-turn-shared-secret.path ]; }; services.postgresql = { enable = true; # synapse requires custom databse configuration: # CREATE DATABASE "matrix-synapse" TEMPLATE template0 LC_COLLATE "C" LC_CTYPE "C"; ensureUsers = lib.singleton { name = "matrix-synapse"; ensurePermissions = { "DATABASE \"matrix-synapse\"" = "ALL PRIVILEGES"; }; }; }; services.nginx.virtualHosts = { "${fqdn}" = { enableACME = true; forceSSL = true; locations."/".return = "301 https://chat.sbruder.de"; locations."/_matrix" = let listenerCfg = (lib.elemAt cfg.listeners 0); in { proxyPass = "http://${listenerCfg.bind_address}:${toString listenerCfg.port}"; extraConfig = '' client_max_body_size ${cfg.max_upload_size}; ''; }; }; "${domain}" = { enableACME = true; forceSSL = true; locations = let # workaround for nginx dropping parent headers # see https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md parentHeaders = lib.concatStringsSep "\n" (lib.filter (lib.hasPrefix "add_header ") (lib.splitString "\n" config.services.nginx.commonHttpConfig)); in { "=/.well-known/matrix/server".extraConfig = '' ${parentHeaders} add_header Content-Type application/json; return 200 '${builtins.toJSON { "m.server" = "${fqdn}:443"; }}'; ''; "=/.well-known/matrix/client".extraConfig = '' ${parentHeaders} add_header Content-Type application/json; add_header Access-Control-Allow-Origin *; return 200 '${builtins.toJSON { "m.homeserver"."base_url" = "https://${fqdn}"; }}'; ''; }; }; }; }