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