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