nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{ pkgs, ... }:
2
3let
4 remoteRepository = "/root/restic-backup";
5 remoteFromFileRepository = "/root/restic-backup-from-file";
6 remoteInhibitTestRepository = "/root/restic-backup-inhibit-test";
7 remoteNoInitRepository = "/root/restic-backup-no-init";
8 rcloneRepository = "rclone:local:/root/restic-rclone-backup";
9
10 backupPrepareCommand = ''
11 touch /root/backupPrepareCommand
12 test ! -e /root/backupCleanupCommand
13 '';
14
15 backupCleanupCommand = ''
16 rm /root/backupPrepareCommand
17 touch /root/backupCleanupCommand
18 '';
19
20 testDir = pkgs.stdenvNoCC.mkDerivation {
21 name = "test-files-to-backup";
22 unpackPhase = "true";
23 installPhase = ''
24 mkdir $out
25 echo some_file > $out/some_file
26 echo some_other_file > $out/some_other_file
27 mkdir $out/a_dir
28 echo a_file > $out/a_dir/a_file
29 echo a_file_2 > $out/a_dir/a_file_2
30 '';
31 };
32
33 passwordFile = "${pkgs.writeText "password" "correcthorsebatterystaple"}";
34 paths = [ "/opt" ];
35 exclude = [ "/opt/excluded_file_*" ];
36 pruneOpts = [
37 "--keep-daily 2"
38 "--keep-weekly 1"
39 "--keep-monthly 1"
40 "--keep-yearly 99"
41 ];
42in
43{
44 name = "restic";
45
46 meta = with pkgs.lib.maintainers; {
47 maintainers = [
48 bbigras
49 i077
50 ];
51 };
52
53 nodes = {
54 server =
55 { pkgs, ... }:
56 {
57 services.restic.backups = {
58 remotebackup = {
59 inherit
60 passwordFile
61 paths
62 exclude
63 pruneOpts
64 backupPrepareCommand
65 backupCleanupCommand
66 ;
67 repository = remoteRepository;
68 initialize = true;
69 timerConfig = null; # has no effect here, just checking that it doesn't break the service
70 };
71 remote-from-file-backup = {
72 inherit passwordFile exclude pruneOpts;
73 initialize = true;
74 repositoryFile = pkgs.writeText "repositoryFile" remoteFromFileRepository;
75 paths = [
76 "/opt/a_dir/a_file"
77 "/opt/a_dir/a_file_2"
78 ];
79 dynamicFilesFrom = ''
80 find /opt -mindepth 1 -maxdepth 1 ! -name a_dir # all files in /opt except for a_dir
81 '';
82 };
83 inhibit-test = {
84 inherit
85 passwordFile
86 paths
87 exclude
88 pruneOpts
89 ;
90 repository = remoteInhibitTestRepository;
91 initialize = true;
92 inhibitsSleep = true;
93 };
94 remote-noinit-backup = {
95 inherit
96 passwordFile
97 exclude
98 pruneOpts
99 paths
100 ;
101 initialize = false;
102 repository = remoteNoInitRepository;
103 };
104 rclonebackup = {
105 inherit
106 passwordFile
107 paths
108 exclude
109 pruneOpts
110 ;
111 initialize = true;
112 repository = rcloneRepository;
113 rcloneConfig = {
114 type = "local";
115 one_file_system = true;
116 };
117
118 # This gets overridden by rcloneConfig.type
119 rcloneConfigFile = pkgs.writeText "rclone.conf" ''
120 [local]
121 type=ftp
122 '';
123 };
124 remoteprune = {
125 inherit passwordFile;
126 repository = remoteRepository;
127 pruneOpts = [ "--keep-last 1" ];
128 };
129 custompackage = {
130 inherit passwordFile paths;
131 repository = "some-fake-repository";
132 package = pkgs.writeShellScriptBin "restic" ''
133 echo "$@" >> /root/fake-restic.log;
134 '';
135
136 pruneOpts = [ "--keep-last 1" ];
137 checkOpts = [ "--some-check-option" ];
138 };
139 };
140
141 environment.sessionVariables.RCLONE_CONFIG_LOCAL_TYPE = "local";
142 };
143 };
144
145 testScript = ''
146 server.start()
147 server.wait_for_unit("dbus.socket")
148 server.fail(
149 "restic-remotebackup snapshots",
150 'restic-remote-from-file-backup snapshots"',
151 "restic-rclonebackup snapshots",
152 "grep 'backup.* /opt' /root/fake-restic.log",
153 )
154 server.succeed(
155 # set up
156 "cp -rT ${testDir} /opt",
157 "touch /opt/excluded_file_1 /opt/excluded_file_2",
158 "mkdir -p /root/restic-rclone-backup",
159 )
160
161 server.fail(
162 # test that noinit backup in fact does not initialize the repository
163 # and thus fails without a pre-initialized repository
164 "systemctl start restic-backups-remote-noinit-backup.service",
165 )
166
167 server.succeed(
168 # test that remotebackup runs custom commands and produces a snapshot
169 "timedatectl set-time '2016-12-13 13:45'",
170 "systemctl start restic-backups-remotebackup.service",
171 "rm /root/backupCleanupCommand",
172 'restic-remotebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
173
174 # test that restoring that snapshot produces the same directory
175 "mkdir /tmp/restore-1",
176 "restic-remotebackup restore latest -t /tmp/restore-1",
177 "diff -ru ${testDir} /tmp/restore-1/opt",
178
179 # test that remote-from-file-backup produces a snapshot
180 "systemctl start restic-backups-remote-from-file-backup.service",
181 'restic-remote-from-file-backup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
182 "mkdir /tmp/restore-2",
183 "restic-remote-from-file-backup restore latest -t /tmp/restore-2",
184 "diff -ru ${testDir} /tmp/restore-2/opt",
185
186 # test that remote-noinit-backup produces a snapshot once initialized
187 "restic-remote-noinit-backup init",
188 "systemctl start restic-backups-remote-noinit-backup.service",
189 'restic-remote-noinit-backup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
190
191 # test that restoring that snapshot produces the same directory
192 "mkdir /tmp/restore-3",
193 "${pkgs.restic}/bin/restic -r ${remoteRepository} -p ${passwordFile} restore latest -t /tmp/restore-3",
194 "diff -ru ${testDir} /tmp/restore-3/opt",
195
196 # test that rclonebackup produces a snapshot
197 "systemctl start restic-backups-rclonebackup.service",
198 'restic-rclonebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
199
200 # test that custompackage runs both `restic backup` and `restic check` with reasonable commandlines
201 "systemctl start restic-backups-custompackage.service",
202 "grep 'backup' /root/fake-restic.log",
203 "grep 'check.* --some-check-option' /root/fake-restic.log",
204
205 # test that we can create four snapshots in remotebackup and rclonebackup
206 "timedatectl set-time '2017-12-13 13:45'",
207 "systemctl start restic-backups-remotebackup.service",
208 "rm /root/backupCleanupCommand",
209 "systemctl start restic-backups-rclonebackup.service",
210
211 "timedatectl set-time '2018-12-13 13:45'",
212 "systemctl start restic-backups-remotebackup.service",
213 "rm /root/backupCleanupCommand",
214 "systemctl start restic-backups-rclonebackup.service",
215
216 "timedatectl set-time '2018-12-14 13:45'",
217 "systemctl start restic-backups-remotebackup.service",
218 "rm /root/backupCleanupCommand",
219 "systemctl start restic-backups-rclonebackup.service",
220
221 "timedatectl set-time '2018-12-15 13:45'",
222 "systemctl start restic-backups-remotebackup.service",
223 "rm /root/backupCleanupCommand",
224 "systemctl start restic-backups-rclonebackup.service",
225
226 "timedatectl set-time '2018-12-16 13:45'",
227 "systemctl start restic-backups-remotebackup.service",
228 "rm /root/backupCleanupCommand",
229 "systemctl start restic-backups-rclonebackup.service",
230
231 'restic-remotebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 4"',
232 'restic-rclonebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 4"',
233
234 # test that remoteprune brings us back to 1 snapshot in remotebackup
235 "systemctl start restic-backups-remoteprune.service",
236 'restic-remotebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
237
238 )
239
240 # test that the inhibit option is working
241 server.systemctl("start --no-block restic-backups-inhibit-test.service")
242 server.wait_until_succeeds(
243 "systemd-inhibit --no-legend --no-pager | grep -q restic",
244 5
245 )
246 '';
247}