Apple Mac Backup with Rsync and Postfix


Apple Mac Backup with Rsync and Postfix


Well, I have been happily using BackBlaze to protect all laptops in our family for years. This week, Information Security at my company decided that cloud backup is a risk as I might be sending corporate secrets somewhere and blocked BackBlaze on my corporate laptop. Reasonable. A pain for me, but reasonable. I keep personal files on my corporate laptop (mostly photos) and would like to continue to back those up. 


Parts List

  • A Mac
  • Another Computer to Backup To (I use an Ubuntu Laptop)
  • rsync (Built into MacOS, but dated)
  • homebrew (To update dated MacOS rsync and install sshpass)
  • sshpass (To send password to rsync)
  • cron (Built into MacOS)
  • postfix (Built into MacOS)

Get rsync Updated and Working

When I started testing rsync from my Mac to my Linux server, I was getting some errors. Some posts recommended making sure your major versions of rsync are the same on the source as on the destination. The version of rsync that comes with the Mac is 2.X and the version on my Linux box is 3.x. I updated rsync on my Mac with these commands:

brew install rsync
sudo ln /usr/local/Cellar/rsync/3.2.3/bin/rsync /usr/local/bin/rsync3
Rather than overwriting the built-in rsync, I created a symbolic link named rsync3 in the PATH.

The rsync syntax that worked for me was:

/usr/local/bin/rsync3 -avzhu --delete --stats /Users/faucherd/Downloads/ dennis@

Let's break the rsync command line options down:
  • -a (archive mode; equals -rlptgoD (no -H,-A,-X))
  • -v (increase verbosity)
  • -z (compress file data during the transfer)
  • -h (output numbers in a human-readable format)
  • -u (--update This forces rsync to skip any files which exist on the destination and have a modified time that is newer than the source file.)
  • --delete (delete extraneous files from the receiving side (ones that aren't on the sending side))
  • --stats (print a verbose set of statistics on the file transfer)
So, basically, copy all the new stuff over and delete anything over there that I have deleted over here. is the IP address of the Linux machine and dennis is the Linux account to use. If you add --dry-run to the rsync command, you can check syntax without actually copying anything. Change source and destination directories as needed.

Use sshpass to Send User Password to rsync

The syntax rsync user@host prompts the user for a paassword. We want this rsync to run regularly and unattended, so we need to pass the password for our Linux user to rsync. The utility sshpass does just that. You install sshpass on MacOS with this command:

brew install hudochenkov/sshpass/sshpass

Now you can pass the password to rsync right on the command line with:

/usr/local/bin/sshpass -p "SuperSecretPassword" /usr/local/bin/rsync3 -avzhu --delete --stats /Users/faucherd/Downloads/ dennis@

Create a Backup Script to Run Regularly

Let's create a shell script that we can run regularly in cron. This is my script that backs up my Downloads and my Documents/Personal directories:

# Backup Downloads to MediaLinux
/usr/local/bin/sshpass -p "SuperSecretPassword" /usr/local/bin/rsync3 -avzhu --delete --stats /Users/faucherd/Downloads/ dennis@
# Backup Personal to MediaLinux
/usr/local/bin/sshpass -p "SuperSecretPassword" /usr/local/bin/rsync3 -avzhu --delete --stats /Users/faucherd/Documents/Personal/ dennis@
grep "Number of regular files transferred" /Users/faucherd/Documents/Personal/Programming/rsync/rsync_all.log | mail -s "rsync Log"

I added a few date commands in to log start and end time to my log file. The last line emails status of the 
backup to me.

Tweak MacOS Postfix to Send Emails Through gMail

The mail command in the shell script uses MacOS Postfix to send the email. You need to tweak MacOS Postfix to define the gMail server and your gMail account. I used the excellent tutorial here.

Schedule Your Backup with Launchd

[I had initially scheduled by rsync job in cron, but cron has been deprecated. I was forced to learn MacOS launchd which is the preferred method]

Running scripts from launchd can cause issues if Terminal does not have default write access to the directories you need. Turning your shell script into an app with Mac Automator overcomes this issue.

Create an App with Automator

Launch Automator and choose Application

Search for shell script and drag that into the pane on the right

Choose you shell, type in the path to your shell script

and choose File > Save (Save your new app in Applications)

Open your new app to save permissions for directory access

Now you can use this app name in your new .plist for launchd.

Create a new .plist file for launchd in ~/Library/LaunchAgents. Here is my working .plist that runs my app every hour (3600 seconds). You should be able to modify this to match your new app.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">
<plist version="1.0">
<string>/Applications/ Stub</string>

Load your new plist:

launchctl load ~/Library/LaunchAgents/FaucherRsync.plist

Start your new plist:

launchctl start ~/Library/LaunchAgents/FaucherRsync.plist

Check to see if you have any errors. Anything non-zero is an error:

launchctl list|grep Faucher
- 0 FaucherRsync

Thank You

Thank you for taking the time to read this post. I hope you found it educational as well as helpful. I welcome any feedback.