Mac O’Clock
Published in

Mac O’Clock

Automating backups on Mac OS X with Borg and cron

Photo by Skitterphoto from Pexels

My first attempt at automating borg backups had a 50% success rate. I setup Vorta on two similar mac mini’s, both running Mojave. I setup borgbase to notify me if no backup had been written for 5 days. I tested on the first machine and verified the backup was completed. I simply configured the second machine and forgot about it.

Five days later I received an email that no backups had been sent from one of the machines. I tried to start a backup from the Vorta client on the machine that failed and the error read “borg not found”. It seemed really odd that the borg binary was not found after a few successful backups. I did some minimal troubleshooting, but gave up after I read that one of the solutions was to deinstall/resinstall. I knew I wanted to add more logging to the backup so I decided to investigate initiating backups via cron.

I had run across a number of resources when i was looking at borg and borgmatic before I found Vorta. One of the resources I ran across was at roll urown. The author did a great job of documenting setting and providing a solution for both system and user backups on ubuntu. I’ve adapted much of what they wrote to work on the Mac.

The installation steps I’ve already covered here. For my use case, I followed the User Data Backup section from roll.urown.net. I created a directory to contain the backup script and the environment variables

$mkdir -p ~/.config/borg
$touch ~/.config/borg/vars.sh
$vi ~/.config/borg/vars.sh

Edit the file vars.sh as follows

#!/bin/bash
export BORG_REPO='notmrealreponame.repo.borgbase.com:repo'
export BORG_PASSPHRASE='notmyrealrepopassphrase'
#export BORG_RSH='ssh -i ~/.config/borg/ssh/id_ed25519'
#export BORG_BASE_DIR="${HOME}"
#export BORG_CONFIG_DIR="${HOME}/.config/borg"
#export BORG_CACHE_DIR="${HOME}/.cache/borg"
#export BORG_SECURITY_DIR="${HOME}/.config/borg/security"
#export BORG_KEYS_DIR="${HOME}/.config/borg/keys"
#export BORG_KEY_FILE="${HOME}/.config/borg/keys/${USER}.key"

Notice I’ve commented out many of the other variables. I’ve left my ssh key in my .ssh directory (the default place where ssh would find it). Some of these variables are useful if you have multiple users, but for what I’m doing, I don’t need them defined. Next is the actual backup script. This is largely borrowed from the borg documentation. I like how the author of roll.urown.net broke out the repo and pass phrase because it allows me to version my script in github without worry of storing the repo or password. I created a file to contain my script

$touch ~/.config/borg/borg-backup
$chmod 0700 ~/.config/borg/borg-backup

With the contents of the file “borg-backup” as follows:

#!/bin/bash
# Automated User Data Backup Script for BorgBackup

exec 1>>~/.config/borg/backup.log 2>&1
# Setup environment variables
# shellcheck source=vars.sh
source ~/.config/borg/vars.sh

# 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:
# --filter AME \
# --filter AME \


/usr/local/bin/borg create \
--verbose \
--list \
--stats \
--show-rc \
--compression lz4 \
--exclude-caches \
\
::'{hostname}-{now}' \
~/Amazon\ Photos/Amazon\ Drive/ \

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:

#/usr/local/bin/borg prune \
# --list \
# --prefix '{user}-{hostname}-' \
# --show-rc \
# --keep-daily 7 \
# --keep-weekly 4 \
# --keep-monthly 6 \
#
#prune_exit=$?
prune_exit=0

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

if [ ${global_exit} -eq 1 ];
then
info "Backup and/or Prune finished with a warning"
fi

if [ ${global_exit} -gt 1 ];
then
info "Backup and/or Prune finished with an error"
fi

exit ${global_exit}

I’ve removed the “ — filter” option for now. I’ve also commented out the “prune” section. Both of these I’ll revisit after I have a better understanding of the output without filter and the impact of prune. Finally, you can see that I’m just backing up my amazon drive path.

The last step is to enable the job in cron. Run the following:

crontab -e

You will be presented with a blank file in your default editor. I added a line that looks like the following:

1 20 * * * ~/.config/borg/borg-backup

This tells cron to run this file 20:01 everyday.

After I set all this up, I tested by updating the line above (by running crontab -e ) and set it to a time that was just few minutes into the future. This worked and I left it alone for a few days.

Unfortunately, I discovered that my energy saver settings prevented cron from running and I again received notifications that borgbase was not receiving backups. After one final adjustment to the energy saver settings

I was able consistently run a backup with cron.

Next Steps

  • I’d like to pull more out into config files, like options to borg as well as paths to backup.
  • I want to consolidate logging. I’m looking at graylog to consolidate logging across my network.
  • I want to receive alerts for failures. I’m looking at using prometheus for alert management.

--

--

--

The best stories for Apple owners and enthusiasts

Recommended from Medium

How to create your own Market Index (Python)

Nuvola Integrates Repeat & Shuffle Status, Adjusts to New Deezer Design, And More

Clean Up Your Frontend Tests: Part 2

Web Development with Vim

Digging into Java debugger

What happens when you type ls -l in the shell

Flutter Interact 2019 : What happened that day!

If You Are Python Programmer Then This Should ‘Worry’ You.!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
John Wheeler

John Wheeler

Security professional, Mac enthusiast, writing code when I have to.

More from Medium

Xcode Cloud: Now Live for Apple Developers

How to Install a .IPA file using the CLI on macOS?

Article image

Install NVM (Node Version Manager) and Node.js

Dockerizing Grav And Other PHP Applications