# Suspend: # sudo systemctl suspend # Suspend for 60 seconds: # sudo rtcwake -m mem -s 60 # Power consumption: # 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 # View service log: # journalctl -u daily-backup-and-suspend # Print unit file: # cat "$(systemctl show -P FragmentPath daily-backup-and-suspend.service)" { config, pkgs, ... }: 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 { yoda.de-p1st-monitor = (builtins.readFile ../../assets/de-p1st-monitor/yodaHedgehog.ini); 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."; }]; systemd.timers."daily-backup-and-suspend" = { wantedBy = [ "multi-user.target" ]; timerConfig = { OnCalendar = [ # Daily "*-*-* 00:00:05" ]; WakeSystem = true; }; }; systemd.services."daily-backup-and-suspend" = { # Packages required for this script. # For `ssh` and `journalwatch`, there are assertions above. path = with pkgs; [ # Provides `ssh` openssh # Provides `awk`, `grep`, `sleep`, `printf`, `echo`, 'sendmail' busybox # Provides `smtpctl` opensmtpd ]; # Script to execute as main process. script = '' set -eu -o pipefail 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 :; do running_services="$(systemctl list-units --type=service --plain --quiet | awk '{ print $1 }')" if ! printf '%s' "''${running_services}" | grep '^btrfs-scrub'; then break; fi printf '%s\n' 'Delaying suspend due to running BTRFS scrub service.' sleep 60s done # Send filtered journal by email. systemctl start journalwatch.service ||: # Send notification by email. printf '%s\n\n%s' 'Subject: ${config.networking.hostName}' 'Finished backup.' | sendmail -f langbein@mail.de daniel@systemli.org # Let sendmail send emails. #while :; do # # TODO: Plain usage of `smtpctl` gives the error: # # smtpctl: this program must be setgid smtpq # queue="$(smtpctl show queue)" # if [ "''${queue}" = "" ]; then # break # fi # printf '%s\n' 'Delaying suspend due to non-empty smtpd email queue.' # sleep 1s #done sleep 15s printf '%s\n' 'Finished backup script.' # Suspend to save power. systemctl suspend ''; }; }