Merge pull request #198239 from jacobgreenleaf/jacobg-borg-inhibit

nixos/borgbackup: Add option for inhibiting sleep

Changed files
+51 -4
nixos
doc
manual
from_md
release-notes
release-notes
modules
services
tests
+8
nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
···
</listitem>
<listitem>
<para>
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
···
</listitem>
<listitem>
<para>
+
<literal>borgbackup</literal> module now has an option for
+
inhibiting system sleep while backups are running, defaulting
+
to off (not inhibiting sleep), available as
+
<link linkend="opt-services.borgbackup.jobs._name_.inhibitsSleep"><literal>services.borgbackup.jobs.&lt;name&gt;.inhibitsSleep</literal></link>.
+
</para>
+
</listitem>
+
<listitem>
+
<para>
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
+2
nixos/doc/manual/release-notes/rl-2305.section.md
···
- `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.
- 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`
···
- `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.<name>.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`
+21 -4
nixos/modules/services/backup/borgbackup.nix
···
concatStringsSep " "
(mapAttrsToList (x: y: "--keep-${x}=${toString y}") cfg.prune.keep);
-
mkBackupScript = cfg: ''
on_exit()
{
exitStatus=$?
···
${optionalString (cfg.prune.prefix != null) "--glob-archives ${escapeShellArg "${cfg.prune.prefix}*"}"} \
$extraPruneArgs
${cfg.postPrune}
-
'';
mkPassEnv = cfg: with cfg.encryption;
if passCommand != null then
···
mkBackupService = name: cfg:
let
userHome = config.users.users.${cfg.user}.home;
-
in nameValuePair "borgbackup-job-${name}" {
description = "BorgBackup job ${name}";
path = with pkgs; [
borgbackup openssh
];
-
script = mkBackupScript cfg;
serviceConfig = {
User = cfg.user;
Group = cfg.group;
···
{manpage}`systemd.timer(5)`
which triggers the backup immediately if the last trigger
was missed (e.g. if the system was powered down).
'';
};
···
concatStringsSep " "
(mapAttrsToList (x: y: "--keep-${x}=${toString y}") cfg.prune.keep);
+
mkBackupScript = name: cfg: pkgs.writeShellScript "${name}-script" (''
+
set -e
on_exit()
{
exitStatus=$?
···
${optionalString (cfg.prune.prefix != null) "--glob-archives ${escapeShellArg "${cfg.prune.prefix}*"}"} \
$extraPruneArgs
${cfg.postPrune}
+
'');
mkPassEnv = cfg: with cfg.encryption;
if passCommand != null then
···
mkBackupService = name: cfg:
let
userHome = config.users.users.${cfg.user}.home;
+
backupJobName = "borgbackup-job-${name}";
+
backupScript = mkBackupScript backupJobName cfg;
+
in nameValuePair backupJobName {
description = "BorgBackup job ${name}";
path = with pkgs; [
borgbackup openssh
];
+
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;
···
{manpage}`systemd.timer(5)`
which triggers the backup immediately if the last trigger
was missed (e.g. if the system was powered down).
+
'';
+
};
+
+
inhibitsSleep = mkOption {
+
default = false;
+
type = types.bool;
+
example = true;
+
description = lib.mdDoc ''
+
Prevents the system from sleeping while backing up.
'';
};
+20
nixos/tests/borgbackup.nix
···
environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519";
};
};
};
···
client.wait_for_unit("network.target")
client.systemctl("start --wait borgbackup-job-commandFail")
client.succeed("systemctl is-failed borgbackup-job-commandFail")
'';
})
···
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";
+
};
+
};
};
···
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")
'';
})