Restic is a great system agnostic tool to do backups. It’s a tool written in Go.

It has many sinks like

  • Local directory
  • SFTP (SSH)
  • Rest server
  • S3 Buckets and other compatible backends.

It’s designs principles are that it’s easy, fast, verifiable, secure and efficient.

An example solution, using nix could be

{config, ...}: {
  # Use agenix for secrets
  age.secrets = {
    "restic/env".file = ../../secrets/restic/env.age;
    "restic/repo".file = ../../secrets/restic/repo.age;
    "restic/password".file = ../../secrets/restic/password.age;
  };
 
  services.restic.backups.b2 = {    
    initialize = true;
 
    timerConfig = {
      OnCalendar = "00:05";
      # This will make sure it ran, even when the trigger was missed.
      Persistent = true;
    };
    
    # Paths to backup, this can be in another file, the nix way.
    paths = ["/my/path/to/backup"];
 
    # It's smart with how many backups it keeps. In this case it keeps the following backups
    # The last 7 days
    # The last 5 weeks
    # The last 12 months.
    pruneOpts = [
      "--keep-daily 7"
      "--keep-weekly 5"
      "--keep-monthly 12"
    ];
 
    # Use our secrets with agenix
    # The repository file holds our 'sink', backblaze b2 in our case
    environmentFile = config.age.secrets."restic/env".path;
    repositoryFile = config.age.secrets."restic/repo".path;
    passwordFile = config.age.secrets."restic/password".path;
 
    createWrapper = true;
  };
}

Make sure you apply your backups, otherwise you’ll end up with Schrödinger backups.

Sources

Restic Restic docs Nix, Agenix & restic tutorial using Backblaze B2 (Archived version)