diff --git a/testgrid.tahoe-lafs.org/access-control.nix b/testgrid.tahoe-lafs.org/access-control.nix index ef80d69..83e206e 100644 --- a/testgrid.tahoe-lafs.org/access-control.nix +++ b/testgrid.tahoe-lafs.org/access-control.nix @@ -1,7 +1,7 @@ { ... }: { # Initial empty root password for easy login: users.users.root.initialHashedPassword = ""; - services.openssh.permitRootLogin = "prohibit-password"; + services.openssh.settings.PermitRootLogin = "prohibit-password"; # Enable the OpenSSH daemon. services.openssh.enable = true; @@ -13,7 +13,7 @@ # # A good change would be to create actual user accounts with sudo # configuration instead, probably. - - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGN4VQm3BIQKEFTw6aPrEwNuShf640N+Py2LOKznFCRT exarkun@bottom" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHx7wJQNqKn8jOC4AxySRL2UxidNp7uIK9ad3pMb1ifF flo@vantaa" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIZtWY7t8HVnaz6bluYsrAlzZC3MZtb8g0nO5L5fCQKR benoit@leastauthority.com" ]; } diff --git a/testgrid.tahoe-lafs.org/configuration.nix b/testgrid.tahoe-lafs.org/configuration.nix index 1ebdf1d..04768d6 100644 --- a/testgrid.tahoe-lafs.org/configuration.nix +++ b/testgrid.tahoe-lafs.org/configuration.nix @@ -3,13 +3,16 @@ # Include the results of the hardware scan. ./hardware-configuration.nix - # Run a Tahoe-LAFS grid - ./tahoe-lafs-testgrid.nix + # This was generated while setting up the machine with nixos-infect. + ./networking.nix + + # Configure the rest of the system + ./system-configuration.nix # Configure authn/authz for system administration ./access-control.nix - # Configure the rest of the system - ./system-configuration.nix + # Run a Tahoe-LAFS grid + ./tahoe-lafs-testgrid.nix ]; } diff --git a/testgrid.tahoe-lafs.org/hardware-configuration.nix b/testgrid.tahoe-lafs.org/hardware-configuration.nix index 4812e87..6bb5267 100644 --- a/testgrid.tahoe-lafs.org/hardware-configuration.nix +++ b/testgrid.tahoe-lafs.org/hardware-configuration.nix @@ -11,23 +11,14 @@ # VM and need a new hardware configuration for it - unless it happens to be # configured just like this one, which it might be). -{ config, lib, pkgs, modulesPath, ... }: - -{ - imports = - [ (modulesPath + "/profiles/qemu-guest.nix") - ]; - - boot.initrd.availableKernelModules = [ "ata_piix" "virtio_pci" "virtio_scsi" "xhci_pci" "sd_mod" "sr_mod" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ ]; - boot.extraModulePackages = [ ]; - - fileSystems."/" = - { device = "/dev/disk/by-uuid/32c12782-e288-4ae2-a2bd-796b37087ff4"; - fsType = "ext4"; - }; - - swapDevices = [ ]; - +{ modulesPath, ... }: { + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + boot.loader.grub.device = "/dev/sda"; + boot.initrd.availableKernelModules = + [ "ata_piix" "uhci_hcd" "xen_blkfront" "vmw_pvscsi" ]; + boot.initrd.kernelModules = [ "nvme" ]; + fileSystems."/" = { + device = "/dev/sda1"; + fsType = "ext4"; + }; } diff --git a/testgrid.tahoe-lafs.org/networking.nix b/testgrid.tahoe-lafs.org/networking.nix new file mode 100644 index 0000000..025e51a --- /dev/null +++ b/testgrid.tahoe-lafs.org/networking.nix @@ -0,0 +1,50 @@ +{ lib, ... }: { + # This file was populated at runtime with the networking + # details gathered from the active system. + networking = { + + hostName = "testgrid"; + domain = "tahoe-lafs.org"; + + nameservers = + [ "2a01:4ff:ff00::add:1" "2a01:4ff:ff00::add:2" "185.12.64.2" ]; + defaultGateway = "172.31.1.1"; + defaultGateway6 = { + address = "fe80::1"; + interface = "eth0"; + }; + dhcpcd.enable = false; + usePredictableInterfaceNames = lib.mkForce false; + interfaces = { + eth0 = { + ipv4.addresses = [{ + address = "37.27.215.216"; + prefixLength = 32; + }]; + ipv6.addresses = [ + { + address = "2a01:4f9:c010:d906::1"; + prefixLength = 64; + } + { + address = "fe80::9400:3ff:fefa:158c"; + prefixLength = 64; + } + ]; + ipv4.routes = [{ + address = "172.31.1.1"; + prefixLength = 32; + }]; + ipv6.routes = [{ + address = "fe80::1"; + prefixLength = 128; + }]; + }; + + }; + }; + services.udev.extraRules = '' + ATTR{address}=="96:00:03:fa:15:8c", NAME="eth0" + + ''; +} diff --git a/testgrid.tahoe-lafs.org/repo-tahoe-lafs-master.nix b/testgrid.tahoe-lafs.org/repo-tahoe-lafs-master.nix deleted file mode 100644 index 60ea4f2..0000000 --- a/testgrid.tahoe-lafs.org/repo-tahoe-lafs-master.nix +++ /dev/null @@ -1,9 +0,0 @@ -let - pkgs = import {}; -in - pkgs.fetchFromGitHub { - owner = "tahoe-lafs"; - repo = "tahoe-lafs"; - rev = "49df402f0762b34c88b01d183b9d217da117cc79"; - sha256 = "0fpvznwgb35fz1i7n76y3kx5mf8qafr5xma087a5hjj3ksxmbgmn"; - } \ No newline at end of file diff --git a/testgrid.tahoe-lafs.org/system-configuration.nix b/testgrid.tahoe-lafs.org/system-configuration.nix index 302ded2..ce853c6 100644 --- a/testgrid.tahoe-lafs.org/system-configuration.nix +++ b/testgrid.tahoe-lafs.org/system-configuration.nix @@ -5,41 +5,9 @@ { config, pkgs, ... }: { - # Use the GRUB 2 boot loader. - boot.loader.grub.enable = true; - boot.loader.grub.version = 2; - # boot.loader.grub.efiSupport = true; - # boot.loader.grub.efiInstallAsRemovable = true; - # boot.loader.efi.efiSysMountPoint = "/boot/efi"; - # Define on which hard drive you want to install Grub. - # boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only - - networking.hostName = "testgrid"; - networking.domain = "tahoe-lafs.org"; - # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. - - # Set your time zone. - # time.timeZone = "Europe/Amsterdam"; - - # The global useDHCP flag is deprecated, therefore explicitly set to false here. - # Per-interface useDHCP will be mandatory in the future, so this generated config - # replicates the default behaviour. - networking.useDHCP = false; - networking.interfaces.ens3.useDHCP = true; - - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - - # Select internationalisation properties. - # i18n.defaultLocale = "en_US.UTF-8"; - # console = { - # font = "Lat2-Terminus16"; - # keyMap = "us"; - # }; - - # Enable the X11 windowing system. - # services.xserver.enable = true; + # Enable flakes. + # https://nixos.wiki/wiki/Nix_command + nix.extraOptions = "experimental-features = nix-command flakes"; # Periodically upgrade NixOS to the latest version. If enabled, a systemd # timer will run `nixos-rebuild switch --upgrade` once a day. @@ -52,59 +20,23 @@ allowReboot = true; }; - # Configure keymap in X11 - # services.xserver.layout = "us"; - # services.xserver.xkbOptions = "eurosign:e"; - - # Enable CUPS to print documents. - # services.printing.enable = true; - - # Enable sound. - # sound.enable = true; - # hardware.pulseaudio.enable = true; - - # Enable touchpad support (enabled default in most desktopManager). - # services.xserver.libinput.enable = true; - - # Define a user account. Don't forget to set a password with ‘passwd’. - # users.users.jane = { - # isNormalUser = true; - # extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. - # }; - # List packages installed in system profile. To search, run: # $ nix search wget - environment.systemPackages = with pkgs; [ - # Let us check out and update the system configuration repository. - git - ]; - - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - # programs.mtr.enable = true; - # programs.gnupg.agent = { - # enable = true; - # enableSSHSupport = true; - # }; + environment.systemPackages = with pkgs; + [ + # Let us check out and update the system configuration repository. + git + ]; # Make sure the firewall is enabled. This is probably the default but let's # be explicit and safe. networking.firewall.enable = true; - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - - # This value determines the NixOS release from which the default # settings for stateful data, like file locations and database versions # on your system were taken. It‘s perfectly fine and recommended to leave # this value at the release version of the first install of this system. # Before changing this value read the documentation for this option # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). - - system.stateVersion = "21.05"; # Did you read the comment? - - boot.loader.grub.devices = [ "/dev/sda" ]; - + system.stateVersion = "24.11"; # Did you read the comment? } diff --git a/testgrid.tahoe-lafs.org/tahoe-lafs-testgrid.nix b/testgrid.tahoe-lafs.org/tahoe-lafs-testgrid.nix index 05cebbe..684775e 100644 --- a/testgrid.tahoe-lafs.org/tahoe-lafs-testgrid.nix +++ b/testgrid.tahoe-lafs.org/tahoe-lafs-testgrid.nix @@ -1,10 +1,15 @@ # Define a NixOS module that sets up the Tahoe-LAFS test grid. { config, pkgs, ... }: let - # Use upstream packaging. The NixOS 21.05 package is broken (though - # master should already have a fix for that). However, maybe we want to - # run bleeding edge on this deployment anyway. - package = pkgs.callPackage ./tahoe-lafs.nix { }; + # Choose the tahoe-lafs package to run: + # + # Some local flavor (see repo history around version 89e5e1f8): + # package = pkgs.callPackage ./tahoe-lafs.nix { }; + # The package from nixpkgs: + # package = pkgs.tahoe-lafs; + # The upstream flake: + package = (builtins.getFlake + "github:tahoe-lafs/tahoe-lafs/f45175569e870ccd8a25bd9903ea109eaf25075d").packages.x86_64-linux.default; in { # Configure Tahoe to run here. services.tahoe = { @@ -30,10 +35,9 @@ in { # client. On a more realistic deployment these would all be run # separately from other to make their failure modes as independent as # possible. - nodes = - let + nodes = let # XXX NixOS module doesn't support multi-introducer configuration. - introducer = "pb://fodk4doc64febdoxke3a4ddfyanz7ajd@tcp:157.90.125.177:5000/el4fo3rm2h22cnilukmjqzyopdgqxrd2"; + introducer = "pb://flm2vcjxaxoyah3f2ufdk74augada55i@tcp:testgrid.tahoe-lafs.org:5000/s3kbdgg3j4ohifa633tt7yi25drl6jqa"; in { alpha = { inherit package; @@ -69,26 +73,10 @@ in { }; }; - # XXX The NixOS Tahoe service doesn't configure any group for the service - # users it creates. A user cannot be created without a group so without the - # following fixes, NixOS throws an error at us at evaluate time. - - # For each service user, assign it to a distinct group. - users.users."tahoe.alpha".group = "tahoe.alpha"; - # And also create that group. - users.groups."tahoe.alpha" = {}; - - users.users."tahoe.beta".group = "tahoe.beta"; - users.groups."tahoe.beta" = {}; - - users.users."tahoe.gamma".group = "tahoe.gamma"; - users.groups."tahoe.gamma" = {}; - - users.users."tahoe.introducer-alpha".group = "tahoe.introducer-alpha"; - users.groups."tahoe.introducer-alpha" = {}; - - users.users."tahoe.introducer-beta".group = "tahoe.introducer-beta"; - users.groups."tahoe.introducer-beta" = {}; + # The current nixpkgs service definition isn't compatible with the upstream + # flake, use our own + disabledModules = [ "services/network-filesystems/tahoe.nix" ]; + imports = [ ./tahoe-service.nix ]; networking.firewall.allowedTCPPorts = with config.services.tahoe; [ # Let traffic through to the introducers diff --git a/testgrid.tahoe-lafs.org/tahoe-lafs.nix b/testgrid.tahoe-lafs.org/tahoe-lafs.nix deleted file mode 100644 index ccbc2b8..0000000 --- a/testgrid.tahoe-lafs.org/tahoe-lafs.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ callPackage }: -let - # - # You can switch to a different revision of tahoe-lafs by running: - # - # nix-prefetch-github --nix --rev tahoe-lafs tahoe-lafs > /path/to/repo-tahoe-lafs-master.nix - # - # An interesting ```` to use is sometimes ``$(git rev-parse HEAD)`` if - # your working directory is a checkout of tahoe-lafs. - # - repo = import ./repo-tahoe-lafs-master.nix; - tahoe-lafs = callPackage "${repo}/nix/py3.nix" { }; -in - tahoe-lafs diff --git a/testgrid.tahoe-lafs.org/tahoe-service.nix b/testgrid.tahoe-lafs.org/tahoe-service.nix new file mode 100644 index 0000000..3304a86 --- /dev/null +++ b/testgrid.tahoe-lafs.org/tahoe-service.nix @@ -0,0 +1,380 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.services.tahoe; +in +{ + options.services.tahoe = { + introducers = lib.mkOption { + default = { }; + type = + with lib.types; + attrsOf (submodule { + options = { + nickname = lib.mkOption { + type = lib.types.str; + description = '' + The nickname of this Tahoe introducer. + ''; + }; + tub.port = lib.mkOption { + default = 3458; + type = lib.types.port; + description = '' + The port on which the introducer will listen. + ''; + }; + tub.location = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.str; + description = '' + The external location that the introducer should listen on. + + If specified, the port should be included. + ''; + }; + package = lib.mkPackageOption pkgs "tahoelafs" { }; + }; + }); + description = '' + The Tahoe introducers. + ''; + }; + nodes = lib.mkOption { + default = { }; + type = + with lib.types; + attrsOf (submodule { + options = { + nickname = lib.mkOption { + type = lib.types.str; + description = '' + The nickname of this Tahoe node. + ''; + }; + tub.port = lib.mkOption { + default = 3457; + type = lib.types.port; + 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. + ''; + }; + tub.location = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.str; + description = '' + The external location that the node should listen on. + + This is the setting to tweak if there are multiple interfaces + and you want to alter which interface Tahoe is advertising. + + If specified, the port should be included. + ''; + }; + web.port = lib.mkOption { + default = 3456; + type = lib.types.port; + 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 = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.str; + description = '' + The furl for a Tahoe introducer node. + + Like all furls, keep this safe and don't share it. + ''; + }; + client.helper = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.str; + description = '' + The furl for a Tahoe helper node. + + Like all furls, keep this safe and don't share it. + ''; + }; + client.shares.needed = lib.mkOption { + default = 3; + type = lib.types.int; + description = '' + The number of shares required to reconstitute a file. + ''; + }; + client.shares.happy = lib.mkOption { + default = 7; + type = lib.types.int; + description = '' + The number of distinct storage nodes required to store + a file. + ''; + }; + client.shares.total = lib.mkOption { + default = 10; + type = lib.types.int; + description = '' + The number of shares required to store a file. + ''; + }; + storage.enable = lib.mkEnableOption "storage service"; + storage.reservedSpace = lib.mkOption { + default = "1G"; + type = lib.types.str; + description = '' + The amount of filesystem space to not use for storage. + ''; + }; + helper.enable = lib.mkEnableOption "helper service"; + sftpd.enable = lib.mkEnableOption "SFTP service"; + sftpd.port = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.int; + description = '' + The port on which the SFTP server will listen. + + This is the correct setting to tweak if you want Tahoe's SFTP + daemon to listen on a different port. + ''; + }; + sftpd.hostPublicKeyFile = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.path; + description = '' + Path to the SSH host public key. + ''; + }; + sftpd.hostPrivateKeyFile = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.path; + description = '' + Path to the SSH host private key. + ''; + }; + sftpd.accounts.file = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.path; + description = '' + Path to the accounts file. + ''; + }; + sftpd.accounts.url = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.str; + description = '' + URL of the accounts server. + ''; + }; + package = lib.mkPackageOption pkgs "tahoelafs" { }; + }; + }); + description = '' + The Tahoe nodes. + ''; + }; + }; + config = lib.mkMerge [ + (lib.mkIf (cfg.introducers != { }) { + environment = { + etc = lib.flip lib.mapAttrs' cfg.introducers ( + node: settings: + lib.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 = tcp6:${toString settings.tub.port} + ${lib.optionalString (settings.tub.location != null) "tub.location = ${settings.tub.location}"} + ''; + } + ); + # Actually require Tahoe, so that we will have it installed. + systemPackages = lib.flip lib.mapAttrsToList cfg.introducers (node: settings: settings.package); + }; + # Open up the firewall. + # networking.firewall.allowedTCPPorts = lib.flip lib.mapAttrsToList cfg.introducers + # (node: settings: settings.tub.port); + systemd.services = lib.flip lib.mapAttrs' cfg.introducers ( + node: settings: + lib.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"; + # Believe it or not, Tahoe is very brittle about the order of + # arguments to $(tahoe run). The node directory must come first, + # and arguments which alter Twisted's behavior come afterwards. + # + # --allow-stdin-close Do not exit when stdin closes ("tahoe run" + # otherwise will exit). + # + # --nodaemon makes twistd run in the foreground. Systemd works + # best with child processes that remain in the foreground. + # + # --pidfile= prevents twistd from writing a pidfile. A pidfile is + # not necessary when Twisted runs as a foreground process. + # + ExecStart = '' + ${settings.package}/bin/tahoe run --allow-stdin-close $STATE_DIRECTORY --nodaemon --pidfile= + ''; + StateDirectory = "tahoe-lafs/introducer-${node}"; + User = "tahoe.introducer-${node}"; + Group = "tahoe.introducer-${node}"; + }; + preStart = '' + if [ ! -d $STATE_DIRECTORY/private ]; then + # See https://github.com/NixOS/nixpkgs/issues/25273 + tahoe create-introducer \ + --hostname="${config.networking.hostName}" \ + $STATE_DIRECTORY + 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 $STATE_DIRECTORY/tahoe.cfg + # ln -s /etc/tahoe-lafs/introducer-${node}.cfg $STATE_DIRECTORY/tahoe.cfg + cp /etc/tahoe-lafs/introducer-"${node}".cfg $STATE_DIRECTORY/tahoe.cfg + ''; + } + ); + users.users = lib.flip lib.mapAttrs' cfg.introducers ( + node: _: + lib.nameValuePair "tahoe.introducer-${node}" { + isSystemUser = true; + group = "tahoe.introducer-${node}"; + home = "/var/db/tahoe-lafs/introducer-${node}"; + } + ); + users.groups = lib.flip lib.mapAttrs' cfg.introducers ( + node: _: + lib.nameValuePair "tahoe.introducer-${node}" { } + ); + }) + (lib.mkIf (cfg.nodes != { }) { + environment = { + etc = lib.flip lib.mapAttrs' cfg.nodes ( + node: settings: + lib.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 = tcp6:${toString settings.tub.port} + ${lib.optionalString (settings.tub.location != null) "tub.location = ${settings.tub.location}"} + # This is a Twisted endpoint. Twisted Web doesn't work on + # non-TCP. ~ C. + web.port = tcp6:${toString settings.web.port} + + [client] + ${lib.optionalString ( + settings.client.introducer != null + ) "introducer.furl = ${settings.client.introducer}"} + ${lib.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 = ${lib.boolToString settings.storage.enable} + reserved_space = ${settings.storage.reservedSpace} + + [helper] + enabled = ${lib.boolToString settings.helper.enable} + + [sftpd] + enabled = ${lib.boolToString settings.sftpd.enable} + ${lib.optionalString (settings.sftpd.port != null) "port = ${toString settings.sftpd.port}"} + ${lib.optionalString ( + settings.sftpd.hostPublicKeyFile != null + ) "host_pubkey_file = ${settings.sftpd.hostPublicKeyFile}"} + ${lib.optionalString ( + settings.sftpd.hostPrivateKeyFile != null + ) "host_privkey_file = ${settings.sftpd.hostPrivateKeyFile}"} + ${lib.optionalString ( + settings.sftpd.accounts.file != null + ) "accounts.file = ${settings.sftpd.accounts.file}"} + ${lib.optionalString ( + settings.sftpd.accounts.url != null + ) "accounts.url = ${settings.sftpd.accounts.url}"} + ''; + } + ); + # Actually require Tahoe, so that we will have it installed. + systemPackages = lib.flip lib.mapAttrsToList cfg.nodes (node: settings: settings.package); + }; + # Open up the firewall. + # networking.firewall.allowedTCPPorts = lib.flip lib.mapAttrsToList cfg.nodes + # (node: settings: settings.tub.port); + systemd.services = lib.flip lib.mapAttrs' cfg.nodes ( + node: settings: + lib.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"; + # The comments for the introducer ExecStart config above apply here as well. + ExecStart = '' + ${settings.package}/bin/tahoe run --allow-stdin-close $STATE_DIRECTORY --nodaemon --pidfile= + ''; + StateDirectory = "tahoe-lafs/${node}"; + User = "tahoe.${node}"; + Group = "tahoe.${node}"; + }; + preStart = '' + if [ ! -d $STATE_DIRECTORY/private ]; then + tahoe create-node --hostname=localhost $STATE_DIRECTORY + 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 $STATE_DIRECTORY/tahoe.cfg + # ln -s /etc/tahoe-lafs/${lib.escapeShellArg node}.cfg $STATE_DIRECTORY/tahoe.cfg + cp /etc/tahoe-lafs/${lib.escapeShellArg node}.cfg $STATE_DIRECTORY/tahoe.cfg + ''; + } + ); + users.users = lib.flip lib.mapAttrs' cfg.nodes ( + node: _: + lib.nameValuePair "tahoe.${node}" { + isSystemUser = true; + group = "tahoe.${node}"; + home = "/var/db/tahoe-lafs/${node}"; + } + ); + users.groups = lib.flip lib.mapAttrs' cfg.nodes ( + node: _: + lib.nameValuePair "tahoe.${node}" { } + ); + }) + ]; +}