Using restic to back up files

Here's the official user's guide from restic, which I found pretty helpful. Since I'm just putting backups onto USB devices, I only need to follow the instructions for a "local" back up.

Installing restic on Ubuntu

sudo apt install restic

Let's check the version really quick:

restic version prints restic 0.9.6 compiled with go1.12.12 on linux/amd64. A little outdated -- 0.12.1 is on Github as I write this -- but it'll do.

Getting set up with restic

Now let's do some backing up!

First, let's try to gain a bare-bones conceptual understanding of how Restic works. Restic has a concept called "repositories", which is where your backup(s) will live. From the docs:

The place where your backups will be saved is called a “repository”. This chapter explains how to create (“init”) such a repository. The repository can be stored locally, or on some remote server or service.

Basically we use restic to pull data into these backup repositories. So for me, my repository (singular for now) will be on my external hard drive.

Initializing a Restic repository

OK, let's initialize one of these repositories. On my external hard drive, I ran:

mkdir /media/sschlinkert/external_harddrive/restic-repo
restic init --repo /media/sschlinkert/external_harddrive/restic-repo

Restic now asks us to create a password for this back-up "repo" (restic uses encryption). We'll be asked to enter the new password as second time to confirm.

Doing our first backup

Finally, time to back-up some data. Following the docs, I composed this command using the backup subcommand to backup my entire home/ directory:

restic -r /media/sschlinkert/external_harddrive/restic-repo --verbose backup /home/sschlinkert/

We will do subsequent snapshots by running the exact same command at later times. In other words this is the command you'd run every night or week to keep the backup up-to-date.

Ensure a snapshot was created

We can do a quick check to see our first snapshot by running:

restic -r /media/sschlinkert/external_harddrive/restic-repo snapshots

Check integrity of that snapshot

One thing that's nice about restic is that you can check the state or "health" of the backup.

restic -r /media/sschlinkert/external_harddrive/restic-repo check

which should output a block of text that should end with: no errors were found. Awesome!

Now try restoring our data!

Now let's say something bad has happened and we need to restore our files from this back-up repo.

Our files aren't exactly just sitting in a directory, as they are when using a tool like rsync. (This is a bit of a downside for restic, but it's fine.) Instead, we have to use restic's restore subcommand.

First, we copy the snapshot id of the snapshot we want to restore from from that snapshot command. Then we'll make a new directory to restore to, and restore to it using restic's restore subcommand:

mkdir ~/Documents_restored
restic -r /media/sschlinkert/external_harddrive/restic-repo restore 37769142 --target ~/Documents_restored

This'll take a while, but when it's done our data should be restored to the location we specified, ~/Documents_restored. At that point, we can do a sanity-check with:

ls ~/Documents_restored

Decent list of excludes for a Restic backup of a home directory on Linux (Made in Dec 2021)

Save the text below in a new file as something like ~/restic-excludes.txt.

You can use it like: restic -r '/media/$USER/external_harddrive/restic-repo/' --verbose backup --exclude-caches --exclude-file=/home/$USER/restic-excludes.txt /home/sschlinkert/

/home/$USER/.bundle
/home/$USER/.cache
/home/$USER/.cargo
/home/$USER/.config/Signal
/home/$USER/.config/nvim/plugged
/home/$USER/.config/nvim/swap
/home/$USER/.config/nvim/undo
/home/$USER/.gem
/home/$USER/.katrain
/home/$USER/.local
/home/$USER/.mozilla
/home/$USER/.npm
/home/$USER/.nvm
/home/$USER/.pyenv
/home/$USER/.rbenv
/home/$USER/.rustup
/home/$USER/.var/app
/home/$USER/.zoom
/home/$USER/go
/home/$USER/snap

A simpler approach for a small directory

I've got a small directory of very important documents. This directory is included in my restic snapshots, but I also want to put it in other locations as redundancies. One such location is Dropbox. However, I want it to encrypt it before I upload it to Dropbox.

Step 1: Compressing with tar

It's a directory (rather than a single file), so the first thing I'm going to do is put it in a tar ball.

tar -czvf important_documents.tar.gz important_documents/

Running this command creates important_documents.tar.gz for us. This single, compressed file will be easier for us to encrypt. (If you need more compression, try tar -cjvf.)

Step 2: Encrypting with age

I've chosen to use an encryption tool called age to encrypt and decrypt this file. I wrote a short guide here, but this'll work for our purposes:

age -p important_documents.tar.gz > important_documents.tar.gz.age

Enter a new passphrase twice. Age will create an encrypted file called important_documents.tar.gz.age.

We can safely upload this important_documents.tar.gz.age file to Dropbox or another unencrypted cloud provider (I do this through the website, but I'm sure there's a way to do it through the command line...).

Step 3: Decrypting and decompressing

We of course need to be able to restore these files. First we decrypt:

age -d important_documents.tar.gz.age > important_documents.tar.gz

Enter your passphrase to decrypt to important_documents.tar.gz. Then we extract the files from the tar ball:

tar -xzvf important_documents.tar.gz

All together (one-liners)

I think these work.

# compress and encrypt
tar -czv important_documents/ | age -p > important_documents.tar.gz.age
# decrypt and extract
age -d important_documents.tar.gz.age | tar -xzv

Couldn't we just make this a shell script?

I attempted to wed all these commands into a handy shell script called Bottle, if you want to try that.

Using symmetrical GPG encryption

If you don't want to use age (it's new), you can use gpg.

Encrypting:

gpg -c important_documents.tar.gz

Decrypting:

gpg --output important_documents.tar.gz --decrypt important_documents.tar.gz.gpg