Skip to content
Snippets Groups Projects
private-storage.nix 4.56 KiB
Newer Older
# A NixOS module which can instantiate a Tahoe-LAFS storage server in the
# preferred configuration for the Private Storage grid.
{ pkgs, lib, config, ... }:
let
  pspkgs = pkgs.callPackage ./pspkgs.nix { };
Jean-Paul Calderone's avatar
Jean-Paul Calderone committed
  # Grab the configuration for this module for convenient access below.
  cfg = config.services.private-storage;
in
{
  # Upstream tahoe-lafs module conflicts with ours (since ours is a
Jean-Paul Calderone's avatar
Jean-Paul Calderone committed
  # copy/paste/edit of upstream's...).  Disable it.
  #
  # https://nixos.org/nixos/manual/#sec-replace-modules
  disabledModules =
  [ "services/network-filesystems/tahoe.nix"
  ];

Jean-Paul Calderone's avatar
Jean-Paul Calderone committed
  # Load our tahoe-lafs module.  It is configurable in the way I want it to be
  # configurable.
  options =
  { services.private-storage.enable = lib.mkEnableOption "private storage service";
    services.private-storage.tahoe.package = lib.mkOption
    { default = pspkgs.privatestorage;
      type = lib.types.package;
      example = lib.literalExample "pkgs.tahoelafs";
      description = ''
        The package to use for the Tahoe-LAFS daemon.
      '';
    };
    services.private-storage.publicIPv4 = lib.mkOption
    { default = "127.0.0.1";
      type = lib.types.str;
      example = lib.literalExample "192.0.2.0";
      description = ''
        An IPv4 address to advertise for this storage service.
      '';
    };
    services.private-storage.introducerFURL = lib.mkOption
    { default = null;
      type = lib.types.nullOr lib.types.str;
      example = lib.literalExample "pb://<tubid>@<location hint>/<swissnum>";
      description = ''
        A Tahoe-LAFS introducer node fURL at which this storage node should announce itself.
      '';
    };
    services.private-storage.publicStoragePort = lib.mkOption
    { default = 8898;
      type = lib.types.int;
      example = lib.literalExample 8098;
      description = ''
        The port number on which to service storage clients.
      '';
    };
    services.private-storage.issuerRootURL = lib.mkOption
    { default = "https://issuer.privatestorage.io/";
      type = lib.types.str;
      example = lib.literalExample "https://example.invalid/";
      description = ''
        The URL of the Ristretto issuer service to announce.
      '';
    };
Jean-Paul Calderone's avatar
Jean-Paul Calderone committed

  # Define configuration based on values given for our options - starting with
  # the option that says whether this is even turned on.
  config = lib.mkIf cfg.enable
  { services.tahoe.nodes."storage" =
    { package = config.services.private-storage.tahoe.package;
Jean-Paul Calderone's avatar
Jean-Paul Calderone committed
      # Each attribute in this set corresponds to a section in the tahoe.cfg
      # file.  Attributes on those sets correspond to individual assignments
      # in those sections.
      #
      # We just populate this according to policy/preference of Private
      # Storage.
      { client = if cfg.introducerFURL == null then {} else
        { "introducer.furl" = cfg.introducerFURL;
        };
        node =
        # XXX Should try to name that is unique across the grid.
        { nickname = "storage";
Jean-Paul Calderone's avatar
Jean-Paul Calderone committed
          # We have the web port active because the CLI uses it.  We may
          # eventually turn this off, or at least have it off by default (with
          # an option to turn it on).  I don't know how much we'll use the CLI
          # on the nodes.  Maybe very little?  Or maybe it will be part of a
          # health check for the node...  In any case, we tell it to bind to
          # localhost so no one *else* can use it.  And the principle of the
          # web interface is that merely having access to it doesn't grant
          # access to any data.  It does grant access to storage capabilities
          # but with our plugin configuration you still need ZKAPs to use
          # those...
          "web.port" = "tcp:3456:interface=127.0.0.1";
Jean-Paul Calderone's avatar
Jean-Paul Calderone committed
          # We have to tell Tahoe-LAFS where to listen for Foolscap
          # connections for the storage protocol.  We have to tell it twice.
          # First, in the syntax which it uses to listen.
          "tub.port" = "tcp:${toString cfg.publicStoragePort}";
Jean-Paul Calderone's avatar
Jean-Paul Calderone committed
          # Second, in the syntax it advertises to in the fURL.
          "tub.location" = "tcp:${cfg.publicIPv4}:${toString cfg.publicStoragePort}";
        { enabled = true;
Jean-Paul Calderone's avatar
Jean-Paul Calderone committed
          # Turn on our plugin.
          plugins = "privatestorageio-zkapauthz-v1";
        };
        "storageserver.plugins.privatestorageio-zkapauthz-v1" =
        { "ristretto-issuer-root-url" = cfg.issuerRootURL;
Jean-Paul Calderone's avatar
Jean-Paul Calderone committed

    # Let traffic destined for the storage node's Foolscap server through.
    networking.firewall.allowedTCPPorts = [ cfg.publicStoragePort ];