-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathexternal-hdd-backup.nix
executable file
·130 lines (124 loc) · 4.65 KB
/
external-hdd-backup.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
{
pkgs,
config,
lib,
...
}:
let
cfg = config.custom;
in
{
options.custom.external-hdd-backup = {
enable = lib.mkEnableOption "laptop";
disk = lib.mkOption {
type = lib.types.str;
default = "/dev/disk/by-label/external-hdd";
};
mountdir = lib.mkOption {
type = lib.types.str;
default = "/media";
};
mountname = lib.mkOption {
type = lib.types.str;
default = "external-hdd";
};
};
config = lib.mkIf cfg.external-hdd-backup.enable {
systemd.services.backup = {
description = "Backup service";
# NB udisks isn't viable as non-root due to:
# Error creating textual authentication agent: Error opening current controlling terminal for the process (`/dev/tty'): No such device or address (polkit-error-quark, 0)
# Error mounting /dev/sda1: GDBus.Error:org.freedesktop.UDisks2.Error.NotAuthorizedCanObtain: Not authorized to perform operation
# And in order to communicate with GUI prompts, e.g. yad, we need to run as user
# udisks is still use for on-demand mountin, but we'll use the autofs for mounting the backup disk
script =
let
backup = pkgs.writeShellScript "backup.sh" ''
# TODO make nixos module with options
DISK="${cfg.backup.disk}"
LAST_RUN_FILE="$HOME/.cache/last_backup"
if [ -f "$LAST_RUN_FILE" ] && [ "$(( $(date +%s) - $(date +%s -r "$LAST_RUN_FILE") ))" -lt 86400 ]; then
echo "<24hrs"
exit 0
fi
# if no external-hdd
if [ ! -e $DISK ]; then
echo "no $DISK"
exit 0
fi
export DISPLAY=:0
${pkgs.xorg.xhost}/bin/xhost +local:${config.custom.username}
export GTK_R2_FILES=$HOME/.gtkrc-2.0
timeout 60 ${pkgs.yad}/bin/yad --question --title "backup" --text "Backup now? Will autostart in 60s."
prompt_status=$?
${pkgs.xorg.xhost}/bin/xhost -local:${config.custom.username}
# if not success or timeout
if [ ! $prompt_status -eq 0 -a ! $prompt_status -eq 124 ]; then
echo "backup cancelled"
${pkgs.libnotify}/bin/notify-send "backup cancelled"
exit 0
fi
DIR="${cfg.backup.mountdir}/${cfg.backup.mountname}"
cd "$DIR"
TEST_DIR=`${pkgs.util-linux}/bin/findmnt -nr -o target -S $DISK`
status=$?
if [ ! $status -eq 0 ]; then
echo "backup failed to find mount"
${pkgs.libnotify}/bin/notify-send "backup failed to find mount"
exit $status
fi
if [ "$DIR" != "$TEST_DIR" ]; then
echo "backup disk mounted at unexpected path: $TEST_DIR"
${pkgs.libnotify}/bin/notify-send "backup disk mounted at unexpected path: $TEST_DIR"
exit 1
fi
${pkgs.libnotify}/bin/notify-send "backup starting"
${pkgs.rsync}/bin/rsync -va --exclude={".cache",".local/share/Steam/"} ~/ $DIR/home/ −−delete−after
status=$?
if [ $status -eq 0 ]; then
touch "$LAST_RUN_FILE"
echo "backup finished"
${pkgs.libnotify}/bin/notify-send "backup finished"
else
echo "backup failed"
${pkgs.libnotify}/bin/notify-send "backup failed"
fi
exit $status
'';
in
"${backup}";
serviceConfig = {
Type = "oneshot";
User = config.custom.username;
};
# trigger on wake
wantedBy = [
"suspend.target"
"hibernate.target"
"hybrid-sleep.target"
"suspend-then-hibernate.target"
];
environment.DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/1000/bus";
};
# trigger backup on hard drive connection
services.udev.extraRules =
# NB could check device label with a trigger script that checks $0 and `RUN+="${trigger} /media/$env{ID_FS_LABEL}"`
# but we just assume the Seagate Expansion Desk is the same as /dev/disk/by-label/external-hdd
# UDEV has crap support for detecting devices
''
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd[a-z]*[0-9]*", ATTRS{model}=="Expansion Desk ", ATTRS{vendor}=="Seagate ", TAG+="systemd", ENV{SYSTEMD_WANTS}+="backup"
'';
services.autofs = {
enable = true;
autoMaster =
let
map = pkgs.writeText "auto.media" ''
${cfg.backup.mountname} -fstype=auto :${cfg.backup.disk}
'';
in
''
${cfg.backup.mountdir} file,sun:${map} -t 60
'';
};
};
}