From e3e563330798723a8991f0d7011e5c1b74a36e5d Mon Sep 17 00:00:00 2001 From: Corbin Date: Tue, 22 Mar 2016 23:40:35 -0700 Subject: services: Add Tahoe-LAFS service. Including systemd configuration and much of the standard storage node and introducer configuration. --- .../modules/services/network-filesystems/tahoe.nix | 286 +++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 nixos/modules/services/network-filesystems/tahoe.nix (limited to 'nixos/modules/services') diff --git a/nixos/modules/services/network-filesystems/tahoe.nix b/nixos/modules/services/network-filesystems/tahoe.nix new file mode 100644 index 000000000000..ab441339a560 --- /dev/null +++ b/nixos/modules/services/network-filesystems/tahoe.nix @@ -0,0 +1,286 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.tahoe; +in + { + options.services.tahoe = { + introducers = mkOption { + default = {}; + type = types.loaOf types.optionSet; + description = '' + The Tahoe introducers. + ''; + options = { + nickname = mkOption { + type = types.str; + description = '' + The nickname of this Tahoe introducer. + ''; + }; + tub.port = mkOption { + default = 3458; + type = types.int; + description = '' + The port on which the introducer will listen. + ''; + }; + package = mkOption { + default = pkgs.tahoelafs; + defaultText = "pkgs.tahoelafs"; + type = types.package; + example = literalExample "pkgs.tahoelafs"; + description = '' + The package to use for the Tahoe LAFS daemon. + ''; + }; + }; + }; + nodes = mkOption { + default = {}; + type = types.loaOf types.optionSet; + description = '' + The Tahoe nodes. + ''; + options = { + nickname = mkOption { + type = types.str; + description = '' + The nickname of this Tahoe node. + ''; + }; + tub.port = mkOption { + default = 3457; + type = types.int; + description = '' + The port on which the tub will listen. + + This is the correct setting to tweak if you want Tahoe's storage + system to listen on a different port. + ''; + }; + web.port = mkOption { + default = 3456; + type = types.int; + description = '' + The port on which the Web server will listen. + + This is the correct setting to tweak if you want Tahoe's WUI to + listen on a different port. + ''; + }; + client.introducer = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The furl for a Tahoe introducer node. + + Like all furls, keep this safe and don't share it. + ''; + }; + client.helper = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The furl for a Tahoe helper node. + + Like all furls, keep this safe and don't share it. + ''; + }; + client.shares.needed = mkOption { + default = 3; + type = types.int; + description = '' + The number of shares required to reconstitute a file. + ''; + }; + client.shares.happy = mkOption { + default = 7; + type = types.int; + description = '' + The number of distinct storage nodes required to store + a file. + ''; + }; + client.shares.total = mkOption { + default = 10; + type = types.int; + description = '' + The number of shares required to store a file. + ''; + }; + storage.enable = mkEnableOption "storage service"; + storage.reservedSpace = mkOption { + default = "1G"; + type = types.str; + description = '' + The amount of filesystem space to not use for storage. + ''; + }; + helper.enable = mkEnableOption "helper service"; + package = mkOption { + default = pkgs.tahoelafs; + defaultText = "pkgs.tahoelafs"; + type = types.package; + example = literalExample "pkgs.tahoelafs"; + description = '' + The package to use for the Tahoe LAFS daemon. + ''; + }; + }; + }; + }; + config = mkMerge [ + (mkIf (cfg.introducers != {}) { + environment = { + etc = flip mapAttrs' cfg.introducers (node: settings: + nameValuePair "tahoe-lafs/introducer-${node}.cfg" { + mode = "0444"; + text = '' + # This configuration is generated by Nix. Edit at your own + # peril; here be dragons. + + [node] + nickname = ${settings.nickname} + tub.port = ${toString settings.tub.port} + ''; + }); + # Actually require Tahoe, so that we will have it installed. + systemPackages = flip mapAttrsToList cfg.introducers (node: settings: + settings.package + ); + }; + # Open up the firewall. + # networking.firewall.allowedTCPPorts = flip mapAttrsToList cfg.introducers + # (node: settings: settings.tub.port); + systemd.services = flip mapAttrs' cfg.introducers (node: settings: + let + pidfile = "/run/tahoe.introducer-${node}.pid"; + # This is a directory, but it has no trailing slash. Tahoe commands + # get antsy when there's a trailing slash. + nodedir = "/var/db/tahoe-lafs/introducer-${node}"; + in nameValuePair "tahoe.introducer-${node}" { + description = "Tahoe LAFS node ${node}"; + wantedBy = [ "multi-user.target" ]; + path = [ settings.package ]; + restartTriggers = [ + config.environment.etc."tahoe-lafs/introducer-${node}.cfg".source ]; + serviceConfig = { + Type = "simple"; + PIDFile = pidfile; + }; + preStart = '' + if [ \! -d ${nodedir} ]; then + mkdir -p /var/db/tahoe-lafs + tahoe create-introducer ${nodedir} + fi + + # Tahoe has created a predefined tahoe.cfg which we must now + # scribble over. + # XXX I thought that a symlink would work here, but it doesn't, so + # we must do this on every prestart. Fixes welcome. + # rm ${nodedir}/tahoe.cfg + # ln -s /etc/tahoe-lafs/introducer-${node}.cfg ${nodedir}/tahoe.cfg + cp /etc/tahoe-lafs/introducer-${node}.cfg ${nodedir}/tahoe.cfg + ''; + # Believe it or not, Tahoe is very brittle about the order of + # arguments to $(tahoe start). The node directory must come first, + # and arguments which alter Twisted's behavior come afterwards. + script = '' + tahoe start ${nodedir} -n -l- --pidfile=${pidfile} + ''; + }); + users.extraUsers = flip mapAttrs' cfg.introducers (node: _: + nameValuePair "tahoe.introducer-${node}" { + description = "Tahoe node user for introducer ${node}"; + isSystemUser = true; + }); + }) + (mkIf (cfg.nodes != {}) { + environment = { + etc = flip mapAttrs' cfg.nodes (node: settings: + nameValuePair "tahoe-lafs/${node}.cfg" { + mode = "0444"; + text = '' + # This configuration is generated by Nix. Edit at your own + # peril; here be dragons. + + [node] + nickname = ${settings.nickname} + tub.port = ${toString settings.tub.port} + # This is a Twisted endpoint. Twisted Web doesn't work on + # non-TCP. ~ C. + web.port = tcp:${toString settings.web.port} + + [client] + ${optionalString (settings.client.introducer != null) + "introducer.furl = ${settings.client.introducer}"} + ${optionalString (settings.client.helper != null) + "helper.furl = ${settings.client.helper}"} + + shares.needed = ${toString settings.client.shares.needed} + shares.happy = ${toString settings.client.shares.happy} + shares.total = ${toString settings.client.shares.total} + + [storage] + enabled = ${if settings.storage.enable then "true" else "false"} + reserved_space = ${settings.storage.reservedSpace} + + [helper] + enabled = ${if settings.helper.enable then "true" else "false"} + ''; + }); + # Actually require Tahoe, so that we will have it installed. + systemPackages = flip mapAttrsToList cfg.nodes (node: settings: + settings.package + ); + }; + # Open up the firewall. + # networking.firewall.allowedTCPPorts = flip mapAttrsToList cfg.nodes + # (node: settings: settings.tub.port); + systemd.services = flip mapAttrs' cfg.nodes (node: settings: + let + pidfile = "/run/tahoe.${node}.pid"; + # This is a directory, but it has no trailing slash. Tahoe commands + # get antsy when there's a trailing slash. + nodedir = "/var/db/tahoe-lafs/${node}"; + in nameValuePair "tahoe.${node}" { + description = "Tahoe LAFS node ${node}"; + wantedBy = [ "multi-user.target" ]; + path = [ settings.package ]; + restartTriggers = [ + config.environment.etc."tahoe-lafs/${node}.cfg".source ]; + serviceConfig = { + Type = "simple"; + PIDFile = pidfile; + }; + preStart = '' + if [ \! -d ${nodedir} ]; then + mkdir -p /var/db/tahoe-lafs + tahoe create-node ${nodedir} + fi + + # Tahoe has created a predefined tahoe.cfg which we must now + # scribble over. + # XXX I thought that a symlink would work here, but it doesn't, so + # we must do this on every prestart. Fixes welcome. + # rm ${nodedir}/tahoe.cfg + # ln -s /etc/tahoe-lafs/${node}.cfg ${nodedir}/tahoe.cfg + cp /etc/tahoe-lafs/${node}.cfg ${nodedir}/tahoe.cfg + ''; + # Believe it or not, Tahoe is very brittle about the order of + # arguments to $(tahoe start). The node directory must come first, + # and arguments which alter Twisted's behavior come afterwards. + script = '' + tahoe start ${nodedir} -n -l- --pidfile=${pidfile} + ''; + }); + users.extraUsers = flip mapAttrs' cfg.nodes (node: _: + nameValuePair "tahoe.${node}" { + description = "Tahoe node user for node ${node}"; + isSystemUser = true; + }); + }) + ]; + } -- cgit 1.4.1