Automatic Backups with BorgBackup on Ubuntu 20.04

Updated on November 21, 2023
Automatic Backups with BorgBackup on Ubuntu 20.04 header image

Introduction

This guide will show you how to create compressed, deduplicated, and encrypted backups of your server's home directory automatically using Borg, storing them on an offsite location.

Prerequisites

You can adapt this guide for other Linux distributions with slight modifications. Borg is compatible with many operating systems.

1. Install Borg

On both the primary server and offsite server, install BorgBackup.

$ sudo apt install borgbackup

Before creating a backup, ensure you have sufficient disk space on both machines. Borg requires a few gigabytes of free space on the primary server in order to function.

$ df -h

Log into the offsite server and create a directory for Borg to use as a repository for the backups. Borg stores backups in a repository as a collection of archives.

$ mkdir /home/user/backup

On the primary server initialize a repository at the directory just created, where username is the remote user with read/write access to the backup directory, and offsite_server is the IP address of the remote server. When prompted, enter a strong passphrase to encrypt the repository.

$ borg init --encryption=repokey username@offsite_server:/home/user/backup

[...]
IMPORTANT: you will need both KEY AND PASSPHRASE to access this repo!
Use "borg key export" to export the key, optionally in printable format.
Write down the passphrase. Store both at safe place(s).

Borg saves a key in the repository in the config file that needs to be present in order to access the repository. Export this key in case the file ever becomes corrupted or lost. Both the key and passphrase are needed to access the repository.

Create a directory to store the key on the primary server.

$ mkdir -p /home/user/.config/borg/keys

Export the key to this directory.

$ borg key export username@offsite_server:/home/user/backup /home/user/.config/borg/keys/backup_repo_key

To import the key if the file ever becomes damaged, change export to import.

Set the BORG_REPO and BORG_PASSPHRASE environment variables to prevent reentering these details in this session.

$ export BORG_REPO='username@offsite_server:/home/user/backup'
$ export BORG_PASSPHRASE='your repository passphrase'

2. Passwordless SSH Access

Before creating a backup, configure Borg to connect to the offsite server without a password.

On the primary server, create a key pair for Borg.

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/your_home/.ssh/id_rsa):

Save the key as /home/user/.ssh/id_rsa_borg and do not enter a passphrase.

Add the new public key to the offsite server.

$ ssh-copy-id -i '/home/user/.ssh/id_rsa_borg' username@offsite_server

Once complete, ensure you are able to log in to the offsite server without a passphrase using the new keyfile.

$ ssh -i '/home/user/.ssh/id_rsa_borg' username@offsite_server

To increase security, limit the keyfile to be used for Borg only and dissallow remote logins.

On the offsite server, edit the authorized_keys file.

$ sudo nano /home/user/.ssh/authorized_keys

Find the public key you added earlier. For example:

ssh-rsa AAAAB3Nza[...]q34Pk= user@example.com

Insert the command directive below before ssh-rsa to limit the key to the borg command and a specific path only. Be sure to change /home/user/backup to the path of the backup repository created earlier. The line will look like this:

command="borg serve --restrict-to-path /home/user/backup",restrict,no-pty,no-agent-forwarding,no-port-forwarding ssh-rsa AAAAB3Nza[...]q34Pk= user@example.com

Save and exit the file and return to the primary server.

Attempt to log in using the keyfile and verify access is denied.

$ ssh -i '/home/user/.ssh/id_rsa_borg' username@offsite_server
PTY allocation request failed on channel 0

Press Enter to receive the second message.

$LOG ERROR borg.archiver Remote: Borg 1.1.11: Got unexpected RPC data format from client.
Connection to <IP> closed.

Once verified, export the BORG_RSH environment variable to tell Borg to use this keyfile in this session.

$ export BORG_RSH='ssh -i /home/user/.ssh/id_rsa_borg'

2. Test a Backup

On the primary server, test a backup of a file or folder in the home directory. Name it something appropriate and ensure you are not prompted for a passphrase.

$ borg create ::backup_name /home/user/path/to/file

To exclude a file or directory from a backup use --exclude=path/to/file/. For example, if you want to exclude the .cache directory when creating a backup, use:

$ borg create --exclude='/home/user/.cache' ::backup_name /home/user/path/to/file

Note: Include the full path when specifying what to exclude. For instance, use /home/user/.cache rather than .cache. Use multiple --exclude=path/to/file/ directives when excluding multiple files and directories. You may also use an exclude file if you have many exclusion patterns.

List the backups created in the repository using the list command, ensuring the backup archive just created is there.

$ borg list
backup_name       Wed, 2020-09-22 12:59:37 [f2cd0350f6cde7d58bb429fe67fg7f11h35f5bd6cdaz1b6d4d5e7b304gjjf81f]

Test a restore of the backup using borg extract. By default, Borg restores the full path of the backup to the current directory. For example in this guide, Borg restores the directories /home/user/path/to/file. To avoid writing any data, include --dry-run in the command.

$ borg extract --dry-run ::backup_name

To extract a single file in an archive, use: $ borg extract ::backup_name /file/to/restore

When finished, you may delete the test backup archive.

$ borg delete ::backup_name

3. Setup Automated Backups

To automate a backup of the home directory, create a backup script to be run daily via cron on the primary server.

$ nano borg-backup.sh

Enter the following, changing details where necessary. This script makes a backup of the /home directory, excluding extraneous files, using the prune command to keep a backup for each day of the week, one for each week and one for each month, automatically deleting extra backups to save space.

#!/bin/sh
# Backup home directory to a remote location using Borg.
# To restore: borg extract username@offsite_server:/path/to/backup_repo::backup_name

export BORG_RSH='ssh -i /home/user/.ssh/id_rsa_borg'
export BORG_REPO='username@offsite_server:/home/user/backup'
export BORG_PASSPHRASE='your repository passphrase'

# Backup /home excluding cache & downloads
borg create -v --stats ::$(hostname)-$(date +"%d-%b-%Y") /home \
--exclude '/home/*/.cache'                          \
--exclude '/home/*/.ccache'                         \
--exclude '/home/$USER/Downloads'                   \

# Prune extra backups
borg prune --prefix $(hostname)- --keep-daily=7 --keep-weekly=4 --keep-monthly=12

exit 0

Save and exit the file.

Make the script executable.

$ chmod +x borg-backup.sh

Test the script to ensure the backup completes successfully.

$ ./borg-backup.sh

Move the script to /etc/cron.daily to be executed automatically each day.

$ mv borg-backup.sh /etc/cron.daily

Conclusion

You have now successfully set up secure, automated backups of your server's home directory to an offsite location with BorgBackup.