1{ config, lib, pkgs, ... }:
2let
3 cfg = config.services.dendrite;
4 settingsFormat = pkgs.formats.yaml { };
5 configurationYaml = settingsFormat.generate "dendrite.yaml" cfg.settings;
6 workingDir = "/var/lib/dendrite";
7in
8{
9 options.services.dendrite = {
10 enable = lib.mkEnableOption "matrix.org dendrite";
11 httpPort = lib.mkOption {
12 type = lib.types.nullOr lib.types.port;
13 default = 8008;
14 description = ''
15 The port to listen for HTTP requests on.
16 '';
17 };
18 httpsPort = lib.mkOption {
19 type = lib.types.nullOr lib.types.port;
20 default = null;
21 description = ''
22 The port to listen for HTTPS requests on.
23 '';
24 };
25 tlsCert = lib.mkOption {
26 type = lib.types.nullOr lib.types.path;
27 example = "/var/lib/dendrite/server.cert";
28 default = null;
29 description = ''
30 The path to the TLS certificate.
31
32 <programlisting>
33 nix-shell -p dendrite --command "generate-keys --tls-cert server.crt --tls-key server.key"
34 </programlisting>
35 '';
36 };
37 tlsKey = lib.mkOption {
38 type = lib.types.nullOr lib.types.path;
39 example = "/var/lib/dendrite/server.key";
40 default = null;
41 description = ''
42 The path to the TLS key.
43
44 <programlisting>
45 nix-shell -p dendrite --command "generate-keys --tls-cert server.crt --tls-key server.key"
46 </programlisting>
47 '';
48 };
49 environmentFile = lib.mkOption {
50 type = lib.types.nullOr lib.types.path;
51 example = "/var/lib/dendrite/registration_secret";
52 default = null;
53 description = ''
54 Environment file as defined in <citerefentry>
55 <refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum>
56 </citerefentry>.
57 Secrets may be passed to the service without adding them to the world-readable
58 Nix store, by specifying placeholder variables as the option value in Nix and
59 setting these variables accordingly in the environment file. Currently only used
60 for the registration secret to allow secure registration when
61 client_api.registration_disabled is true.
62
63 <programlisting>
64 # snippet of dendrite-related config
65 services.dendrite.settings.client_api.registration_shared_secret = "$REGISTRATION_SHARED_SECRET";
66 </programlisting>
67
68 <programlisting>
69 # content of the environment file
70 REGISTRATION_SHARED_SECRET=verysecretpassword
71 </programlisting>
72
73 Note that this file needs to be available on the host on which
74 <literal>dendrite</literal> is running.
75 '';
76 };
77 settings = lib.mkOption {
78 type = lib.types.submodule {
79 freeformType = settingsFormat.type;
80 options.global = {
81 server_name = lib.mkOption {
82 type = lib.types.str;
83 example = "example.com";
84 description = ''
85 The domain name of the server, with optional explicit port.
86 This is used by remote servers to connect to this server.
87 This is also the last part of your UserID.
88 '';
89 };
90 private_key = lib.mkOption {
91 type = lib.types.path;
92 example = "${workingDir}/matrix_key.pem";
93 description = ''
94 The path to the signing private key file, used to sign
95 requests and events.
96
97 <programlisting>
98 nix-shell -p dendrite --command "generate-keys --private-key matrix_key.pem"
99 </programlisting>
100 '';
101 };
102 trusted_third_party_id_servers = lib.mkOption {
103 type = lib.types.listOf lib.types.str;
104 example = [ "matrix.org" ];
105 default = [ "matrix.org" "vector.im" ];
106 description = ''
107 Lists of domains that the server will trust as identity
108 servers to verify third party identifiers such as phone
109 numbers and email addresses
110 '';
111 };
112 };
113 options.client_api = {
114 registration_disabled = lib.mkOption {
115 type = lib.types.bool;
116 default = true;
117 description = ''
118 Whether to disable user registration to the server
119 without the shared secret.
120 '';
121 };
122 };
123 };
124 default = { };
125 description = ''
126 Configuration for dendrite, see:
127 <link xlink:href="https://github.com/matrix-org/dendrite/blob/master/dendrite-config.yaml"/>
128 for available options with which to populate settings.
129 '';
130 };
131 };
132
133 config = lib.mkIf cfg.enable {
134 assertions = [{
135 assertion = cfg.httpsPort != null -> (cfg.tlsCert != null && cfg.tlsKey != null);
136 message = ''
137 If Dendrite is configured to use https, tlsCert and tlsKey must be provided.
138
139 nix-shell -p dendrite --command "generate-keys --tls-cert server.crt --tls-key server.key"
140 '';
141 }];
142
143 systemd.services.dendrite = {
144 description = "Dendrite Matrix homeserver";
145 after = [
146 "network.target"
147 ];
148 wantedBy = [ "multi-user.target" ];
149 serviceConfig = {
150 Type = "simple";
151 DynamicUser = true;
152 StateDirectory = "dendrite";
153 WorkingDirectory = workingDir;
154 RuntimeDirectory = "dendrite";
155 RuntimeDirectoryMode = "0700";
156 EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
157 ExecStartPre =
158 if (cfg.environmentFile != null) then ''
159 ${pkgs.envsubst}/bin/envsubst \
160 -i ${configurationYaml} \
161 -o /run/dendrite/dendrite.yaml
162 '' else ''
163 ${pkgs.coreutils}/bin/cp ${configurationYaml} /run/dendrite/dendrite.yaml
164 '';
165 ExecStart = lib.strings.concatStringsSep " " ([
166 "${pkgs.dendrite}/bin/dendrite-monolith-server"
167 "--config /run/dendrite/dendrite.yaml"
168 ] ++ lib.optionals (cfg.httpPort != null) [
169 "--http-bind-address :${builtins.toString cfg.httpPort}"
170 ] ++ lib.optionals (cfg.httpsPort != null) [
171 "--https-bind-address :${builtins.toString cfg.httpsPort}"
172 "--tls-cert ${cfg.tlsCert}"
173 "--tls-key ${cfg.tlsKey}"
174 ]);
175 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
176 Restart = "on-failure";
177 };
178 };
179 };
180 meta.maintainers = lib.teams.matrix.members;
181}