163 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
import ./make-test.nix ({ pkgs, ... }:
 | 
						|
 | 
						|
let
 | 
						|
  passphrase = "supersecret";
 | 
						|
  dataDir = "/ran:dom/data";
 | 
						|
  excludeFile = "not_this_file";
 | 
						|
  keepFile = "important_file";
 | 
						|
  keepFileData = "important_data";
 | 
						|
  localRepo = "/root/back:up";
 | 
						|
  archiveName = "my_archive";
 | 
						|
  remoteRepo = "borg@server:."; # No need to specify path
 | 
						|
  privateKey = pkgs.writeText "id_ed25519" ''
 | 
						|
    -----BEGIN OPENSSH PRIVATE KEY-----
 | 
						|
    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
 | 
						|
    QyNTUxOQAAACBx8UB04Q6Q/fwDFjakHq904PYFzG9pU2TJ9KXpaPMcrwAAAJB+cF5HfnBe
 | 
						|
    RwAAAAtzc2gtZWQyNTUxOQAAACBx8UB04Q6Q/fwDFjakHq904PYFzG9pU2TJ9KXpaPMcrw
 | 
						|
    AAAEBN75NsJZSpt63faCuaD75Unko0JjlSDxMhYHAPJk2/xXHxQHThDpD9/AMWNqQer3Tg
 | 
						|
    9gXMb2lTZMn0pelo8xyvAAAADXJzY2h1ZXR6QGt1cnQ=
 | 
						|
    -----END OPENSSH PRIVATE KEY-----
 | 
						|
  '';
 | 
						|
  publicKey = ''
 | 
						|
    ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHHxQHThDpD9/AMWNqQer3Tg9gXMb2lTZMn0pelo8xyv root@client
 | 
						|
  '';
 | 
						|
  privateKeyAppendOnly = pkgs.writeText "id_ed25519" ''
 | 
						|
    -----BEGIN OPENSSH PRIVATE KEY-----
 | 
						|
    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
 | 
						|
    QyNTUxOQAAACBacZuz1ELGQdhI7PF6dGFafCDlvh8pSEc4cHjkW0QjLwAAAJC9YTxxvWE8
 | 
						|
    cQAAAAtzc2gtZWQyNTUxOQAAACBacZuz1ELGQdhI7PF6dGFafCDlvh8pSEc4cHjkW0QjLw
 | 
						|
    AAAEAAhV7wTl5dL/lz+PF/d4PnZXuG1Id6L/mFEiGT1tZsuFpxm7PUQsZB2Ejs8Xp0YVp8
 | 
						|
    IOW+HylIRzhweORbRCMvAAAADXJzY2h1ZXR6QGt1cnQ=
 | 
						|
    -----END OPENSSH PRIVATE KEY-----
 | 
						|
  '';
 | 
						|
  publicKeyAppendOnly = ''
 | 
						|
    ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFpxm7PUQsZB2Ejs8Xp0YVp8IOW+HylIRzhweORbRCMv root@client
 | 
						|
  '';
 | 
						|
 | 
						|
in {
 | 
						|
  name = "borgbackup";
 | 
						|
  meta = with pkgs.stdenv.lib; {
 | 
						|
    maintainers = with maintainers; [ dotlambda ];
 | 
						|
  };
 | 
						|
 | 
						|
  nodes = {
 | 
						|
    client = { config, pkgs, ... }: {
 | 
						|
      services.borgbackup.jobs = {
 | 
						|
        
 | 
						|
        local = rec {
 | 
						|
          paths = dataDir;
 | 
						|
          repo = localRepo;
 | 
						|
          preHook = ''
 | 
						|
            # Don't append a timestamp
 | 
						|
            archiveName="${archiveName}"
 | 
						|
          '';
 | 
						|
          encryption = {
 | 
						|
            mode = "repokey";
 | 
						|
            inherit passphrase;
 | 
						|
          };
 | 
						|
          compression = "auto,zlib,9";
 | 
						|
          prune.keep = {
 | 
						|
            within = "1y";
 | 
						|
            yearly = 5;
 | 
						|
          };
 | 
						|
          exclude = [ "*/${excludeFile}" ];
 | 
						|
          postHook = "echo post";
 | 
						|
          startAt = [ ]; # Do not run automatically
 | 
						|
        };
 | 
						|
 | 
						|
        remote = {
 | 
						|
          paths = dataDir;
 | 
						|
          repo = remoteRepo;
 | 
						|
          encryption.mode = "none";
 | 
						|
          startAt = [ ];
 | 
						|
          environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519";
 | 
						|
        };
 | 
						|
 | 
						|
        remoteAppendOnly = {
 | 
						|
          paths = dataDir;
 | 
						|
          repo = remoteRepo;
 | 
						|
          encryption.mode = "none";
 | 
						|
          startAt = [ ];
 | 
						|
          environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519.appendOnly";
 | 
						|
        };
 | 
						|
 | 
						|
      };
 | 
						|
    };
 | 
						|
 | 
						|
    server = { config, pkgs, ... }: {
 | 
						|
      services.openssh = {
 | 
						|
        enable = true;
 | 
						|
        passwordAuthentication = false;
 | 
						|
        challengeResponseAuthentication = false;
 | 
						|
      };
 | 
						|
 | 
						|
      services.borgbackup.repos.repo1 = {
 | 
						|
        authorizedKeys = [ publicKey ];
 | 
						|
        path = "/data/borgbackup";
 | 
						|
      };
 | 
						|
 | 
						|
      # Second repo to make sure the authorizedKeys options are merged correctly
 | 
						|
      services.borgbackup.repos.repo2 = {
 | 
						|
        authorizedKeysAppendOnly = [ publicKeyAppendOnly ];
 | 
						|
        path = "/data/borgbackup";
 | 
						|
        quota = ".5G";
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  testScript = ''
 | 
						|
    startAll;
 | 
						|
 | 
						|
    $client->fail('test -d "${remoteRepo}"');
 | 
						|
 | 
						|
    $client->succeed("cp ${privateKey} /root/id_ed25519");
 | 
						|
    $client->succeed("chmod 0600 /root/id_ed25519");
 | 
						|
    $client->succeed("cp ${privateKeyAppendOnly} /root/id_ed25519.appendOnly");
 | 
						|
    $client->succeed("chmod 0600 /root/id_ed25519.appendOnly");
 | 
						|
 | 
						|
    $client->succeed("mkdir -p ${dataDir}");
 | 
						|
    $client->succeed("touch ${dataDir}/${excludeFile}");
 | 
						|
    $client->succeed("echo '${keepFileData}' > ${dataDir}/${keepFile}");
 | 
						|
 | 
						|
    subtest "local", sub {
 | 
						|
      my $borg = "BORG_PASSPHRASE='${passphrase}' borg";
 | 
						|
      $client->systemctl("start --wait borgbackup-job-local");
 | 
						|
      $client->fail("systemctl is-failed borgbackup-job-local");
 | 
						|
      # Make sure exactly one archive has been created
 | 
						|
      $client->succeed("c=\$($borg list '${localRepo}' | wc -l) && [[ \$c == '1' ]]");
 | 
						|
      # Make sure excludeFile has been excluded
 | 
						|
      $client->fail("$borg list '${localRepo}::${archiveName}' | grep -qF '${excludeFile}'");
 | 
						|
      # Make sure keepFile has the correct content
 | 
						|
      $client->succeed("$borg extract '${localRepo}::${archiveName}'");
 | 
						|
      $client->succeed('c=$(cat ${dataDir}/${keepFile}) && [[ "$c" == "${keepFileData}" ]]');
 | 
						|
    };
 | 
						|
 | 
						|
    subtest "remote", sub {
 | 
						|
      my $borg = "BORG_RSH='ssh -oStrictHostKeyChecking=no -i /root/id_ed25519' borg";
 | 
						|
      $server->waitForUnit("sshd.service");
 | 
						|
      $client->waitForUnit("network.target");
 | 
						|
      $client->systemctl("start --wait borgbackup-job-remote");
 | 
						|
      $client->fail("systemctl is-failed borgbackup-job-remote");
 | 
						|
 | 
						|
      # Make sure we can't access repos other than the specified one
 | 
						|
      $client->fail("$borg list borg\@server:wrong");
 | 
						|
 | 
						|
      #TODO: Make sure that data is actually deleted
 | 
						|
    };
 | 
						|
 | 
						|
    subtest "remoteAppendOnly", sub {
 | 
						|
      my $borg = "BORG_RSH='ssh -oStrictHostKeyChecking=no -i /root/id_ed25519.appendOnly' borg";
 | 
						|
      $server->waitForUnit("sshd.service");
 | 
						|
      $client->waitForUnit("network.target");
 | 
						|
      $client->systemctl("start --wait borgbackup-job-remoteAppendOnly");
 | 
						|
      $client->fail("systemctl is-failed borgbackup-job-remoteAppendOnly");
 | 
						|
 | 
						|
      # Make sure we can't access repos other than the specified one
 | 
						|
      $client->fail("$borg list borg\@server:wrong");
 | 
						|
 | 
						|
      #TODO: Make sure that data is not actually deleted
 | 
						|
    };
 | 
						|
 | 
						|
  '';
 | 
						|
})
 |