grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / network-filesystems / tahoe.nix
blobe3296e6f66d540498b6f65bd71da66cf6e0849b9
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.tahoe;
4 in
5   {
6     options.services.tahoe = {
7       introducers = lib.mkOption {
8         default = {};
9         type = with lib.types; attrsOf (submodule {
10           options = {
11             nickname = lib.mkOption {
12               type = lib.types.str;
13               description = ''
14                 The nickname of this Tahoe introducer.
15               '';
16             };
17             tub.port = lib.mkOption {
18               default = 3458;
19               type = lib.types.port;
20               description = ''
21                 The port on which the introducer will listen.
22               '';
23             };
24             tub.location = lib.mkOption {
25               default = null;
26               type = lib.types.nullOr lib.types.str;
27               description = ''
28                 The external location that the introducer should listen on.
30                 If specified, the port should be included.
31               '';
32             };
33             package = lib.mkPackageOption pkgs "tahoelafs" { };
34           };
35         });
36         description = ''
37           The Tahoe introducers.
38         '';
39       };
40       nodes = lib.mkOption {
41         default = {};
42         type = with lib.types; attrsOf (submodule {
43           options = {
44             nickname = lib.mkOption {
45               type = lib.types.str;
46               description = ''
47                 The nickname of this Tahoe node.
48               '';
49             };
50             tub.port = lib.mkOption {
51               default = 3457;
52               type = lib.types.port;
53               description = ''
54                 The port on which the tub will listen.
56                 This is the correct setting to tweak if you want Tahoe's storage
57                 system to listen on a different port.
58               '';
59             };
60             tub.location = lib.mkOption {
61               default = null;
62               type = lib.types.nullOr lib.types.str;
63               description = ''
64                 The external location that the node should listen on.
66                 This is the setting to tweak if there are multiple interfaces
67                 and you want to alter which interface Tahoe is advertising.
69                 If specified, the port should be included.
70               '';
71             };
72             web.port = lib.mkOption {
73               default = 3456;
74               type = lib.types.port;
75               description = ''
76                 The port on which the Web server will listen.
78                 This is the correct setting to tweak if you want Tahoe's WUI to
79                 listen on a different port.
80               '';
81             };
82             client.introducer = lib.mkOption {
83               default = null;
84               type = lib.types.nullOr lib.types.str;
85               description = ''
86                 The furl for a Tahoe introducer node.
88                 Like all furls, keep this safe and don't share it.
89               '';
90             };
91             client.helper = lib.mkOption {
92               default = null;
93               type = lib.types.nullOr lib.types.str;
94               description = ''
95                 The furl for a Tahoe helper node.
97                 Like all furls, keep this safe and don't share it.
98               '';
99             };
100             client.shares.needed = lib.mkOption {
101               default = 3;
102               type = lib.types.int;
103               description = ''
104                 The number of shares required to reconstitute a file.
105               '';
106             };
107             client.shares.happy = lib.mkOption {
108               default = 7;
109               type = lib.types.int;
110               description = ''
111                 The number of distinct storage nodes required to store
112                 a file.
113               '';
114             };
115             client.shares.total = lib.mkOption {
116               default = 10;
117               type = lib.types.int;
118               description = ''
119                 The number of shares required to store a file.
120               '';
121             };
122             storage.enable = lib.mkEnableOption "storage service";
123             storage.reservedSpace = lib.mkOption {
124               default = "1G";
125               type = lib.types.str;
126               description = ''
127                 The amount of filesystem space to not use for storage.
128               '';
129             };
130             helper.enable = lib.mkEnableOption "helper service";
131             sftpd.enable = lib.mkEnableOption "SFTP service";
132             sftpd.port = lib.mkOption {
133               default = null;
134               type = lib.types.nullOr lib.types.int;
135               description = ''
136                 The port on which the SFTP server will listen.
138                 This is the correct setting to tweak if you want Tahoe's SFTP
139                 daemon to listen on a different port.
140               '';
141             };
142             sftpd.hostPublicKeyFile = lib.mkOption {
143               default = null;
144               type = lib.types.nullOr lib.types.path;
145               description = ''
146                 Path to the SSH host public key.
147               '';
148             };
149             sftpd.hostPrivateKeyFile = lib.mkOption {
150               default = null;
151               type = lib.types.nullOr lib.types.path;
152               description = ''
153                 Path to the SSH host private key.
154               '';
155             };
156             sftpd.accounts.file = lib.mkOption {
157               default = null;
158               type = lib.types.nullOr lib.types.path;
159               description = ''
160                 Path to the accounts file.
161               '';
162             };
163             sftpd.accounts.url = lib.mkOption {
164               default = null;
165               type = lib.types.nullOr lib.types.str;
166               description = ''
167                 URL of the accounts server.
168               '';
169             };
170             package = lib.mkPackageOption pkgs "tahoelafs" { };
171           };
172         });
173         description = ''
174           The Tahoe nodes.
175         '';
176       };
177     };
178     config = lib.mkMerge [
179       (lib.mkIf (cfg.introducers != {}) {
180         environment = {
181           etc = lib.flip lib.mapAttrs' cfg.introducers (node: settings:
182             lib.nameValuePair "tahoe-lafs/introducer-${node}.cfg" {
183               mode = "0444";
184               text = ''
185                 # This configuration is generated by Nix. Edit at your own
186                 # peril; here be dragons.
188                 [node]
189                 nickname = ${settings.nickname}
190                 tub.port = ${toString settings.tub.port}
191                 ${lib.optionalString (settings.tub.location != null)
192                   "tub.location = ${settings.tub.location}"}
193               '';
194             });
195           # Actually require Tahoe, so that we will have it installed.
196           systemPackages = lib.flip lib.mapAttrsToList cfg.introducers (node: settings:
197             settings.package
198           );
199         };
200         # Open up the firewall.
201         # networking.firewall.allowedTCPPorts = lib.flip lib.mapAttrsToList cfg.introducers
202         #   (node: settings: settings.tub.port);
203         systemd.services = lib.flip lib.mapAttrs' cfg.introducers (node: settings:
204           let
205             pidfile = "/run/tahoe.introducer-${node}.pid";
206             # This is a directory, but it has no trailing slash. Tahoe commands
207             # get antsy when there's a trailing slash.
208             nodedir = "/var/db/tahoe-lafs/introducer-${node}";
209           in lib.nameValuePair "tahoe.introducer-${node}" {
210             description = "Tahoe LAFS node ${node}";
211             wantedBy = [ "multi-user.target" ];
212             path = [ settings.package ];
213             restartTriggers = [
214               config.environment.etc."tahoe-lafs/introducer-${node}.cfg".source ];
215             serviceConfig = {
216               Type = "simple";
217               PIDFile = pidfile;
218               # Believe it or not, Tahoe is very brittle about the order of
219               # arguments to $(tahoe run). The node directory must come first,
220               # and arguments which alter Twisted's behavior come afterwards.
221               ExecStart = ''
222                 ${settings.package}/bin/tahoe run ${lib.escapeShellArg nodedir} --pidfile=${lib.escapeShellArg pidfile}
223               '';
224             };
225             preStart = ''
226               if [ ! -d ${lib.escapeShellArg nodedir} ]; then
227                 mkdir -p /var/db/tahoe-lafs
228                 # See https://github.com/NixOS/nixpkgs/issues/25273
229                 tahoe create-introducer \
230                   --hostname="${config.networking.hostName}" \
231                   ${lib.escapeShellArg nodedir}
232               fi
234               # Tahoe has created a predefined tahoe.cfg which we must now
235               # scribble over.
236               # XXX I thought that a symlink would work here, but it doesn't, so
237               # we must do this on every prestart. Fixes welcome.
238               # rm ${nodedir}/tahoe.cfg
239               # ln -s /etc/tahoe-lafs/introducer-${node}.cfg ${nodedir}/tahoe.cfg
240               cp /etc/tahoe-lafs/introducer-"${node}".cfg ${lib.escapeShellArg nodedir}/tahoe.cfg
241             '';
242           });
243         users.users = lib.flip lib.mapAttrs' cfg.introducers (node: _:
244           lib.nameValuePair "tahoe.introducer-${node}" {
245             description = "Tahoe node user for introducer ${node}";
246             isSystemUser = true;
247           });
248       })
249       (lib.mkIf (cfg.nodes != {}) {
250         environment = {
251           etc = lib.flip lib.mapAttrs' cfg.nodes (node: settings:
252             lib.nameValuePair "tahoe-lafs/${node}.cfg" {
253               mode = "0444";
254               text = ''
255                 # This configuration is generated by Nix. Edit at your own
256                 # peril; here be dragons.
258                 [node]
259                 nickname = ${settings.nickname}
260                 tub.port = ${toString settings.tub.port}
261                 ${lib.optionalString (settings.tub.location != null)
262                   "tub.location = ${settings.tub.location}"}
263                 # This is a Twisted endpoint. Twisted Web doesn't work on
264                 # non-TCP. ~ C.
265                 web.port = tcp:${toString settings.web.port}
267                 [client]
268                 ${lib.optionalString (settings.client.introducer != null)
269                   "introducer.furl = ${settings.client.introducer}"}
270                 ${lib.optionalString (settings.client.helper != null)
271                   "helper.furl = ${settings.client.helper}"}
273                 shares.needed = ${toString settings.client.shares.needed}
274                 shares.happy = ${toString settings.client.shares.happy}
275                 shares.total = ${toString settings.client.shares.total}
277                 [storage]
278                 enabled = ${lib.boolToString settings.storage.enable}
279                 reserved_space = ${settings.storage.reservedSpace}
281                 [helper]
282                 enabled = ${lib.boolToString settings.helper.enable}
284                 [sftpd]
285                 enabled = ${lib.boolToString settings.sftpd.enable}
286                 ${lib.optionalString (settings.sftpd.port != null)
287                   "port = ${toString settings.sftpd.port}"}
288                 ${lib.optionalString (settings.sftpd.hostPublicKeyFile != null)
289                   "host_pubkey_file = ${settings.sftpd.hostPublicKeyFile}"}
290                 ${lib.optionalString (settings.sftpd.hostPrivateKeyFile != null)
291                   "host_privkey_file = ${settings.sftpd.hostPrivateKeyFile}"}
292                 ${lib.optionalString (settings.sftpd.accounts.file != null)
293                   "accounts.file = ${settings.sftpd.accounts.file}"}
294                 ${lib.optionalString (settings.sftpd.accounts.url != null)
295                   "accounts.url = ${settings.sftpd.accounts.url}"}
296               '';
297             });
298           # Actually require Tahoe, so that we will have it installed.
299           systemPackages = lib.flip lib.mapAttrsToList cfg.nodes (node: settings:
300             settings.package
301           );
302         };
303         # Open up the firewall.
304         # networking.firewall.allowedTCPPorts = lib.flip lib.mapAttrsToList cfg.nodes
305         #   (node: settings: settings.tub.port);
306         systemd.services = lib.flip lib.mapAttrs' cfg.nodes (node: settings:
307           let
308             pidfile = "/run/tahoe.${node}.pid";
309             # This is a directory, but it has no trailing slash. Tahoe commands
310             # get antsy when there's a trailing slash.
311             nodedir = "/var/db/tahoe-lafs/${node}";
312           in lib.nameValuePair "tahoe.${node}" {
313             description = "Tahoe LAFS node ${node}";
314             wantedBy = [ "multi-user.target" ];
315             path = [ settings.package ];
316             restartTriggers = [
317               config.environment.etc."tahoe-lafs/${node}.cfg".source ];
318             serviceConfig = {
319               Type = "simple";
320               PIDFile = pidfile;
321               # Believe it or not, Tahoe is very brittle about the order of
322               # arguments to $(tahoe run). The node directory must come first,
323               # and arguments which alter Twisted's behavior come afterwards.
324               ExecStart = ''
325                 ${settings.package}/bin/tahoe run ${lib.escapeShellArg nodedir} --pidfile=${lib.escapeShellArg pidfile}
326               '';
327             };
328             preStart = ''
329               if [ ! -d ${lib.escapeShellArg nodedir} ]; then
330                 mkdir -p /var/db/tahoe-lafs
331                 tahoe create-node --hostname=localhost ${lib.escapeShellArg nodedir}
332               fi
334               # Tahoe has created a predefined tahoe.cfg which we must now
335               # scribble over.
336               # XXX I thought that a symlink would work here, but it doesn't, so
337               # we must do this on every prestart. Fixes welcome.
338               # rm ${nodedir}/tahoe.cfg
339               # ln -s /etc/tahoe-lafs/${lib.escapeShellArg node}.cfg ${nodedir}/tahoe.cfg
340               cp /etc/tahoe-lafs/${lib.escapeShellArg node}.cfg ${lib.escapeShellArg nodedir}/tahoe.cfg
341             '';
342           });
343         users.users = lib.flip lib.mapAttrs' cfg.nodes (node: _:
344           lib.nameValuePair "tahoe.${node}" {
345             description = "Tahoe node user for node ${node}";
346             isSystemUser = true;
347           });
348       })
349     ];
350   }