diff --git a/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml index e943b6c26279..aded38b4f723 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml @@ -68,6 +68,14 @@ instead. + + + borgbackup module now has an option for + inhibiting system sleep while backups are running, defaulting + to off (not inhibiting sleep), available as + services.borgbackup.jobs.<name>.inhibitsSleep. + + The EC2 image module no longer fetches instance metadata in diff --git a/nixos/doc/manual/release-notes/rl-2305.section.md b/nixos/doc/manual/release-notes/rl-2305.section.md index 305c19f87f0d..7aff655f4419 100644 --- a/nixos/doc/manual/release-notes/rl-2305.section.md +++ b/nixos/doc/manual/release-notes/rl-2305.section.md @@ -28,6 +28,8 @@ In addition to numerous new and upgraded packages, this release has the followin - `carnix` and `cratesIO` has been removed due to being unmaintained, use alternatives such as [naersk](https://github.com/nix-community/naersk) and [crate2nix](https://github.com/kolloch/crate2nix) instead. +- `borgbackup` module now has an option for inhibiting system sleep while backups are running, defaulting to off (not inhibiting sleep), available as [`services.borgbackup.jobs..inhibitsSleep`](#opt-services.borgbackup.jobs._name_.inhibitsSleep). + - The EC2 image module no longer fetches instance metadata in stage-1. This results in a significantly smaller initramfs, since network drivers no longer need to be included, and faster boots, since metadata fetching can happen in parallel with startup of other services. This breaks services which rely on metadata being present by the time stage-2 is entered. Anything which reads EC2 metadata from `/etc/ec2-metadata` should now have an `after` dependency on `fetch-ec2-metadata.service` diff --git a/nixos/modules/services/backup/borgbackup.nix b/nixos/modules/services/backup/borgbackup.nix index ea1d393c7b02..0ae3d4180ae7 100644 --- a/nixos/modules/services/backup/borgbackup.nix +++ b/nixos/modules/services/backup/borgbackup.nix @@ -19,7 +19,8 @@ let concatStringsSep " " (mapAttrsToList (x: y: "--keep-${x}=${toString y}") cfg.prune.keep); - mkBackupScript = cfg: '' + mkBackupScript = name: cfg: pkgs.writeShellScript "${name}-script" ('' + set -e on_exit() { exitStatus=$? @@ -61,7 +62,7 @@ let ${optionalString (cfg.prune.prefix != null) "--glob-archives ${escapeShellArg "${cfg.prune.prefix}*"}"} \ $extraPruneArgs ${cfg.postPrune} - ''; + ''); mkPassEnv = cfg: with cfg.encryption; if passCommand != null then @@ -73,12 +74,19 @@ let mkBackupService = name: cfg: let userHome = config.users.users.${cfg.user}.home; - in nameValuePair "borgbackup-job-${name}" { + backupJobName = "borgbackup-job-${name}"; + backupScript = mkBackupScript backupJobName cfg; + in nameValuePair backupJobName { description = "BorgBackup job ${name}"; path = with pkgs; [ borgbackup openssh ]; - script = mkBackupScript cfg; + script = "exec " + optionalString cfg.inhibitsSleep ''\ + ${pkgs.systemd}/bin/systemd-inhibit \ + --who="borgbackup" \ + --what="sleep" \ + --why="Scheduled backup" \ + '' + backupScript; serviceConfig = { User = cfg.user; Group = cfg.group; @@ -341,6 +349,15 @@ in { ''; }; + inhibitsSleep = mkOption { + default = false; + type = types.bool; + example = true; + description = lib.mdDoc '' + Prevents the system from sleeping while backing up. + ''; + }; + user = mkOption { type = types.str; description = lib.mdDoc '' diff --git a/nixos/tests/borgbackup.nix b/nixos/tests/borgbackup.nix index d3cd6c66bfeb..9afe4d537da4 100644 --- a/nixos/tests/borgbackup.nix +++ b/nixos/tests/borgbackup.nix @@ -99,6 +99,18 @@ in { environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519"; }; + sleepInhibited = { + inhibitsSleep = true; + # Blocks indefinitely while "backing up" so that we can try to suspend the local system while it's hung + dumpCommand = pkgs.writeScript "sleepInhibited" '' + cat /dev/zero + ''; + repo = remoteRepo; + encryption.mode = "none"; + startAt = [ ]; + environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519"; + }; + }; }; @@ -204,5 +216,13 @@ in { client.wait_for_unit("network.target") client.systemctl("start --wait borgbackup-job-commandFail") client.succeed("systemctl is-failed borgbackup-job-commandFail") + + with subtest("sleepInhibited"): + server.wait_for_unit("sshd.service") + client.wait_for_unit("network.target") + client.fail("systemd-inhibit --list | grep -q borgbackup") + client.systemctl("start borgbackup-job-sleepInhibited") + client.wait_until_succeeds("systemd-inhibit --list | grep -q borgbackup") + client.systemctl("stop borgbackup-job-sleepInhibited") ''; })