1 { pkgs, lib, hostName, ... }:
4 # Show what's happening to the user
5 systemd.services."zfs-term@" = {
6 description = "ZFS terminal for: %I";
7 unitConfig.StopWhenUnneeded = false;
8 environment.DISPLAY = ":0";
9 environment.XAUTHORITY = "/home/sevy/.Xauthority";
10 after = [ "graphical.target" ];
14 ExecStart = pkgs.writeShellScript "zfs-term" ''
17 ${pkgs.xterm}/bin/xterm -fg white -bg black -fa Monospace -fs 6 \
18 -title "ZFS backup to: $DESTPOOL" -e "journalctl -f -o short \
19 -u zfs-import@$DESTPOOL \
20 -u zfs-local-backup-home@$DESTPOOL"
24 # Prune old snapshots on the backup and send new ones
25 systemd.services."zfs-local-backup-home@" = {
26 description = "ZFS backup home, on: %I";
27 wants = [ "zfs-term@%i.service" ];
28 after = [ "zfs-import@%i.service" ];
29 requires = [ "zfs-import@%i.service" ];
30 path = lib.mkBefore [ "/run/booted-system/sw" ];
34 CacheDirectory = [ "zfs-usb-backup/%I" ];
35 RuntimeDirectory = [ "zfs-usb-backup/%I" ];
38 SyslogIdentifier = "zfs-local-backup-home@%i";
39 ExecStartPre = "+" + pkgs.writeShellScript "zfs-local-backup-home-startPre" ''
42 if zpool status "$DESTPOOL"; then
43 zfs allow ${User} bookmark,hold,mount,send ${hostName}/home
44 zfs allow ${User} bookmark,create,destroy,load-key,mount,mountpoint,receive,rollback,snapshot "$DESTPOOL"/${User}
45 zpool scrub -p "$DESTPOOL" || true
48 ExecStart = pkgs.writeShellScript "zfs-local-backup-home" ''
51 # sanoid is quite conservative:
52 # by setting hourly=24, a snapshot must be >24 hours old
53 # and there must been >24 total hourly snapshots,
54 # or nothing is pruned.
55 install -D -m 400 /dev/stdin /tmp/sanoid/sanoid.conf <<EOF
59 process_children_only=false
61 [$DESTPOOL/${User}/backup/${hostName}/home]
69 ${pkgs.sanoid}/bin/sanoid \
70 --cache-dir /var/cache/zfs-usb-backup/"$DESTPOOL" \
71 --configdir /tmp/sanoid \
73 --run-dir /run/zfs-usb-backup/"$DESTPOOL" \
76 for dataset in ${hostName}/home; do
77 ${pkgs.sanoid}/bin/syncoid \
79 --exclude "home/Downloads" \
80 --exclude "home/Videos" \
82 --no-privilege-elevation \
89 "$DESTPOOL"/${User}/backup/"$dataset"
92 ExecStartPost = "+" + pkgs.writeShellScript "zfs-local-backup-home-startPost" ''
95 # Only if the zpool still exists to avoid uninterruptible hanging
96 if zpool status -v "$DESTPOOL"; then
97 # Scrub the zpool 1 minute (in the background)
98 zpool scrub "$DESTPOOL"
101 while zpool status -v "$DESTPOOL"; do
102 zpool scrub -p "$DESTPOOL" || true
104 # Export the zpool (to avoid a forced import later on)
105 zpool export "$DESTPOOL" || true
107 systemctl --no-block stop zfs-term@"$DESTPOOL"
111 programs.bash.interactiveShellInit = ''
112 mount-zfs-backup () {
116 zpool status "$zpool" 2>/dev/null ||
117 sudo zpool import -d /dev/disk/by-id/ "$zpool"
118 trap "sudo zpool export $zpool" EXIT
119 zfs list -rH -t filesystem -o mounted,mountpoint,name "$zpool"/"$USER"/backup |
120 grep "^no\\s*/" | cut -f 3 | xargs -ortL1 sudo zfs mount -Olv || true
121 ${pkgs.mate.caja-with-extensions}/bin/caja --browser /mnt/"$zpool"/"$USER"/backup