at 23.11-pre 8.3 kB view raw
1import ./make-test-python.nix ({ pkgs, ... }: 2 3let 4 passphrase = "supersecret"; 5 dataDir = "/ran:dom/data"; 6 excludeFile = "not_this_file"; 7 keepFile = "important_file"; 8 keepFileData = "important_data"; 9 localRepo = "/root/back:up"; 10 archiveName = "my_archive"; 11 remoteRepo = "borg@server:."; # No need to specify path 12 privateKey = pkgs.writeText "id_ed25519" '' 13 -----BEGIN OPENSSH PRIVATE KEY----- 14 b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW 15 QyNTUxOQAAACBx8UB04Q6Q/fwDFjakHq904PYFzG9pU2TJ9KXpaPMcrwAAAJB+cF5HfnBe 16 RwAAAAtzc2gtZWQyNTUxOQAAACBx8UB04Q6Q/fwDFjakHq904PYFzG9pU2TJ9KXpaPMcrw 17 AAAEBN75NsJZSpt63faCuaD75Unko0JjlSDxMhYHAPJk2/xXHxQHThDpD9/AMWNqQer3Tg 18 9gXMb2lTZMn0pelo8xyvAAAADXJzY2h1ZXR6QGt1cnQ= 19 -----END OPENSSH PRIVATE KEY----- 20 ''; 21 publicKey = '' 22 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHHxQHThDpD9/AMWNqQer3Tg9gXMb2lTZMn0pelo8xyv root@client 23 ''; 24 privateKeyAppendOnly = pkgs.writeText "id_ed25519" '' 25 -----BEGIN OPENSSH PRIVATE KEY----- 26 b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW 27 QyNTUxOQAAACBacZuz1ELGQdhI7PF6dGFafCDlvh8pSEc4cHjkW0QjLwAAAJC9YTxxvWE8 28 cQAAAAtzc2gtZWQyNTUxOQAAACBacZuz1ELGQdhI7PF6dGFafCDlvh8pSEc4cHjkW0QjLw 29 AAAEAAhV7wTl5dL/lz+PF/d4PnZXuG1Id6L/mFEiGT1tZsuFpxm7PUQsZB2Ejs8Xp0YVp8 30 IOW+HylIRzhweORbRCMvAAAADXJzY2h1ZXR6QGt1cnQ= 31 -----END OPENSSH PRIVATE KEY----- 32 ''; 33 publicKeyAppendOnly = '' 34 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFpxm7PUQsZB2Ejs8Xp0YVp8IOW+HylIRzhweORbRCMv root@client 35 ''; 36 37in { 38 name = "borgbackup"; 39 meta = with pkgs.lib; { 40 maintainers = with maintainers; [ dotlambda ]; 41 }; 42 43 nodes = { 44 client = { ... }: { 45 services.borgbackup.jobs = { 46 47 local = { 48 paths = dataDir; 49 repo = localRepo; 50 preHook = '' 51 # Don't append a timestamp 52 archiveName="${archiveName}" 53 ''; 54 encryption = { 55 mode = "repokey"; 56 inherit passphrase; 57 }; 58 compression = "auto,zlib,9"; 59 prune.keep = { 60 within = "1y"; 61 yearly = 5; 62 }; 63 exclude = [ "*/${excludeFile}" ]; 64 postHook = "echo post"; 65 startAt = [ ]; # Do not run automatically 66 }; 67 68 remote = { 69 paths = dataDir; 70 repo = remoteRepo; 71 encryption.mode = "none"; 72 startAt = [ ]; 73 environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519"; 74 }; 75 76 remoteAppendOnly = { 77 paths = dataDir; 78 repo = remoteRepo; 79 encryption.mode = "none"; 80 startAt = [ ]; 81 environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519.appendOnly"; 82 }; 83 84 commandSuccess = { 85 dumpCommand = pkgs.writeScript "commandSuccess" '' 86 echo -n test 87 ''; 88 repo = remoteRepo; 89 encryption.mode = "none"; 90 startAt = [ ]; 91 environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519"; 92 }; 93 94 commandFail = { 95 dumpCommand = "${pkgs.coreutils}/bin/false"; 96 repo = remoteRepo; 97 encryption.mode = "none"; 98 startAt = [ ]; 99 environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519"; 100 }; 101 102 sleepInhibited = { 103 inhibitsSleep = true; 104 # Blocks indefinitely while "backing up" so that we can try to suspend the local system while it's hung 105 dumpCommand = pkgs.writeScript "sleepInhibited" '' 106 cat /dev/zero 107 ''; 108 repo = remoteRepo; 109 encryption.mode = "none"; 110 startAt = [ ]; 111 environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519"; 112 }; 113 114 }; 115 }; 116 117 server = { ... }: { 118 services.openssh = { 119 enable = true; 120 settings = { 121 PasswordAuthentication = false; 122 KbdInteractiveAuthentication = false; 123 }; 124 }; 125 126 services.borgbackup.repos.repo1 = { 127 authorizedKeys = [ publicKey ]; 128 path = "/data/borgbackup"; 129 }; 130 131 # Second repo to make sure the authorizedKeys options are merged correctly 132 services.borgbackup.repos.repo2 = { 133 authorizedKeysAppendOnly = [ publicKeyAppendOnly ]; 134 path = "/data/borgbackup"; 135 quota = ".5G"; 136 }; 137 }; 138 }; 139 140 testScript = '' 141 start_all() 142 143 client.fail('test -d "${remoteRepo}"') 144 145 client.succeed( 146 "cp ${privateKey} /root/id_ed25519" 147 ) 148 client.succeed("chmod 0600 /root/id_ed25519") 149 client.succeed( 150 "cp ${privateKeyAppendOnly} /root/id_ed25519.appendOnly" 151 ) 152 client.succeed("chmod 0600 /root/id_ed25519.appendOnly") 153 154 client.succeed("mkdir -p ${dataDir}") 155 client.succeed("touch ${dataDir}/${excludeFile}") 156 client.succeed("echo '${keepFileData}' > ${dataDir}/${keepFile}") 157 158 with subtest("local"): 159 borg = "BORG_PASSPHRASE='${passphrase}' borg" 160 client.systemctl("start --wait borgbackup-job-local") 161 client.fail("systemctl is-failed borgbackup-job-local") 162 # Make sure exactly one archive has been created 163 assert int(client.succeed("{} list '${localRepo}' | wc -l".format(borg))) > 0 164 # Make sure excludeFile has been excluded 165 client.fail( 166 "{} list '${localRepo}::${archiveName}' | grep -qF '${excludeFile}'".format(borg) 167 ) 168 # Make sure keepFile has the correct content 169 client.succeed("{} extract '${localRepo}::${archiveName}'".format(borg)) 170 assert "${keepFileData}" in client.succeed("cat ${dataDir}/${keepFile}") 171 # Make sure the same is true when using `borg mount` 172 client.succeed( 173 "mkdir -p /mnt/borg && {} mount '${localRepo}::${archiveName}' /mnt/borg".format( 174 borg 175 ) 176 ) 177 assert "${keepFileData}" in client.succeed( 178 "cat /mnt/borg/${dataDir}/${keepFile}" 179 ) 180 181 with subtest("remote"): 182 borg = "BORG_RSH='ssh -oStrictHostKeyChecking=no -i /root/id_ed25519' borg" 183 server.wait_for_unit("sshd.service") 184 client.wait_for_unit("network.target") 185 client.systemctl("start --wait borgbackup-job-remote") 186 client.fail("systemctl is-failed borgbackup-job-remote") 187 188 # Make sure we can't access repos other than the specified one 189 client.fail("{} list borg\@server:wrong".format(borg)) 190 191 # TODO: Make sure that data is actually deleted 192 193 with subtest("remoteAppendOnly"): 194 borg = ( 195 "BORG_RSH='ssh -oStrictHostKeyChecking=no -i /root/id_ed25519.appendOnly' borg" 196 ) 197 server.wait_for_unit("sshd.service") 198 client.wait_for_unit("network.target") 199 client.systemctl("start --wait borgbackup-job-remoteAppendOnly") 200 client.fail("systemctl is-failed borgbackup-job-remoteAppendOnly") 201 202 # Make sure we can't access repos other than the specified one 203 client.fail("{} list borg\@server:wrong".format(borg)) 204 205 # TODO: Make sure that data is not actually deleted 206 207 with subtest("commandSuccess"): 208 server.wait_for_unit("sshd.service") 209 client.wait_for_unit("network.target") 210 client.systemctl("start --wait borgbackup-job-commandSuccess") 211 client.fail("systemctl is-failed borgbackup-job-commandSuccess") 212 id = client.succeed("borg-job-commandSuccess list | tail -n1 | cut -d' ' -f1").strip() 213 client.succeed(f"borg-job-commandSuccess extract ::{id} stdin") 214 assert "test" == client.succeed("cat stdin") 215 216 with subtest("commandFail"): 217 server.wait_for_unit("sshd.service") 218 client.wait_for_unit("network.target") 219 client.systemctl("start --wait borgbackup-job-commandFail") 220 client.succeed("systemctl is-failed borgbackup-job-commandFail") 221 222 with subtest("sleepInhibited"): 223 server.wait_for_unit("sshd.service") 224 client.wait_for_unit("network.target") 225 client.fail("systemd-inhibit --list | grep -q borgbackup") 226 client.systemctl("start borgbackup-job-sleepInhibited") 227 client.wait_until_succeeds("systemd-inhibit --list | grep -q borgbackup") 228 client.systemctl("stop borgbackup-job-sleepInhibited") 229 ''; 230})