While my home lab grows and grows the amount of configurations, services and data keeps growing as well. To save me the hassle of setting up everything from scratch when something shits the bed I was looking into different methods of backing up my data.

What needs to be backed up:
- Debian Server running Plesk + whole website infrastructure
- Debian Server running Plex and my media
- Debian Server running Homeassistant and monitoring
- Raspbian based Raspberry Pi running Octoprint
- 2x Windows Machines running Windows 10

For the Linux based machines I have decided on Borg based of the ease of use, fast speed and ability to mount the backups as a filesystem.

Borg Documentation — Borg - Deduplicating Archiver 1.1.17 documentation

The easiest way for me was setting up a shared folder on my NAS dedicated to Backups. I have created a dedicated user called backup with write/read access on that shared folder.

On each Linux machine I did the following:

Setting up Borg

Mount the shared folder

sudo mkdir /mnt/backup
sudo nano /etc/fstab
You can also rename the mount to whatever you want
//NAS.IP/backup/ /mnt/backup/ cifs user=backup,password=password  0  0
If you want to mount the share as a specific user append ",userid=username" at the end of password
sudo mount -a
If you get an error 22 you might have to install cifs-utils via "sudo apt install -y cifs-utils"

Install Borg

sudo apt-get install borgbackup

After installing Borg you can initialise a repository with different authentication and encryption settings. More on this in the official documentation.

borg init --encryption=repokey-blake2 /mnt/backup/SERVER/Borg
Initialise the repo

Borg will prompt you to create a passphrase to be used to encrypt the repository.

The key is saved in the repository in the config file automatically but if you want to export it and save it somewhere else you can do it with:

borg key export /mnt/backup/SERVER/Borg/ SERVER_borg_key

Backup Script

I am basically just using the standard backup script example from Borg and change the directories that get backed up based on the applications running on the server.

#!/bin/sh

# Setting this, so the repo does not need to be given on the commandline:
export BORG_REPO=/mnt/backup/SERVER/Borg/

# See the section "Passphrase notes" for more infos.
export BORG_PASSPHRASE='yourpassphrasehere'

# some helpers and error handling:
info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; }
trap 'echo $( date ) Backup interrupted >&2; exit 2' INT TERM

info "Starting backup"

# Backup the most important directories into an archive named after
# the machine this script is currently running on:

borg create                         \
    --verbose                       \
    --filter AME                    \
    --list                          \
    --stats                         \
    --show-rc                       \
    --compression lz4               \
    --exclude-caches                \
    --exclude '/home/*/.cache/*'    \
    --exclude '/var/tmp/*'          \
                                    \
    ::'{hostname}-{now}'            \
    /etc                            \
    /home                           \
    /root                           \
    /var                            \
	/opt                            \
	/srv                            \


backup_exit=$?

info "Pruning repository"

# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly
# archives of THIS machine. The '{hostname}-' prefix is very important to
# limit prune's operation to this machine's archives and not apply to
# other machines' archives also:

borg prune                          \
    --list                          \
    --prefix '{hostname}-'          \
    --show-rc                       \
    --keep-daily    7               \
    --keep-weekly   4               \
    --keep-monthly  6               \

prune_exit=$?

# use highest exit code as global exit code
global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit ))

if [ ${global_exit} -eq 0 ]; then
    info "Backup and Prune finished successfully"
elif [ ${global_exit} -eq 1 ]; then
    info "Backup and/or Prune finished with warnings"
else
    info "Backup and/or Prune finished with errors"
fi

exit ${global_exit}
Feel free to change which directories get saved based on your needs

Add the script to crontab

0 1 * * * /pathto/backup.sh >/dev/null 2>&1

Make the script executable

chmod +x backup.sh 

Run the script to see if it works

./backup.sh

Now this is my current setup, it is not perfect and not a full disk backup that you can just restore with one click. But it works fine for my use case.

Restoring a Backup

Listing the archives

Restoring a backup with Borg seems pretty straight forward. First you can list all available backup archives in your backup respository.

borg list /pathto/backup

It should show something like this if you have used the backup script

PLATINUM-2022-02-13T11:24:27         Sun, 2022-02-13 11:24:27 [ebc13bd0349f112927889d38aa8d7e926063ee39003aac772eb6126db9c05f83]
PLATINUM-2022-02-14T01:00:01         Mon, 2022-02-14 01:00:02 [d3f86f373ce80a8a39bafe1477244527df2ddc515354790c44c41657e4515cf1]

Restoring the archive

If you want to just extract and download the archive to your current directory, you can just use the extract command

borg extract /pathto/backup::PLATINUM-2022-02-13T11:24:27

Mounting the archive
The cool thing about Borg is that you can mount the archive and look for specific files to restore. You need to create a writable directory first like a normal mount.

mkdir /mnt/borg

And then mount the archive

borg mount /pathto/backup /mnt/borg

If you want to mount a specific archive you can specify it as well

borg mount /pathto/backup::PLATINUM-2022-02-13T11:24:27 /mnt/borg

After you are done just unmount it

borg umount /mnt/borg
Great! Next, complete checkout for full access to KHDev.
Welcome back! You've successfully signed in.
You've successfully subscribed to KHDev.
Success! Your account is fully activated, you now have access to all content.
Success! Your billing info has been updated.
Your billing was not updated.