Secure remote backup with restic and Backblaze S3 backend
In this guide, we’ll explore the correct configuration of restic with Backblaze’s S3 backend, distinguishing it from the outdated and less recommended B2 backend prevalent in other online guides.
For those that have never heard of restic, it is a tool that allows secure cloud backup. This means there is no remote infrastructure to manage. All that is needed is an S3 bucket.
This guide primarily focuses on utilizing NixOS; however, its principles can be adapted to other Linux distributions. In such cases, setting up services will require manual intervention, involving the creation of files and direct use of systemctl
to enable them and initializing the restic repo manually.
1. Setup
The setup covered in this article will suit the needs of most people. In my other article restic and filesystem snapshots, filesystem snapshots are considered.
1.1. Bucket creation
On Backblaze, create a new bucket for your restic repository. Select a zone that is physically close to you.
1.2. Prepare New Application Key
The Backblaze master application key only works with the B2 backend. You’ll need to generate a new Backblaze application key to use the S3 backend. This information does not seem to be documented on Backblaze’s website and it is what took me very long to get my setup working correctly.
1.3. Service and timer config
On NixOS, it is very simple:
{ pkgs, userName, ... }: {
services.restic.backups.the-world = {
initialize = true;
user = userName; # root is probably not needed
environmentFile = "/etc/nixos/hosts/the-world/restic-environment-file";
repositoryFile = "/etc/nixos/hosts/the-world/restic-repository-file";
passwordFile = "/etc/nixos/hosts/the-world/restic-password-file";
pruneOpts = [
"--keep-daily 7"
"--keep-weekly 4"
"--keep-monthly 2"
"--keep-yearly 0"
];
paths = [
"/home/${userName}"
"/unsynced/${userName}/Workspace" # /unsynced and /home are on different zfs data sets since I don't want to include /unsynced in my zfs snapshots. This includes code, due to caches and artefacts taking a lot of space... However, restic can do this thanks to its exclusion list.
"/etc/nixos" # uncommited changes should be backed up
];
exclude = [
"/unsynced/${userName}/Workspace/**/build" # Dart/Flutter
"/unsynced/${userName}/Workspace/**/.dart_tool" # Dart/Flutter
"/unsynced/${userName}/Workspace/**/target" # Rust (even though "--exclude-caches" should be enough)
"/home/${userName}/.cache"
"/home/${userName}/.local/share/waydroid" # permission issues with normal user
"/home/${userName}/.local/share/Trash"
"/home/${userName}/.var/app/*/cache"
"/home/.zfs" # ZFS snapshots
];
backupPrepareCommand = "${pkgs.restic}/bin/restic unlock"; # necessary to prevent locks from persisting indefinitely. See more:
# https://forum.restic.net/t/restic-unlock-automation/5511
extraBackupArgs = [
"--exclude-caches"
];
timerConfig = {
OnCalendar = "hourly"; # Empty string to disable the timer
Persistent = true;
# NB: the option Persistent=true triggers the service
# immediately if it missed the last start time
};
};
}
If you also want to use userName
the same way I use it, I defined it in specialArgs
(in my flake.nix
):
specialArgs = {
userName = "manuel"; # simplified version of my actual config
# ...
}
On other Linux distributions you will have to initialize the restic repo manually.
1.4. Repo files
Make sure the following line is added to your .gitignore
:
**/restic-*-file
Create these files:
/etc/nixos/hosts/YOUR_HOST_NAME/restic-environment-file
AWS_ACCESS_KEY_ID="your_backblaze_keyID_goes_here" AWS_SECRET_ACCESS_KEY="your_backblaze_keyID_goes_here"
NB: do not use
B2_ACCOUNT_ID
andB2_ACCOUNT_KEY
, as they are designed to work with the B2 backend./etc/nixos/hosts/YOUR_HOST_NAME/restic-repository-file
s3:https://s3.YOUR_LOCATION.backblazeb2.com/your_backblaze_bucket_name_goes_here
Make sure to enter the right bucket location, for example:
s3:https://s3.eu-central-003.backblazeb2.com/your_backblaze_bucket_name_goes_here
Do not use the B2 backend that is found in most tutorials, such as:
b2:your_backblaze_bucket_name_goes_here:/
/etc/nixos/hosts/YOUR_HOST_NAME/restic-password-file
your_restic_repo_password_goes_here
And then run nixos-rebuild switch
with superuser privileges. Now, you can enjoy your restic backups. Make sure to regularly check their status.
2. Status monitoring
2.1. Systemd service
services.restic.backups.the-world
generates restic-backups-the-world.service
and restic-backups-the-world.timer
.
Useful commands:
systemctl status restic-backups-the-world.service
systemctl restart restic-backups-the-world.service
2.2. Locks
Locks can be listed with restic list locks --no-lock
, inspected with restic cat lock lock-UUID
and disentangled with restic unlock
.
To prevent locks from persisting indefinitely and preventing a fully automated backup strategy, ensure the presence of backupPrepareCommand = "${pkgs.restic}/bin/restic unlock"
in your configuration. A discussion about this can be found here: https://forum.restic.net/t/restic-unlock-automation/5511.
3. Restoring
To restore from your backup, run:
restic mount /some/path