{
  config,
  lib,
  sec,
  ...
}:
let
  inherit (config.machine.synapse)
    domain
    enable
    port
    metrics
    ;
in
with lib;
mkIf enable {
  services.matrix-synapse = {
    inherit enable;
    enableRegistrationScript = true;
    settings = {
      server_name = domain;
      public_baseurl = "https://${domain}";
      signing_key_path = sec."matrix/signingKey".path;
      listeners = [
        {
          inherit port;
          bind_addresses = [ "::1" ];
          type = "http";
          tls = false;
          x_forwarded = true;
          resources = [
            {
              compress = true;
              names = [
                "client"
                "federation"
              ];
            }
          ];
        }
      ]
      ++ (optionals metrics.enable [
        {
          inherit (metrics) port;
          bind_addresses = [ "127.0.0.1" ];
          type = "metrics";
          tls = false;
          resources = [
            {
              names = [ "metrics" ];
            }
          ];
        }
      ]);

      enable_metrics = metrics.enable;

      enable_registration = true;
      enable_registration_without_verification = false;

      allow_public_rooms_over_federation = true;
      federation_domain_whitelist = null;

      allow_public_rooms_without_auth = true;

      ip_range_blacklist = [
        "127.0.0.0/8"
        "10.0.0.0/8"
        "172.16.0.0/12"
        "192.168.0.0/16"
        "100.64.0.0/10"
        "169.254.0.0/16"
        "::1/128"
        "fe80::/10"
        "fc00::/7"
        "::/0" # disable IPv6 (temporary)
      ];

      url_preview_enabled = true;
      url_preview_ip_range_blacklist = [
        "127.0.0.0/8"
        "10.0.0.0/8"
        "172.16.0.0/12"
        "192.168.0.0/16"
        "100.64.0.0/10"
        "169.254.0.0/16"
        "::1/128"
        "fe80::/10"
        "fc00::/7"
      ];

      dynamic_thumbnails = true;
      max_upload_size = "50M";
      media_retention = {
        local_media_lifetime = "90d";
        remote_media_lifetime = "14d";
      };

      retention = {
        enabled = true;
        default_policy.max_lifetime = "180d";
        purge_jobs = [
          { interval = "1d"; }
        ];
      };
    };
  };
}
