From 899a37d1909be0d4a11102bbdaeaebef793a5177 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Fri, 24 Jun 2022 12:00:14 +0200 Subject: [PATCH] nixos/matrix-synapse: update docs * Update attribute names in code examples (* -> settings.*). * Use `nix-shell -p` rather than `nix run` because the example won't work with the current default Nix. * Update config values for `element-web`. * Fix link to `element-web` security considerations. * Make the synapse expression even smaller and use callout-lists to explain the code. * Document how to correctly deploy the shared registration secret. [1] https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient --- nixos/modules/services/matrix/synapse.xml | 235 +++++++++++++--------- 1 file changed, 140 insertions(+), 95 deletions(-) diff --git a/nixos/modules/services/matrix/synapse.xml b/nixos/modules/services/matrix/synapse.xml index cf33957d58ec..65bc53d33ac3 100644 --- a/nixos/modules/services/matrix/synapse.xml +++ b/nixos/modules/services/matrix/synapse.xml @@ -33,21 +33,26 @@ installation instructions of Synapse . -{ pkgs, lib, ... }: +{ pkgs, lib, config, ... }: let - fqdn = - let - join = hostName: domain: hostName + lib.optionalString (domain != null) ".${domain}"; - in join config.networking.hostName config.networking.domain; -in { - networking = { - hostName = "myhostname"; - domain = "example.org"; + fqdn = "${config.networking.hostName}.${config.networking.domain}"; + clientConfig = { + "m.homeserver".base_url = "https://${fqdn}"; + "m.identity_server" = {}; }; - networking.firewall.allowedTCPPorts = [ 80 443 ]; + serverConfig."m.server" = "${config.services.matrix-synapse.settings.server_name}:443"; + mkWellKnown = data: '' + add_header Content-Type application/json; + add_header Access-Control-Allow-Origin *; + return 200 '${builtins.toJSON data}'; + ''; +in { + = "myhostname"; + = "example.org"; + = [ 80 443 ]; - services.postgresql.enable = true; - services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" '' + = true; + = pkgs.writeText "synapse-init.sql" '' CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse'; CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" TEMPLATE template0 @@ -57,78 +62,41 @@ in { services.nginx = { enable = true; - # only recommendedProxySettings and recommendedGzipSettings are strictly required, - # but the rest make sense as well recommendedTlsSettings = true; recommendedOptimisation = true; recommendedGzipSettings = true; recommendedProxySettings = true; - virtualHosts = { - # This host section can be placed on a different host than the rest, - # i.e. to delegate from the host being accessible as ${config.networking.domain} - # to another host actually running the Matrix homeserver. - "${config.networking.domain}" = { + "${config.networking.domain}" = { enableACME = true; forceSSL = true; - - locations."= /.well-known/matrix/server".extraConfig = - let - # use 443 instead of the default 8448 port to unite - # the client-server and server-server port for simplicity - server = { "m.server" = "${fqdn}:443"; }; - in '' - add_header Content-Type application/json; - return 200 '${builtins.toJSON server}'; - ''; - locations."= /.well-known/matrix/client".extraConfig = - let - client = { - "m.homeserver" = { "base_url" = "https://${fqdn}"; }; - "m.identity_server" = { "base_url" = "https://vector.im"; }; - }; - # ACAO required to allow element-web on any URL to request this json file - in '' - add_header Content-Type application/json; - add_header Access-Control-Allow-Origin *; - return 200 '${builtins.toJSON client}'; - ''; + locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; + locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; }; - - # Reverse proxy for Matrix client-server and server-server communication - ${fqdn} = { + "${fqdn}" = { enableACME = true; forceSSL = true; - - # Or do a redirect instead of the 404, or whatever is appropriate for you. - # But do not put a Matrix Web client here! See the Element web section below. - locations."/".extraConfig = '' + locations."/".extraConfig = '' return 404; ''; - - # forward all Matrix API calls to the synapse Matrix homeserver - locations."/_matrix" = { - proxyPass = "http://[::1]:8008"; # without a trailing / - }; + locations."/_matrix".proxyPass = "http://[::1]:8008"; + locations."/_synapse/client".proxyPass = "http://[::1]:8008"; }; }; }; + services.matrix-synapse = { enable = true; - server_name = config.networking.domain; - listeners = [ - { - port = 8008; + settings.server_name = config.networking.domain; + settings.listeners = [ + { port = 8008; bind_addresses = [ "::1" ]; type = "http"; tls = false; x_forwarded = true; resources = [ { - names = [ "client" ]; + names = [ "client" "federation" ]; compress = true; - } { - names = [ "federation" ]; - compress = false; } ]; } ]; @@ -136,20 +104,59 @@ in { } - - - 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. - - + + + + 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. + + + + + 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. + + + + + This is usually needed for homeserver discovery (from e.g. other Matrix clients). + Further reference can be found in the upstream docs + + + + + 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. + + + + + Forward all Matrix API calls to the synapse Matrix homeserver. A trailing slash + must not be used here. + + + + + Forward requests for e.g. SSO and password-resets. + + + + +
+ Registering Matrix users If you want to run a server with public registration by anybody, you can then enable services.matrix-synapse.settings.enable_registration = @@ -159,7 +166,7 @@ in { To create a new user or admin, run the following after you have set the secret and have rebuilt NixOS: -$ nix run nixpkgs.matrix-synapse +$ nix-shell -p matrix-synapse $ register_new_matrix_user -k your-registration-shared-secret http://localhost:8008 New user localpart: your-username Password: @@ -168,12 +175,51 @@ in { Success! In the example, this would create a user with the Matrix Identifier - @your-username:example.org. Note that the registration - secret ends up in the nix store and therefore is world-readable by any user - on your machine, so it makes sense to only temporarily activate the - registration_shared_secret - option until a better solution for NixOS is in place. + @your-username:example.org. + + + When using , the secret + will end up in the world-readable store. Instead it's recommended to deploy the secret + in an additional file like this: + + + + Create a file with the following contents: +registration_shared_secret: your-very-secret-secret + + + + + Deploy the file with a secret-manager such as + from nixops1 + or sops-nix to + e.g. /run/secrets/matrix-shared-secret and ensure that it's readable + by matrix-synapse. + + + + + Include the file like this in your configuration: + +{ + = [ + "/run/secrets/matrix-shared-secret" + ]; +} + + + + + + + + + It's also possible to user alternative authentication mechanism such as + LDAP (via matrix-synapse-ldap3) + or OpenID. + +
Element (formerly known as Riot) Web Client @@ -206,10 +252,7 @@ Success! root = pkgs.element-web.override { conf = { - default_server_config."m.homeserver" = { - "base_url" = "https://${fqdn}"; - "server_name" = "${fqdn}"; - }; + default_server_config = clientConfig; # see `clientConfig` from the snippet above. }; }; }; @@ -217,15 +260,17 @@ Success! - - Note that the Element developers do not recommend running Element and your Matrix - homeserver on the same fully-qualified domain name for security reasons. In - the example, this means that you should not reuse the - myhostname.example.org virtualHost to also serve Element, - but instead serve it on a different subdomain, like - element.example.org in the example. See the - Element - Important Security Notes for more information on this subject. - + + + The Element developers do not recommend running Element and your Matrix + homeserver on the same fully-qualified domain name for security reasons. In + the example, this means that you should not reuse the + myhostname.example.org virtualHost to also serve Element, + but instead serve it on a different subdomain, like + element.example.org in the example. See the + Element + Important Security Notes for more information on this subject. + +