Backing up to Amazon S3 with Restic

January 15, 2024

This is the easiest backup solution I've found! I'm backing up production servers to specific S3 buckets using Restic.

Create a new S3 bucket

Log in to your S3 console and create a new bucket. You'll want to give it a sensible name - I like something like benholmen.server-name.backup - and be sure that you don't enable public access.

Screenshot of S3 bucket setup

Create AWS credentials

You'll want to create some credentials specially for Restic, so head over to IAM > Users. Click Create User, give it a username, then set permissions on Step 2.

Since this user should only be able to access S3 and no other AWS assets, pick Attach policies directly and search for AmazonS3FullAccess. Check the box next to AmazonS3FullAccess and click Next to review. Click Create user to make it official.

Screenshot of S3 user setup

You'll now need to generate an access key for your new user. View the newly created user, click Security credentials, and click Create access key. AWS has a number of different tools for authenticating and most of these options will steer you to another option - click Other and proceed.

Screenshot of S3 access key setup

Copy the Access key and Secret access key. You'll use these in your Restic configuration.

Screenshot of S3 access key setup

Install and configure Restic

These instructions are for Ubuntu, using the repository version of Restic.

1sudo apt install restic

As of January 15, 2024, the repository version of Restic is 0.12.1 which was released in August 2021. This is significantly behind the official source, which is 0.16.3. I decided to install the repository version because it's easier, but you can also download official binaries and install it manually.

To download the latest version, locate the latest release and find the appropriate file for your architecture. For example, I found 0.16.3 for amd64.

1wget https://github.com/restic/restic/releases/download/v0.16.3/restic_0.16.3_linux_amd64.bz2
2bzip2 -d restic_0.16.3_linux_amd64.bz2
3mv bzip2 restic_0.16.3_linux_amd64 /usr/bin/restic
4restic version

Generate a password for your backups:

1openssl rand -base64 32

You'll now set up a bash script that loads some environmental variables for Restic to use. Edit a file ~/.restic.env in your favorite editor and add these contents:

1export AWS_ACCESS_KEY_ID="your access key"
2export AWS_SECRET_ACCESS_KEY="your secret key"
3export RESTIC_REPOSITORY="s3:https://s3.amazonaws.com/benholmen.server-name.backup/restic"
4export RESTIC_PASSWORD="your password here"

I chose to put my Restic backups in a restic folder; you can drop that if you want to only use this bucket for Restic backups. In my case, I'm also using Laravel Forge to backup MySQL databases.

Make your first backup

Before running Restic commands in an ssh session or cron job, you'll need to pull in the .restic.env variables. This command will set the variables in your current session, so that they're available to Restic.

1source ~/.restic.env

You'll need to initialize a Restic repository once:

1restic init

You can now run a backup:

1restic backup /home

Restoring a backup

Each time you make a backup, Restic stores a snapshot of the changes. To see what's available, list the available snapshots:

1$ source ~/.restic.env
2$ restic snapshots
3repository 42424242 opened successfully, password is correct
4ID Time Host Tags Paths
5--------------------------------------------------------------------------------------
67498e76f 2024-01-11 20:22:22 sample /etc/nginx
7 /home/forge/sample-site.com
8
9419aa26b 2024-01-11 23:00:01 sample /etc/nginx
10 /home/forge/sample-site.com

You can then choose a specific snapshot to restore from, or just the latest:

1source ~/.restic.env
2restic restore latest --target output-directory # Restore everything from the latest snapshot
3restic restore [snapshot id] --target output-directory # Restore everything from a specific snapshot

You can also restore a specific file:

1source ~/.restic.env
2restic restore latest --include [path to file] --target output-directory # Restore specific file from the latest snapshot
3restic restore [snapshot id] --include [path to file] --target output-directory # Restore specific file from a specific snapshot

Schedule backups

Now that your configuration is working, you can schedule backups with cron. Edit your crontab:

1crontab -e

Adapt this command to suit your schedule and what you want to back up. This command does the following every hour:

  1. Loads .restic.env config file
  2. Backs up nginx config and a web folder
  3. Sends error output to ~/restic.error.log
  4. Sends all other output to ~/restic.log
1# m h dom mon dow command
20 * * * * . ~/.restic.env && restic backup /etc/nginx ~/sample-site.com/ 2>> ~/restic.error.log >> ~/restic.log

Prune your backups

If you run this indefinitely, your backups will keep increasing in size. You can prune old backups with some very flexible config - I recommend you read the docs. Here's the config I settled on, installed in my crontab:

1# m h dom mon dow command
21 0 * * * . ~/.restic.env && restic forget --keep-last 10 --keep-daily 30 --keep-monthly 12 2>> ~/restic.error.log >> ~/restic.log

This will keep the last 10 backups, one backup per day for the last 30 days, and one backup per month for the last 12 months.

This blog is an experiment: less about education and more about documenting the oddities I've experienced while building web apps.

My hope is that you're here because of a random search and you're experiencing something I've had to deal with.

Popular Posts

Recent Posts

View all