Setup automatic remote backups with borg and rsync.net in NixOS

Introduction

The following is a small tutorial on how to setup Borg on NixOS, while using rsync.net as a remote target for your backups.

Prerequisites

  • An account created on rsync.net
  • NixOS on your local machine, with a flakes setup
  • You have a .ssh key pair in your local machine

Nothing else (not even having a repo on rsync.net or even borg installed) is assumed for this guide.

Terms

  • Repo: top-level storage unit where your backup data is written.

Add your public key to the rsync.net server

$ cat ~/.ssh/id_ed25519.pub | ssh <rsync.net user>@<rsync.net server ip> 'dd of=.ssh/authorized_keys oflag=append conv=notrunc'

Create remote repo on rsync.net

$ nix shell nixpkgs#borgbackup
$ borg --remote-path=borg14 init -e repokey-blake2 <rsync.net user>@<rsync.net server ip>:<path to repo name>

You will be prompted for a password. Store it in a file accessible only by root in your local machine. For example:

/var/trust/borg/passphrase

This path will later be referenced by your Nix config.

Also, export the key and store it in a safe place (maybe your password manager?):

borg --remote-path=borg14 key export --paper <rsync.net user>@<rsync.net server ip>:<path to repo name>

Create local job to automatically backup data

Configure your local NixOS to use Borg:

{
  services.borgbackup.jobs = {
    rsync = {
      paths = [
        "/paths/to/backup"
      ];
      exclude = [
      ];
      user = "root";
      group = "root";
      doInit = true;
      startAt = [
        "hourly"
      ];
      inhibitsSleep = true;
      persistentTimer = true;

      repo = "<rsync.net user>@<rsync.net server ip>:<path to repo name>";
      encryption = {
        mode = "repokey-blake2";
        passCommand = "cat /var/trust/borg/passphrase";
      };
      compression = "auto,lz4";
      prune = {
        keep = {
          hourly = 24;
          daily = 7;
          weekly = 4;
          monthly = 12;
          yearly = 99;
        };
      };
      extraArgs = [
        "--remote-path=borg14"
      ];
    };
  };

  environment.sessionVariables.BORG_REMOTE_PATH = "borg14";
}

I also have an example of a module here: borgsync.nix.

Then simply switch:

sudo nixos-rebuild switch --flake . --show-trace

Test your backup

The easiest way to test your backup is to restart the job and then list the backups on the remote server:

sudo systemctl restart borgbackup-job-rsync.service
borg list <rsync.net user>@<rsync.net server ip>:<path to repo name>