{ config, pkgs, ... }: let # 1. create DNS entry `_matrix._tcp.ingolf-wagner.de SRV - 10 8448 matrix.ingolf-wagner.de` (8448 for federation) # 2. create DNS entry `matrix.ingolf-wagner.de A - 95.216.66.212` # 3. test with : https://federationtester.matrix.org/#ingolf-wagner.de # 4. info at : https://silvio.github.io/docker-matrix/Example.configs.html domain = "ingolf-wagner.de"; baseUrl = "https://matrix.${domain}"; matrix_create_user = pkgs.writers.writeBashBin "matrix-create-user" '' ${pkgs.matrix-synapse}/bin/register_new_matrix_user \ -k $( ${pkgs.gojq}/bin/gojq \ --yaml-input \ --raw-output \ '.registration_shared_secret' \ ${config.sops.secrets.matrix_shared_secret.path} ) \ http://localhost:8008 ''; clientConfig."m.homeserver".base_url = baseUrl; serverConfig."m.server" = "matrix.${domain}:443"; mkWellKnown = data: '' default_type application/json; add_header Access-Control-Allow-Origin *; return 200 '${builtins.toJSON data}'; ''; element-web = pkgs.runCommand "element-web-with-config" { nativeBuildInputs = [ pkgs.buildPackages.jq ]; } '' cp -r ${pkgs.element-web} $out chmod -R u+w $out jq '."default_server_config"."m.homeserver" = { "base_url": "https://matrix.${domain}", "server_name": "${domain}" }' \ > $out/config.json < ${pkgs.element-web}/config.json ln -s $out/config.json $out/config.matrix.${domain}.json ''; in { networking.firewall.allowedTCPPorts = [ 80 443 8448 ]; networking.firewall.allowedUDPPorts = [ 80 443 8448 ]; environment.systemPackages = [ matrix_create_user ]; sops.secrets.matrix_shared_secret.owner = "matrix-synapse"; users.users.matrix-synapse = { isSystemUser = true; uid = config.ids.uids.matrix-synapse; group = "matrix-synapse"; }; users.groups.matrix-synapse.gid = config.ids.gids.matrix-synapse; # todo : mount postgresql folder in a dedicated zfs pool containers.matrix-ingolf-wagner-de = { autoStart = true; privateNetwork = false; bindMounts = { rootpassword = { hostPath = config.sops.secrets.matrix_shared_secret.path; mountPoint = "/run/secrets/matrix-shared-secret"; isReadOnly = true; }; }; config = { config, pkgs, lib, ... }: { system.stateVersion = "23.11"; services.postgresql = { enable = true; initialScript = pkgs.writeText "synapse-init.sql" '' CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse'; CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" TEMPLATE template0 LC_COLLATE = "C" LC_CTYPE = "C"; ''; }; services.matrix-synapse = { enable = true; settings.server_name = domain; # The public base URL value must match the `base_url` value set in `clientConfig` above. # The default value here is based on `server_name`, so if your `server_name` is different # from the value of `matrix.` above, you will likely run into some mismatched domain names # in client applications. settings.public_baseurl = baseUrl; extraConfigFiles = [ "/run/secrets/matrix-shared-secret" ]; settings.listeners = [ { port = 8008; bind_addresses = [ "::1" ]; type = "http"; tls = false; x_forwarded = true; #resources = [{ # names = [ "client" "federation" ]; # compress = true; #}]; resources = [ { names = [ "client" ]; compress = true; } { names = [ "federation" ]; compress = false; } ]; } ]; }; }; }; services.nginx = { enable = true; recommendedTlsSettings = true; recommendedOptimisation = true; recommendedGzipSettings = true; recommendedProxySettings = true; virtualHosts = { # If the A and AAAA DNS records on example.org do not point on the same host as the # records for myhostname.example.org, you can easily move the /.well-known # virtualHost section of the code to the host that is serving example.org, while # the rest stays on myhostname.example.org with no other changes required. # This pattern also allows to seamlessly move the homeserver from # myhostname.example.org to myotherhost.example.org by only changing the # /.well-known redirection target. #"${domain}" = { # enableACME = true; # forceSSL = true; # # This section is not needed if the server_name of matrix-synapse is equal to # # the domain (i.e. example.org from @foo:example.org) and the federation port # # is 8448. # # Further reference can be found in the docs about delegation under # # https://element-hq.github.io/synapse/latest/delegate.html # locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; # # This is usually needed for homeserver discovery (from e.g. other Matrix clients). # # Further reference can be found in the upstream docs at # # https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient # locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; #}; "matrix.${domain}" = { listen = [ { addr = "0.0.0.0"; port = 80; } { addr = "0.0.0.0"; port = 443; ssl = true; } # for federation { addr = "0.0.0.0"; port = 8448; ssl = true; } ]; enableACME = true; forceSSL = true; # It's also possible to do a redirect here or something else, this vhost is not # needed for Matrix. It's recommended though to *not put* element # here, see also the section about Element. locations."/".extraConfig = '' return 404; ''; # Forward all Matrix API calls to the synapse Matrix homeserver. A trailing slash # *must not* be used here. locations."/_matrix".proxyPass = "http://[::1]:8008"; # Forward requests for e.g. SSO and password-resets. #locations."/_synapse/client".proxyPass = "http://[::1]:8008"; }; "element.${domain}" = { forceSSL = true; enableACME = true; extraConfig = '' proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 600; ''; # locations."/_matrix".proxyPass = "http://127.0.0.1:${toString config.services.dendrite.httpPort}"; # # for remote admin access # locations."/_synapse".proxyPass = "http://127.0.0.1:${toString config.services.dendrite.httpPort}"; locations."/".root = element-web; }; }; }; # $ nix-shell -p dendrite --run 'generate-keys --private-key /tmp/key' #sops.secrets.matrix-server-key = { }; #services.dendrite = { # enable = true; # httpPort = 8448; # settings = { # global = { # server_name = "terranix.org"; # # `private_key` has the type `path` # # prefix a `/` to make `path` happy # private_key = "/$CREDENTIALS_DIRECTORY/matrix-server-key"; # trusted_third_party_id_servers = [ # "matrix.org" # "vector.im" # "xaos.space" # "lassul.us" # "thalheim.io" # "nixos.org" # ]; # metrics.enabled = false; # }; # logging = [ # { # type = "std"; # level = "warn"; # } # ]; # client_api = { # registration_disabled = true; # rate_limiting.enabled = false; # # set only for the first admin account, than remove. # #registration_shared_secret = ""; # disable once first admin account is created # }; # media_api = { # dynamic_thumbnails = true; # }; # mscs = { # mscs = [ "msc2836" "msc2946" ]; # }; # sync_api = { # real_ip_header = "X-Real-IP"; # }; # federation_api = { # key_perspectives = [ # { # server_name = "matrix.org"; # keys = [ # { # key_id = "ed25519:auto"; # public_key = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"; # } # { # key_id = "ed25519:a_RXGa"; # public_key = "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ"; # } # ]; # } # ]; # prefer_direct_fetch = false; # }; # }; #}; #systemd.services.dendrite.serviceConfig.LoadCredential = [ # "matrix-server-key:${config.sops.secrets.matrix-server-key.path}" #]; #services.nginx.virtualHosts.${server_name} = { # locations."= /.well-known/matrix/server".alias = # pkgs.writeText "matrix-server" (builtins.toJSON { "m.server" = "${nginx-vhost}:443"; }); # locations."= /.well-known/matrix/client".alias = # pkgs.writeText "matrix-client" (builtins.toJSON { "m.homeserver".base_url = "https://${nginx-vhost}"; }); #}; }