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.
- Install the
borgbackup
package.
sudo apt install borgbackup -y
- Generate a passphrase for your Borg repo
openssl rand -hex 24
- 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 fasterFor 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..
- 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.
#!/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​
- 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