1 { config, lib, pkgs, ... }:
3 cfg = config.services.tahoe;
6 options.services.tahoe = {
7 introducers = lib.mkOption {
9 type = with lib.types; attrsOf (submodule {
11 nickname = lib.mkOption {
14 The nickname of this Tahoe introducer.
17 tub.port = lib.mkOption {
19 type = lib.types.port;
21 The port on which the introducer will listen.
24 tub.location = lib.mkOption {
26 type = lib.types.nullOr lib.types.str;
28 The external location that the introducer should listen on.
30 If specified, the port should be included.
33 package = lib.mkPackageOption pkgs "tahoelafs" { };
37 The Tahoe introducers.
40 nodes = lib.mkOption {
42 type = with lib.types; attrsOf (submodule {
44 nickname = lib.mkOption {
47 The nickname of this Tahoe node.
50 tub.port = lib.mkOption {
52 type = lib.types.port;
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.
60 tub.location = lib.mkOption {
62 type = lib.types.nullOr lib.types.str;
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.
72 web.port = lib.mkOption {
74 type = lib.types.port;
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.
82 client.introducer = lib.mkOption {
84 type = lib.types.nullOr lib.types.str;
86 The furl for a Tahoe introducer node.
88 Like all furls, keep this safe and don't share it.
91 client.helper = lib.mkOption {
93 type = lib.types.nullOr lib.types.str;
95 The furl for a Tahoe helper node.
97 Like all furls, keep this safe and don't share it.
100 client.shares.needed = lib.mkOption {
102 type = lib.types.int;
104 The number of shares required to reconstitute a file.
107 client.shares.happy = lib.mkOption {
109 type = lib.types.int;
111 The number of distinct storage nodes required to store
115 client.shares.total = lib.mkOption {
117 type = lib.types.int;
119 The number of shares required to store a file.
122 storage.enable = lib.mkEnableOption "storage service";
123 storage.reservedSpace = lib.mkOption {
125 type = lib.types.str;
127 The amount of filesystem space to not use for storage.
130 helper.enable = lib.mkEnableOption "helper service";
131 sftpd.enable = lib.mkEnableOption "SFTP service";
132 sftpd.port = lib.mkOption {
134 type = lib.types.nullOr lib.types.int;
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.
142 sftpd.hostPublicKeyFile = lib.mkOption {
144 type = lib.types.nullOr lib.types.path;
146 Path to the SSH host public key.
149 sftpd.hostPrivateKeyFile = lib.mkOption {
151 type = lib.types.nullOr lib.types.path;
153 Path to the SSH host private key.
156 sftpd.accounts.file = lib.mkOption {
158 type = lib.types.nullOr lib.types.path;
160 Path to the accounts file.
163 sftpd.accounts.url = lib.mkOption {
165 type = lib.types.nullOr lib.types.str;
167 URL of the accounts server.
170 package = lib.mkPackageOption pkgs "tahoelafs" { };
178 config = lib.mkMerge [
179 (lib.mkIf (cfg.introducers != {}) {
181 etc = lib.flip lib.mapAttrs' cfg.introducers (node: settings:
182 lib.nameValuePair "tahoe-lafs/introducer-${node}.cfg" {
185 # This configuration is generated by Nix. Edit at your own
186 # peril; here be dragons.
189 nickname = ${settings.nickname}
190 tub.port = ${toString settings.tub.port}
191 ${lib.optionalString (settings.tub.location != null)
192 "tub.location = ${settings.tub.location}"}
195 # Actually require Tahoe, so that we will have it installed.
196 systemPackages = lib.flip lib.mapAttrsToList cfg.introducers (node: settings:
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:
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 ];
214 config.environment.etc."tahoe-lafs/introducer-${node}.cfg".source ];
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.
222 ${settings.package}/bin/tahoe run ${lib.escapeShellArg nodedir} --pidfile=${lib.escapeShellArg pidfile}
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}
234 # Tahoe has created a predefined tahoe.cfg which we must now
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
243 users.users = lib.flip lib.mapAttrs' cfg.introducers (node: _:
244 lib.nameValuePair "tahoe.introducer-${node}" {
245 description = "Tahoe node user for introducer ${node}";
249 (lib.mkIf (cfg.nodes != {}) {
251 etc = lib.flip lib.mapAttrs' cfg.nodes (node: settings:
252 lib.nameValuePair "tahoe-lafs/${node}.cfg" {
255 # This configuration is generated by Nix. Edit at your own
256 # peril; here be dragons.
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
265 web.port = tcp:${toString settings.web.port}
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}
278 enabled = ${lib.boolToString settings.storage.enable}
279 reserved_space = ${settings.storage.reservedSpace}
282 enabled = ${lib.boolToString settings.helper.enable}
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}"}
298 # Actually require Tahoe, so that we will have it installed.
299 systemPackages = lib.flip lib.mapAttrsToList cfg.nodes (node: settings:
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:
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 ];
317 config.environment.etc."tahoe-lafs/${node}.cfg".source ];
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.
325 ${settings.package}/bin/tahoe run ${lib.escapeShellArg nodedir} --pidfile=${lib.escapeShellArg pidfile}
329 if [ ! -d ${lib.escapeShellArg nodedir} ]; then
330 mkdir -p /var/db/tahoe-lafs
331 tahoe create-node --hostname=localhost ${lib.escapeShellArg nodedir}
334 # Tahoe has created a predefined tahoe.cfg which we must now
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
343 users.users = lib.flip lib.mapAttrs' cfg.nodes (node: _:
344 lib.nameValuePair "tahoe.${node}" {
345 description = "Tahoe node user for node ${node}";