Skip to main content

Borg

From Borgs website 🔽

BorgBackup (short: Borg) is a deduplicating backup program. Optionally, it supports compression and authenticated encryption.

The main goal of Borg is to provide an efficient and secure way to backup data. The data deduplication technique used makes Borg suitable for daily backups since only changes are stored. The authenticated encryption technique makes it suitable for backups to not fully trusted targets.

How I Use Borg​

I am using Borg to create deduplicated backups for all of my data on my machines. I've set up a script to automate Borg's commands, pulling most of it directly from their automating backups example. I am using Ansible along with Semaphore UI to automate some backup tasks for databases and executing the script on a cron schedule.

Installation and Setup​

This installation is on Linux, check the docs for how to get started on your specific OS.

  1. Install the borgbackup package.
sudo apt install borgbackup -y
  1. Generate a passphrase for your Borg repo
openssl rand -hex 24
  1. Initialize a new repo

You will want to put the location that you are going to have your repo.. It will almost certainly not be the same as mine, which I will use [email protected]:/path/to/repo for this walkthrough.

I am using my Elitedesk Mini PC (Intel CPU), so I will use repokey-blake2 since borg states: On modern Intel/AMD CPUs blake2 is faster

For ARM based machines I believe repokey is faster but please confirm with the docs

borg init -e repokey-blake2 [email protected]:/path/to/repo

You will be prompted for a passphrase and you can paste the passphrase we just created..

  1. Export the Borg key from the repo to store in a secure place.
borg key export ssh://[email protected]/path/to/repo

Helpful Commands​

Below are some other helpful commands I've used since setting up Borg. You may or may not find these useful as well!

List Existing Backups​

Using the list command we can see all existing backups in the repo

borg list /path/to/repo

Repo/Archive Info​

Get the info of a repo

sudo borg info /path/to/repo

Additionally, get the info of a specific archive

sudo borg info /path/to/repo::raspberrypi-2024-01-14T02:01:58

Delete Archives​

I wanted to remove the archives from when I was testing exclusions in Borg

borg delete --glob-archives '{hostname}-\*' /path/to/repo

Delete Repo​

If needed you can also delete an entire repo and the related local cache

borg delete /path/to/repo

Examples​

The Script​

Below is the script I use to automate the backup process with Borg.

borg.sh
#!/bin/sh

# Setting this, so the repo does not need to be given on the commandline:
export BORG_REPO=ssh://[email protected]/path/to/repo

# See the section "Passphrase notes" for more infos.
export BORG_PASSPHRASE='<your-passphrase>'

# 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 '/mnt/volume/media/paperless' \
--exclude '/mnt/volume/storage/paperless' \
--exclude '/mnt/volume/database/postgres' \
--exclude '/mnt/volume/database/immich_postgres' \
--exclude '/mnt/volume/database/mongodb' \
\
::'{hostname}-{now}' \
/mnt/volume

backup_exit=$?

info "Pruning repository"

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

borg prune \
--list \
--glob-archives '{hostname}-*' \
--show-rc \
--keep-daily 5 \
--keep-weekly 2 \
--keep-monthly 3

prune_exit=$?

# actually free repo disk space by compacting segments

info "Compacting repository"

borg compact

compact_exit=$?

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

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

exit ${global_exit}

Ansible Playbook​

borg_backups.yml
- name: Backup
  hosts: "10.0.0.152"
  become: yes
  tasks:
    - name: Backup Postgres Database
      ansible.builtin.shell: docker exec -t postgres pg_dumpall -c -U gitea | gzip > "/mnt/volume/backups/postgres.sql.gz"

    - name: Backup Immich Database
      ansible.builtin.shell: docker exec -t immich_postgres pg_dumpall -c -U gitea | gzip > "/mnt/volume/backups/immich_postgres.sql.gz"

    - name: Backup Mongo Database
      ansible.builtin.shell: docker exec mongo sh -c 'mongodump --archive' | gzip > "/mnt/volume/backups/mongo.db.gz"

    - name: Backup Paperless
      ansible.builtin.shell: docker exec -t paperless-ngx document_exporter --no-archive --no-thumbnail --zip --zip-name paperless.backup /usr/src/paperless/export

    - name: Run Borg Backup Script
      ansible.builtin.shell:
        cmd: ./borg.sh
        chdir: /root/scripts