2023-11-05 17:21:29 +01:00
|
|
|
{ config, pkgs, ... }:
|
2023-11-15 13:54:37 +01:00
|
|
|
let
|
|
|
|
backup-source = "rootNas";
|
|
|
|
# The "stay-awake" file is located at `${backup-source}:${stay-awake-file}`.
|
|
|
|
stay-awake-file = "${config.networking.hostName}.stay-awake";
|
|
|
|
in
|
2023-11-05 17:21:29 +01:00
|
|
|
{
|
2023-11-08 11:18:16 +01:00
|
|
|
# Suspend:
|
2023-11-05 17:21:29 +01:00
|
|
|
# sudo systemctl suspend
|
2023-11-08 11:18:16 +01:00
|
|
|
# Suspend for 60 seconds:
|
|
|
|
# sudo rtcwake -m mem -s 60
|
2023-11-05 17:21:29 +01:00
|
|
|
|
|
|
|
# Power consumption:
|
2023-11-05 18:40:04 +01:00
|
|
|
# 2.4W powered off, with 1 RAM, 1 SSD
|
|
|
|
# 2.6W suspended, with 1 RAM, 1 SSD
|
|
|
|
# 2.6W suspended, with 1 RAM, 1 SSD, 2 HDDs
|
|
|
|
# 18.9W idle, with 1 RAM, 1 SSD, 2 HDDs
|
2023-11-05 17:21:29 +01:00
|
|
|
|
2023-11-15 13:54:37 +01:00
|
|
|
# journalctl -u daily-backup-and-suspend
|
|
|
|
|
|
|
|
assertions = [{
|
|
|
|
assertion = config.services.openssh.enable;
|
|
|
|
message = "systemd service daily-backup-and-suspend requires SSH.";
|
|
|
|
} {
|
|
|
|
assertion = config.services.journalwatch.enable;
|
|
|
|
message = "systemd service daily-backup-and-suspend requires journalwatch.";
|
|
|
|
}];
|
2023-11-05 17:21:29 +01:00
|
|
|
|
2023-11-15 13:54:37 +01:00
|
|
|
systemd.timers."daily-backup-and-suspend" = {
|
2023-11-05 17:21:29 +01:00
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
timerConfig = {
|
|
|
|
OnCalendar = [
|
|
|
|
# Daily
|
2023-11-15 13:54:37 +01:00
|
|
|
"*-*-* 00:00:05"
|
2023-11-05 17:21:29 +01:00
|
|
|
];
|
|
|
|
WakeSystem = true;
|
2023-11-15 13:54:37 +01:00
|
|
|
};
|
|
|
|
};
|
|
|
|
systemd.services."daily-backup-and-suspend" = {
|
|
|
|
# Packages required for this script.
|
|
|
|
# For `ssh` and `journalwatch`, there are assertions above.
|
|
|
|
path = with pkgs; [
|
|
|
|
# Provides `echo`, `sleep`, `printf`.
|
|
|
|
coreutils
|
2023-11-19 14:12:18 +01:00
|
|
|
# Provides `ssh`
|
|
|
|
openssh
|
2023-11-15 13:54:37 +01:00
|
|
|
];
|
|
|
|
# Script to execute as main process.
|
2023-11-05 17:21:29 +01:00
|
|
|
script = ''
|
|
|
|
set -eu -o pipefail
|
2023-11-15 13:54:37 +01:00
|
|
|
printf '%s\n' 'Starting backup script.'
|
|
|
|
|
|
|
|
# TODO: Backup: Pull BTRFS snapshots from ${backup-source}.
|
|
|
|
|
|
|
|
# Don't suspend as long as `${backup-source}:${stay-awake-file}` exists.
|
|
|
|
while :; do
|
|
|
|
result="$(ssh ${backup-source} 'ls ${stay-awake-file} 2>&1')"
|
|
|
|
case "$${result}" in
|
|
|
|
*"No such file or directory")
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
"${stay-awake-file}")
|
|
|
|
printf '%s\n' 'Delaying suspend due to ${stay-awake-file} file.'
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
printf '%s\n' 'Delaying suspend due to SSH connectivity problems.'
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
sleep 10s
|
|
|
|
done
|
|
|
|
|
|
|
|
# Wait until no BTRFS scrub service is running.
|
|
|
|
while systemctl list-units --type=service --plain --quiet | awk '{ print $1 }' | grep '^btrfs-scrub'; do
|
|
|
|
printf '%s\n' 'Delaying suspend due to running BTRFS scrub service.'
|
|
|
|
sleep 60s
|
|
|
|
done
|
|
|
|
|
|
|
|
# Send filtered journal by email.
|
|
|
|
systemctl start journalwatch.service ||:
|
|
|
|
# Short delay to let sendmail send the email.
|
|
|
|
sleep 15s
|
|
|
|
|
|
|
|
printf '%s\n' 'Finished backup script.'
|
|
|
|
|
|
|
|
# Suspend to save power.
|
|
|
|
# TODO
|
|
|
|
#systemctl suspend
|
2023-11-05 17:21:29 +01:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
}
|