Skip to content
Snippets Groups Projects
private-storage.nix 8.15 KiB
Newer Older
  • Learn to ignore specific revisions
  • let
      pkgs = import <nixpkgs> { };
      # Here are the preconstructed secrets which we can assign to the introducer.
      # This is a lot easier than having the introducer generate them and then
      # discovering and configuring the other nodes with them.
      pemFile = pkgs.writeTextFile {
        name = "node.pem";
        text = ''
    -----BEGIN CERTIFICATE-----
    MIICojCCAYoCAQEwDQYJKoZIhvcNAQELBQAwFzEVMBMGA1UEAwwMbmV3cGJfdGhp
    bmd5MB4XDTE5MDkyMDE4NDkzNloXDTIwMDkxOTE4NDkzNlowFzEVMBMGA1UEAwwM
    bmV3cGJfdGhpbmd5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1zK4
    wH0ZvjFCnFo+PvT/ANBJ2H7pZQDRHFHmhW28VeQ4nCqlifjxJ/MOWpqKYK6rxHOK
    DNTDR5MbkFO7l0yquB0/FArP9RErezKakXz8qSLhipDZk7y+0fKWMPxcgdSzm28Z
    817Yzp1naXPHQRcno3M3eo58FyoTDAOXP3hiS+bFm8RGVINLSBJtILKoplvgSdyD
    /1Xg4zbh2FK+gS0f92jel5JyAaebt3EQPiIxwUrvi5a1w5EQKi13sJ22RK5H6sch
    Xg76GMMBCckLs+g8xza5uHLbotMnWb7ddW+pC0SQsrihUxz902lQoUuxq2aJig6o
    Ti6wsetUcxtOErfy6wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQC7ciESyktDoAus
    ni6zW30AXnoTxD/LNCf2HMUFcyFF57p5dcaTsAUhUd+aKX/iJyhy6bfgo8GGI5xN
    LvhvNQ6Cb6Z9qiCWDvEll+nbfuJNEanEd6bkR06/TX5bK5iDMYZD4Z+SSHsNDNEF
    DXJ96zp42UfQTdimxXHmZidAYvtYeLe4EDoJGhpuryEAIUwPdTvsPX+pLfCdtdyP
    595zbHkUPPnA3feWckcmN0FWiXisaE4ERXdPrcBnMB5TqY7KI0j2TjW59l1TnNFD
    dEKMyBD89ndBXvZq8JO8nzdM0WF32jSM/Yb+clS6PHoypHGo4jBTE3AEIXMUe//x
    MSwj51gz
    -----END CERTIFICATE-----
    -----BEGIN PRIVATE KEY-----
    MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXMrjAfRm+MUKc
    Wj4+9P8A0EnYfullANEcUeaFbbxV5DicKqWJ+PEn8w5amopgrqvEc4oM1MNHkxuQ
    U7uXTKq4HT8UCs/1ESt7MpqRfPypIuGKkNmTvL7R8pYw/FyB1LObbxnzXtjOnWdp
    c8dBFyejczd6jnwXKhMMA5c/eGJL5sWbxEZUg0tIEm0gsqimW+BJ3IP/VeDjNuHY
    Ur6BLR/3aN6XknIBp5u3cRA+IjHBSu+LlrXDkRAqLXewnbZErkfqxyFeDvoYwwEJ
    yQuz6DzHNrm4ctui0ydZvt11b6kLRJCyuKFTHP3TaVChS7GrZomKDqhOLrCx61Rz
    G04St/LrAgMBAAECggEAfRKjwmxzK9Fhj5H7n4exNf3ZDZUlfWiuILGRM3eGAL22
    ET3QHJKtRrTDYPF0/6BFgNZOJAr8vHrJiGbCHruWdY+5+6IVH7As/1t37psgFgWJ
    5Ikvi+glV8yQckQaV/MRuIMoKAS2Kc/eLLH32uLkTOFIG1j40lXH4DGuFFuZddbH
    Ie2TsgUmI3LXTSGSq4qSgXyB46uGuGOn4WKIAKp7O4kN2jBB5y3q9C2YltQ+Dv+k
    T64wBNK3ZnHHNKli0A86kzPLVQJfHgjzC76QRlC+guKgRoV9Kut3LLfoi6ep5yJr
    RT6Pr/hTNKCluIZUTPhmB0u3xGr9gj6vDsMCanvrsQKBgQD5y7ZJqFvgh9MlhSLN
    20p7jlyu+cYSDWktUjA4109ior8oaCVUXziSuPsr9JfwYRaYsJTUpCYKECFYLibA
    qI+Jj/auJljuCmrfWuS9Z08sAmVoU+O4FZt2UVbui5l5spU41Ze09f81DpzkHhZ0
    SEVH2SgChdy7KdPPhxcVhJHqJQKBgQDciwameP0WaazTY77ZRE4Yt+dPyPFkpSer
    bibeMmss5d+QVo4B4YEL20CrmaJq+FB9u99nL1d6VsvtWuovvHKMmoM//D8Si7PW
    ieAm9mN0L+2Xf25UVFBewQkzNuJJG+z1OtHFfIDDGnNzL2yx//3YFJnR/ehftsK7
    lIlXUElzzwKBgGUW1cx1P8lb7k0u1ejtJ/VcpZGCL3A60SewLSezqsLGDgoyK3k7
    l8944Nzm/V4gTF66h2COlX5ZDMV819372SrYggH0LuUWfi2pwQwNdPLgfV19JZjn
    1aRKQp4DDLc9WDpJ5j0rmH5GTaPbsUaZwL/U1+Y9ehicUsWXa/YfUlWpAoGBAJCZ
    7yBTj82UOCbZ7ZZS/MmkOtvLKssMpnf2XzGs6SylA/KFbdK54ny9oydgMmfkrBHk
    jtP+7GJgapET3RyzeH/MB2Z6o3grdRyjhf7F6euSSTvd558PMSsPclLMF45L6w/X
    IxdTTLGftDa/z4reB7gXucs/qY6oLAIFoA9Jqv9tAoGAIpw4GDw5IQFZhcHuHCOZ
    Xrq9L1fR5rYBQa6xcPHkMbWzigcNJz7FnLg0tB1SvF23egpmj5VAcnWyjyj883pn
    h2wuwJUFy8LALtjJwqhjUtQfv5LLiT5061/CUrhD3GEBNlYbOO4FA1Z0SIhFYn40
    VzowmHAqdxYvlfJsWe91UI0=
    -----END PRIVATE KEY-----
    '';
      };
      tubID = "rr7y46ixsg6qmck4jkkc7hke6xe4sv5f";
      swissnum = "2k6p3wrabat5jrj7otcih4cjdema4q3m";
      introducerPort = 35151;
      location = "tcp:introducer:${toString introducerPort}";
      introducerFURL = "pb://${tubID}@${location}/${swissnum}";
      introducerFURLFile = pkgs.writeTextFile {
        name = "introducer.furl";
        text = introducerFURL;
      };
    
    
      # assignAddresses :: Set Name (Set -> AttrSet) -> Set Name (Set -> AttrSet)
      assignAddresses = nodes:
        let
          # makeNetwork :: Integer -> AttrSet
          makeNetwork = n: {
            networking.firewall.enable = false;
            networking.useDHCP = false;
            networking.interfaces.eth0.ipv4.addresses = [
              { address = "192.168.0.${toString n}"; prefixLength = 24; }
            ];
          };
          # addresses :: [Integer]
          addresses = pkgs.lib.range 0 (builtins.length (builtins.attrNames nodes));
          # nodesAsList :: [(Name, (Set -> AttrSet))]
          nodesAsList = pkgs.lib.attrsets.mapAttrsToList (name: value: [name value]) nodes;
          # nodeAndNetworkList :: [[Name, Set -> AttrSet], Integer]
          nodeAndNetworkList = pkgs.lib.lists.zipListsWith (fst: snd: [fst snd]) nodesAsList addresses;
    
          # mergeNodeAndNetwork :: Integer -> Name -> (Set -> AttrSet) -> {Name, (Set -> AttrSet)}
          mergeNodeAndNetwork = number: name: node: {
            inherit name;
            value = args@{ pkgs, ... }: ((node args) // (makeNetwork number));
          };
          at = builtins.elemAt;
          merged = map (elem:
            let
              node = (at (at elem 0) 1);
              name = (at (at elem 0) 0);
              number = (at elem 1);
            in
              mergeNodeAndNetwork number name node
          ) nodeAndNetworkList;
        in
          builtins.listToAttrs merged;
    
    # https://nixos.org/nixos/manual/index.html#sec-nixos-tests
    import <nixpkgs/nixos/tests/make-test.nix> {
    
    
      nodes = assignAddresses rec {
    
        # Get a machine where we can run a Tahoe-LAFS client node.
        client =
          { config, pkgs, ... }:
          { environment.systemPackages = [
              pkgs.tahoe-lafs
              pkgs.daemonize
            ];
          };
    
        # Get another machine where we can run a Tahoe-LAFS introducer node.  It has the same configuration as the client.
        introducer = client;
    
        # Configure a single machine as a PrivateStorage storage node.
        storage =
          { config, pkgs, ... }:
          { imports =
            [ ../private-storage.nix
            ];
            services.private-storage.enable = true;
            services.private-storage.publicIPv4 = "storage";
            services.private-storage.introducerFURL = introducerFURL;
          };
      };
    
    
      # Test the machine with a Perl program (sobbing).
      testScript =
        ''
    
    Jean-Paul Calderone's avatar
    Jean-Paul Calderone committed
          # Start booting all the VMs in parallel to speed up operations down below.
          startAll;
    
    
          $introducer->succeed(
              'tahoe create-introducer ' .
              '--port tcp:${toString introducerPort} ' .
              '--location tcp:introducer:${toString introducerPort} ' .
              '/tmp/introducer'
          );
          $introducer->copyFileFromHost(
              '${pemFile}',
              '/tmp/introducer/private/node.pem'
          );
          $introducer->copyFileFromHost(
              '${introducerFURLFile}',
              '/tmp/introducer/private/introducer.furl'
          );
          $introducer->succeed(
              'daemonize ' .
              '-e /tmp/stderr ' .
              '-o /tmp/stdout ' .
              '$(type -p tahoe) run /tmp/introducer'
          );
    
          eval {
            $introducer->waitForOpenPort(${toString introducerPort});
            # Signal success. :/
            1;
          } or do {
            my $error = $@ || 'Unknown failure';
            my ($code, $log) = $introducer->execute('cat /tmp/stdout /tmp/stderr');
            $introducer->log($log);
            die $@;
          };
    
          # The systemd unit should reach the running state.
    
          $storage->waitForUnit('tahoe.storage.service');
    
    
          # Some while after that the Tahoe-LAFS node should listen on the web API
          # port. The port number here has to agree with the port number set in
          # the private-storage.nix module.
    
    
          # Once the web API is listening it should be possible to scrape some
          # status from the node if it is really working.
    
          $storage->succeed('tahoe -d /var/db/tahoe-lafs/storage status');
    
          #
          # Storage appears to be working so try to get a client to speak with it.
          #
    
          # Create a Tahoe-LAFS client on it.
    
          $client->succeed(
              'tahoe create-client ' .
              '--shares-needed 1 ' .
              '--shares-happy 1 ' .
              '--shares-total 1 ' .
              '--introducer ${introducerFURL} /tmp/client'
          );
    
          # Launch it
          $client->succeed(
              'daemonize ' .
              '-e /tmp/stderr ' .
              '-o /tmp/stdout ' .
              '$(type -p tahoe) run /tmp/client'
          );
          $client->waitForOpenPort(3456);
    
          my ($code, $out) = $client->execute(
              'tahoe -d /tmp/client ' .
              'put /etc/issue'
          );
          ($code == 0) or do {
              my ($code, $log) = $client->execute('cat /tmp/stdout /tmp/stderr');
              $client->log($log);
              die "put failed";
          };
          $client->succeed(
              'tahoe -d /tmp/client ' .
              "get $out"
          );