Merge pull request #14145 from MostAwesomeDude/tahoe

services: Add Tahoe-LAFS service.

+287
+1
nixos/modules/module-list.nix
··· 283 283 ./services/network-filesystems/openafs-client/default.nix 284 284 ./services/network-filesystems/rsyncd.nix 285 285 ./services/network-filesystems/samba.nix 286 + ./services/network-filesystems/tahoe.nix 286 287 ./services/network-filesystems/diod.nix 287 288 ./services/network-filesystems/u9fs.nix 288 289 ./services/network-filesystems/yandex-disk.nix
+286
nixos/modules/services/network-filesystems/tahoe.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + let 5 + cfg = config.services.tahoe; 6 + in 7 + { 8 + options.services.tahoe = { 9 + introducers = mkOption { 10 + default = {}; 11 + type = types.loaOf types.optionSet; 12 + description = '' 13 + The Tahoe introducers. 14 + ''; 15 + options = { 16 + nickname = mkOption { 17 + type = types.str; 18 + description = '' 19 + The nickname of this Tahoe introducer. 20 + ''; 21 + }; 22 + tub.port = mkOption { 23 + default = 3458; 24 + type = types.int; 25 + description = '' 26 + The port on which the introducer will listen. 27 + ''; 28 + }; 29 + package = mkOption { 30 + default = pkgs.tahoelafs; 31 + defaultText = "pkgs.tahoelafs"; 32 + type = types.package; 33 + example = literalExample "pkgs.tahoelafs"; 34 + description = '' 35 + The package to use for the Tahoe LAFS daemon. 36 + ''; 37 + }; 38 + }; 39 + }; 40 + nodes = mkOption { 41 + default = {}; 42 + type = types.loaOf types.optionSet; 43 + description = '' 44 + The Tahoe nodes. 45 + ''; 46 + options = { 47 + nickname = mkOption { 48 + type = types.str; 49 + description = '' 50 + The nickname of this Tahoe node. 51 + ''; 52 + }; 53 + tub.port = mkOption { 54 + default = 3457; 55 + type = types.int; 56 + description = '' 57 + The port on which the tub will listen. 58 + 59 + This is the correct setting to tweak if you want Tahoe's storage 60 + system to listen on a different port. 61 + ''; 62 + }; 63 + web.port = mkOption { 64 + default = 3456; 65 + type = types.int; 66 + description = '' 67 + The port on which the Web server will listen. 68 + 69 + This is the correct setting to tweak if you want Tahoe's WUI to 70 + listen on a different port. 71 + ''; 72 + }; 73 + client.introducer = mkOption { 74 + default = null; 75 + type = types.nullOr types.str; 76 + description = '' 77 + The furl for a Tahoe introducer node. 78 + 79 + Like all furls, keep this safe and don't share it. 80 + ''; 81 + }; 82 + client.helper = mkOption { 83 + default = null; 84 + type = types.nullOr types.str; 85 + description = '' 86 + The furl for a Tahoe helper node. 87 + 88 + Like all furls, keep this safe and don't share it. 89 + ''; 90 + }; 91 + client.shares.needed = mkOption { 92 + default = 3; 93 + type = types.int; 94 + description = '' 95 + The number of shares required to reconstitute a file. 96 + ''; 97 + }; 98 + client.shares.happy = mkOption { 99 + default = 7; 100 + type = types.int; 101 + description = '' 102 + The number of distinct storage nodes required to store 103 + a file. 104 + ''; 105 + }; 106 + client.shares.total = mkOption { 107 + default = 10; 108 + type = types.int; 109 + description = '' 110 + The number of shares required to store a file. 111 + ''; 112 + }; 113 + storage.enable = mkEnableOption "storage service"; 114 + storage.reservedSpace = mkOption { 115 + default = "1G"; 116 + type = types.str; 117 + description = '' 118 + The amount of filesystem space to not use for storage. 119 + ''; 120 + }; 121 + helper.enable = mkEnableOption "helper service"; 122 + package = mkOption { 123 + default = pkgs.tahoelafs; 124 + defaultText = "pkgs.tahoelafs"; 125 + type = types.package; 126 + example = literalExample "pkgs.tahoelafs"; 127 + description = '' 128 + The package to use for the Tahoe LAFS daemon. 129 + ''; 130 + }; 131 + }; 132 + }; 133 + }; 134 + config = mkMerge [ 135 + (mkIf (cfg.introducers != {}) { 136 + environment = { 137 + etc = flip mapAttrs' cfg.introducers (node: settings: 138 + nameValuePair "tahoe-lafs/introducer-${node}.cfg" { 139 + mode = "0444"; 140 + text = '' 141 + # This configuration is generated by Nix. Edit at your own 142 + # peril; here be dragons. 143 + 144 + [node] 145 + nickname = ${settings.nickname} 146 + tub.port = ${toString settings.tub.port} 147 + ''; 148 + }); 149 + # Actually require Tahoe, so that we will have it installed. 150 + systemPackages = flip mapAttrsToList cfg.introducers (node: settings: 151 + settings.package 152 + ); 153 + }; 154 + # Open up the firewall. 155 + # networking.firewall.allowedTCPPorts = flip mapAttrsToList cfg.introducers 156 + # (node: settings: settings.tub.port); 157 + systemd.services = flip mapAttrs' cfg.introducers (node: settings: 158 + let 159 + pidfile = "/run/tahoe.introducer-${node}.pid"; 160 + # This is a directory, but it has no trailing slash. Tahoe commands 161 + # get antsy when there's a trailing slash. 162 + nodedir = "/var/db/tahoe-lafs/introducer-${node}"; 163 + in nameValuePair "tahoe.introducer-${node}" { 164 + description = "Tahoe LAFS node ${node}"; 165 + wantedBy = [ "multi-user.target" ]; 166 + path = [ settings.package ]; 167 + restartTriggers = [ 168 + config.environment.etc."tahoe-lafs/introducer-${node}.cfg".source ]; 169 + serviceConfig = { 170 + Type = "simple"; 171 + PIDFile = pidfile; 172 + }; 173 + preStart = '' 174 + if [ \! -d ${nodedir} ]; then 175 + mkdir -p /var/db/tahoe-lafs 176 + tahoe create-introducer ${nodedir} 177 + fi 178 + 179 + # Tahoe has created a predefined tahoe.cfg which we must now 180 + # scribble over. 181 + # XXX I thought that a symlink would work here, but it doesn't, so 182 + # we must do this on every prestart. Fixes welcome. 183 + # rm ${nodedir}/tahoe.cfg 184 + # ln -s /etc/tahoe-lafs/introducer-${node}.cfg ${nodedir}/tahoe.cfg 185 + cp /etc/tahoe-lafs/introducer-${node}.cfg ${nodedir}/tahoe.cfg 186 + ''; 187 + # Believe it or not, Tahoe is very brittle about the order of 188 + # arguments to $(tahoe start). The node directory must come first, 189 + # and arguments which alter Twisted's behavior come afterwards. 190 + script = '' 191 + tahoe start ${nodedir} -n -l- --pidfile=${pidfile} 192 + ''; 193 + }); 194 + users.extraUsers = flip mapAttrs' cfg.introducers (node: _: 195 + nameValuePair "tahoe.introducer-${node}" { 196 + description = "Tahoe node user for introducer ${node}"; 197 + isSystemUser = true; 198 + }); 199 + }) 200 + (mkIf (cfg.nodes != {}) { 201 + environment = { 202 + etc = flip mapAttrs' cfg.nodes (node: settings: 203 + nameValuePair "tahoe-lafs/${node}.cfg" { 204 + mode = "0444"; 205 + text = '' 206 + # This configuration is generated by Nix. Edit at your own 207 + # peril; here be dragons. 208 + 209 + [node] 210 + nickname = ${settings.nickname} 211 + tub.port = ${toString settings.tub.port} 212 + # This is a Twisted endpoint. Twisted Web doesn't work on 213 + # non-TCP. ~ C. 214 + web.port = tcp:${toString settings.web.port} 215 + 216 + [client] 217 + ${optionalString (settings.client.introducer != null) 218 + "introducer.furl = ${settings.client.introducer}"} 219 + ${optionalString (settings.client.helper != null) 220 + "helper.furl = ${settings.client.helper}"} 221 + 222 + shares.needed = ${toString settings.client.shares.needed} 223 + shares.happy = ${toString settings.client.shares.happy} 224 + shares.total = ${toString settings.client.shares.total} 225 + 226 + [storage] 227 + enabled = ${if settings.storage.enable then "true" else "false"} 228 + reserved_space = ${settings.storage.reservedSpace} 229 + 230 + [helper] 231 + enabled = ${if settings.helper.enable then "true" else "false"} 232 + ''; 233 + }); 234 + # Actually require Tahoe, so that we will have it installed. 235 + systemPackages = flip mapAttrsToList cfg.nodes (node: settings: 236 + settings.package 237 + ); 238 + }; 239 + # Open up the firewall. 240 + # networking.firewall.allowedTCPPorts = flip mapAttrsToList cfg.nodes 241 + # (node: settings: settings.tub.port); 242 + systemd.services = flip mapAttrs' cfg.nodes (node: settings: 243 + let 244 + pidfile = "/run/tahoe.${node}.pid"; 245 + # This is a directory, but it has no trailing slash. Tahoe commands 246 + # get antsy when there's a trailing slash. 247 + nodedir = "/var/db/tahoe-lafs/${node}"; 248 + in nameValuePair "tahoe.${node}" { 249 + description = "Tahoe LAFS node ${node}"; 250 + wantedBy = [ "multi-user.target" ]; 251 + path = [ settings.package ]; 252 + restartTriggers = [ 253 + config.environment.etc."tahoe-lafs/${node}.cfg".source ]; 254 + serviceConfig = { 255 + Type = "simple"; 256 + PIDFile = pidfile; 257 + }; 258 + preStart = '' 259 + if [ \! -d ${nodedir} ]; then 260 + mkdir -p /var/db/tahoe-lafs 261 + tahoe create-node ${nodedir} 262 + fi 263 + 264 + # Tahoe has created a predefined tahoe.cfg which we must now 265 + # scribble over. 266 + # XXX I thought that a symlink would work here, but it doesn't, so 267 + # we must do this on every prestart. Fixes welcome. 268 + # rm ${nodedir}/tahoe.cfg 269 + # ln -s /etc/tahoe-lafs/${node}.cfg ${nodedir}/tahoe.cfg 270 + cp /etc/tahoe-lafs/${node}.cfg ${nodedir}/tahoe.cfg 271 + ''; 272 + # Believe it or not, Tahoe is very brittle about the order of 273 + # arguments to $(tahoe start). The node directory must come first, 274 + # and arguments which alter Twisted's behavior come afterwards. 275 + script = '' 276 + tahoe start ${nodedir} -n -l- --pidfile=${pidfile} 277 + ''; 278 + }); 279 + users.extraUsers = flip mapAttrs' cfg.nodes (node: _: 280 + nameValuePair "tahoe.${node}" { 281 + description = "Tahoe node user for node ${node}"; 282 + isSystemUser = true; 283 + }); 284 + }) 285 + ]; 286 + }