Best practices for configuring automated backups with Restic and Btrfs snapshots

I’ve set up a configuration for automated Restic backups, mostly using the Restic page on the NixOS wiki and the options in services.restic.backups. I want to use Btrfs snapshots to ensure atomicity of my backups since Restic doesn’t have native support for Btrfs snapshots. My script has two problems:

  1. It relies on two scripts that are external to my Nix configuration, which isn’t ideal. Also, the service seems to attempt to run Restic even if the Btrfs snapshot scripts fail.
  2. I’m unsure how best to pass the host information and SSH keys to the Restic systemd service. Ideally I could keep that information in ~/.ssh as I normally would and point the systemd service there. Unfortunately, Restic upstream doesn’t (seem to) support manual specification of the location of a key file.

Here is the relevant portion of my system configuration:

environment.systemPackages = [ pkgs.restic ];
    services.restic.backups.mybackup = {
        initialize = true;
        repository = "sftp:user@serveraddress:/repo/path";
        timerConfig = {
            OnCalendar = "6 hours";
            Persistent = true;
        };
        backupPrepareCommand = "/etc/nixos/restic_snapshot_init.sh";
        paths = [
            "/var/snapshots/Data"
        ];
        backupCleanupCommand = "/etc/nixos/restic_snapshot_teardown.sh";
        passwordFile = "/etc/nixos/ignore/restic-password";
    };

/etc/nixos/restic_snapshot_init.sh:

#!/bin/sh
set -e

/run/current-system/sw/bin/btrfs subvolume snapshot -r /home/user/Data/ /var/snapshots/Data

/run/current-system/sw/bin/btrfs subvolume snapshot -r /var/snapshots/Data /var/snapshots/"Data $(date)"

/etc/nixos/restic_snapshot_teardown.sh:

#!/bin/sh
set -e

/run/current-system/sw/bin/btrfs subvolume delete /var/snapshots/Data

For a short script like this, it’s fairly trivial to make it internal to your configuration:

backupPrepareCommand = "${pkgs.writeShellScript "restic-snapshot-init" ''
  set -e

  ${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r /home/user/Data/ /var/snapshots/Data

  ${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r /var/snapshots/Data /var/snapshots/"Data $(${pkgs.coreutils}/bin/date)"
''}";

The ssh keys are a harder issue. My first thought would be to move all of this to a user service. It’ll probably get a lot easier to do there. I have no idea if the restic nixos module gives you any help with that, though.

If what you want to do isn’t well covered by the module, you can always skip the module and just do things more directly through the more foundational options.

1 Like

I found an easy solution to the SSH key problem. I needed to set $HOME for the systemd service.

services.restic.backups.backupname.environmentFile = "./ignore/restic_environment";

ignore/restic_environment:

HOME=/home/username

(For completeness in the marked solution):
The shell scripts can be accomplished like this:

backupPrepareCommand = "${pkgs.writeShellScript "restic-snapshot-init" ''
  set -e

  ${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r /home/user/Data/ /var/snapshots/Data

  ${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r /var/snapshots/Data /var/snapshots/"Data $(${pkgs.coreutils}/bin/date)"
''}";