1# Matrix {#module-services-matrix}
2
3[Matrix](https://matrix.org/) is an open standard for
4interoperable, decentralised, real-time communication over IP. It can be used
5to power Instant Messaging, VoIP/WebRTC signalling, Internet of Things
6communication - or anywhere you need a standard HTTP API for publishing and
7subscribing to data whilst tracking the conversation history.
8
9This chapter will show you how to set up your own, self-hosted Matrix
10homeserver using the Synapse reference homeserver, and how to serve your own
11copy of the Element web client. See the
12[Try Matrix Now!](https://matrix.org/docs/projects/try-matrix-now.html)
13overview page for links to Element Apps for Android and iOS,
14desktop clients, as well as bridges to other networks and other projects
15around Matrix.
16
17## Synapse Homeserver {#module-services-matrix-synapse}
18
19[Synapse](https://github.com/matrix-org/synapse) is
20the reference homeserver implementation of Matrix from the core development
21team at matrix.org. The following configuration example will set up a
22synapse server for the `example.org` domain, served from
23the host `myhostname.example.org`. For more information,
24please refer to the
25[installation instructions of Synapse](https://matrix-org.github.io/synapse/latest/setup/installation.html) .
26```
27{ pkgs, lib, config, ... }:
28let
29 fqdn = "${config.networking.hostName}.${config.networking.domain}";
30 clientConfig."m.homeserver".base_url = "https://${fqdn}";
31 serverConfig."m.server" = "${fqdn}:443";
32 mkWellKnown = data: ''
33 add_header Content-Type application/json;
34 add_header Access-Control-Allow-Origin *;
35 return 200 '${builtins.toJSON data}';
36 '';
37in {
38 networking.hostName = "myhostname";
39 networking.domain = "example.org";
40 networking.firewall.allowedTCPPorts = [ 80 443 ];
41
42 services.postgresql.enable = true;
43 services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" ''
44 CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
45 CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
46 TEMPLATE template0
47 LC_COLLATE = "C"
48 LC_CTYPE = "C";
49 '';
50
51 services.nginx = {
52 enable = true;
53 recommendedTlsSettings = true;
54 recommendedOptimisation = true;
55 recommendedGzipSettings = true;
56 recommendedProxySettings = true;
57 virtualHosts = {
58 # If the A and AAAA DNS records on example.org do not point on the same host as the
59 # records for myhostname.example.org, you can easily move the /.well-known
60 # virtualHost section of the code to the host that is serving example.org, while
61 # the rest stays on myhostname.example.org with no other changes required.
62 # This pattern also allows to seamlessly move the homeserver from
63 # myhostname.example.org to myotherhost.example.org by only changing the
64 # /.well-known redirection target.
65 "${config.networking.domain}" = {
66 enableACME = true;
67 forceSSL = true;
68 # This section is not needed if the server_name of matrix-synapse is equal to
69 # the domain (i.e. example.org from @foo:example.org) and the federation port
70 # is 8448.
71 # Further reference can be found in the docs about delegation under
72 # https://matrix-org.github.io/synapse/latest/delegate.html
73 locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
74 # This is usually needed for homeserver discovery (from e.g. other Matrix clients).
75 # Further reference can be found in the upstream docs at
76 # https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient
77 locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;
78 };
79 "${fqdn}" = {
80 enableACME = true;
81 forceSSL = true;
82 # It's also possible to do a redirect here or something else, this vhost is not
83 # needed for Matrix. It's recommended though to *not put* element
84 # here, see also the section about Element.
85 locations."/".extraConfig = ''
86 return 404;
87 '';
88 # Forward all Matrix API calls to the synapse Matrix homeserver. A trailing slash
89 # *must not* be used here.
90 locations."/_matrix".proxyPass = "http://[::1]:8008";
91 # Forward requests for e.g. SSO and password-resets.
92 locations."/_synapse/client".proxyPass = "http://[::1]:8008";
93 };
94 };
95 };
96
97 services.matrix-synapse = {
98 enable = true;
99 settings.server_name = config.networking.domain;
100 settings.listeners = [
101 { port = 8008;
102 bind_addresses = [ "::1" ];
103 type = "http";
104 tls = false;
105 x_forwarded = true;
106 resources = [ {
107 names = [ "client" "federation" ];
108 compress = true;
109 } ];
110 }
111 ];
112 };
113}
114```
115
116## Registering Matrix users {#module-services-matrix-register-users}
117
118If you want to run a server with public registration by anybody, you can
119then enable `services.matrix-synapse.settings.enable_registration = true;`.
120Otherwise, or you can generate a registration secret with
121{command}`pwgen -s 64 1` and set it with
122[](#opt-services.matrix-synapse.settings.registration_shared_secret).
123To create a new user or admin, run the following after you have set the secret
124and have rebuilt NixOS:
125```ShellSession
126$ nix-shell -p matrix-synapse
127$ register_new_matrix_user -k your-registration-shared-secret http://localhost:8008
128New user localpart: your-username
129Password:
130Confirm password:
131Make admin [no]:
132Success!
133```
134In the example, this would create a user with the Matrix Identifier
135`@your-username:example.org`.
136
137::: {.warning}
138When using [](#opt-services.matrix-synapse.settings.registration_shared_secret), the secret
139will end up in the world-readable store. Instead it's recommended to deploy the secret
140in an additional file like this:
141
142 - Create a file with the following contents:
143
144 ```
145 registration_shared_secret: your-very-secret-secret
146 ```
147 - Deploy the file with a secret-manager such as
148 [{option}`deployment.keys`](https://nixops.readthedocs.io/en/latest/overview.html#managing-keys)
149 from {manpage}`nixops(1)` or [sops-nix](https://github.com/Mic92/sops-nix/) to
150 e.g. {file}`/run/secrets/matrix-shared-secret` and ensure that it's readable
151 by `matrix-synapse`.
152 - Include the file like this in your configuration:
153
154 ```
155 {
156 services.matrix-synapse.extraConfigFiles = [
157 "/run/secrets/matrix-shared-secret"
158 ];
159 }
160 ```
161:::
162
163::: {.note}
164It's also possible to user alternative authentication mechanism such as
165[LDAP (via `matrix-synapse-ldap3`)](https://github.com/matrix-org/matrix-synapse-ldap3)
166or [OpenID](https://matrix-org.github.io/synapse/latest/openid.html).
167:::
168
169## Element (formerly known as Riot) Web Client {#module-services-matrix-element-web}
170
171[Element Web](https://github.com/vector-im/riot-web/) is
172the reference web client for Matrix and developed by the core team at
173matrix.org. Element was formerly known as Riot.im, see the
174[Element introductory blog post](https://element.io/blog/welcome-to-element/)
175for more information. The following snippet can be optionally added to the code before
176to complete the synapse installation with a web client served at
177`https://element.myhostname.example.org` and
178`https://element.example.org`. Alternatively, you can use the hosted
179copy at <https://app.element.io/>,
180or use other web clients or native client applications. Due to the
181`/.well-known` urls set up done above, many clients should
182fill in the required connection details automatically when you enter your
183Matrix Identifier. See
184[Try Matrix Now!](https://matrix.org/docs/projects/try-matrix-now.html)
185for a list of existing clients and their supported featureset.
186```
187{
188 services.nginx.virtualHosts."element.${fqdn}" = {
189 enableACME = true;
190 forceSSL = true;
191 serverAliases = [
192 "element.${config.networking.domain}"
193 ];
194
195 root = pkgs.element-web.override {
196 conf = {
197 default_server_config = clientConfig; # see `clientConfig` from the snippet above.
198 };
199 };
200 };
201}
202```
203
204::: {.note}
205The Element developers do not recommend running Element and your Matrix
206homeserver on the same fully-qualified domain name for security reasons. In
207the example, this means that you should not reuse the
208`myhostname.example.org` virtualHost to also serve Element,
209but instead serve it on a different subdomain, like
210`element.example.org` in the example. See the
211[Element Important Security Notes](https://github.com/vector-im/element-web/tree/v1.10.0#important-security-notes)
212for more information on this subject.
213:::