Skip to content

Borg Backup

Step-by-step guide to using borg as a tool for backups across multiple devices. I'll use a client-server approach where the server stores backups of multiple clients.

Partition the physical drive and create a filesystem

Find the device name of your hard drive first using lsblk or parted -l. The name is in the format sdX where X is a lowercase letter. Create a new primary partition on this device using parted. When asked, confirm with Yes.

1
2
3
4
# parted /dev/sdX/
(parted) mklabel gpt
(parted) mkpart primary 1 -1
(parted) quit

Use mkfs.ext4 to format the partition as ext4. Optionally, add a label by passing -L to the command. I use the label backup.

1
# mkfs.ext4 -L backup /dev/sdX1

This process may take a little while. Verify it's success afterwards by checking lsblk --fs.

Mounting the partition at boot time

In order to mount the filesystem each time our server boots, edit the file /etc/fstab. In this case we add a line referencing the UUID found in lsblk --fs and mount it as ext4 to /mnt/backup.

1
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /mnt/backup    ext4    defaults   0       2

Now reboot or manually mount the filesystem.

1
2
# /mnt/backup
# mount -a

Create a backup user and set it's home directory

Add a user on the server who will have access to borg. Set the home directory to the backup partition.

1
2
3
# useradd -m borg
# passwd borg
# usermod -d /mnt/backup/borg -m borg

Allow ssh login as borg user

On each client device, create a new ssh identity for borg and copy the public key to the server.

1
2
$ ssh-keygen -t ed25519
$ ssh-copy-id -i «path/to/key» borg@«server»

Restrict borg user access

In case a single machine is compromised, an attacker will have acces to the borg server and will be able to delete all backups and control the server. To avoid this, we can restrict ssh access to only allow the borg command. Therefore, we log in as borg on our server and edit the file .ssh/authorized_keys. For each client, find the corresponding line and expand it by specifying command="..." as seen below:

1
command="borg serve --restrict-to-path ~/repo/«client»" ssh-ed25519 «key_fingerprint» «user»@«client»

Note that an attacker is still able to run borg prune and thereby delete existing backups. In order to avoid this, we can additionaly specify the --append-only flag.

In this case we will not be able to run borg prune remotely anymore. To delete old backups, we will need physical access to the machine.

1
command="borg serve --restrict-to-path ~/repo/«client» --append-only" ssh-ed25519 «key_fingerprint» «user»@«client»

Finally, we can now disable normal login for the user borg.

1
# passwd -l borg

Login as borg via root

After doing this, we will still be able to log into our borg account by running su - borg as root.

1
# su - borg

Create a borg repository

As borg on «server»:

1
$ mkdir -p ~/repo/«client»

On client:

1
$ borg init --encryption=repokey borg@«server»:~/repo/«client»

Export the repository key and store it in a safe location (e.g. password safe)

1
$ borg key export borg@«server»:~/repo/«client» ./borg-key-«client»

Backup a single file or directory

1
# borg create -s --progress borg@«server»:~/repo/«client»::«archive» /path/to/file

Backup an entire filesystem

Locations you want to exclude:

1
2
3
4
5
6
7
8
/dev
/lost+found
/mnt
/media
/proc
/run
/sys
/tmp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# borg create --progress --verbose --stats --exclude-caches --exclude '/dev/*' \
    --exclude '/lost+found/*'       \
    --exclude '/mnt/*'              \
    --exclude '/media/*'            \
    --exclude '/proc/*'             \
    --exclude '/run/*'              \
    --exclude '/sys/*'              \
    --exclude '/tmp/*'              \
    --exclude re:/\\.cache/         \
    --exclude re:/\\.ccache/        \
    borg@«server»:~/repo/«client»::«client»-«date» /

Restore a backup

Delete an archive

1
# borg delete borg@«server»:~/repo/«client»::«archive»

Delete old archives

1
2
3
4
5
6
# borg prune --verbose --stats --progress --list \
    --keep-daily=14                 \
    --keep-weekly=8                 \
    --keep-monthly=12               \
    --keep-yearly=10                \
    borg@«server»:~/repo/«client»

Automating daily backup