Example: Scheduling regular backups on macOS

In case it helps anyone else, this is how I run backups on a regular basis on my MacBook.

  1. Use .bashrc or .bash_profile to export any environment variables your restic command may need, for example, the repository password. (This is convenient because it also allows you to get them in any Terminal you start.)

  2. Create a file called ~/Library/LaunchAgents/net.restic.backup.plist with these contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>net.restic.backup</string>
	
	<key>ProgramArguments</key>
	<array>
		<string>/bin/bash</string>
		<string>-c</string>
		<string>source /Users/USERNAME/.bashrc ; restic backup DATA_FOLDER</string>
	</array>

	<key>StandardOutPath</key>
	<string>LOG_FILE</string>
	
	<key>StandardErrorPath</key>
	<string>LOG_FILE</string>
	
	<key>StartCalendarInterval</key>
	<dict>
		<key>Hour</key>
		<integer>22</integer>
		<key>Minute</key>
		<integer>0</integer>
		<key>Weekday</key>
		<integer>3</integer>
	</dict>
</dict>
</plist>
  1. Replace USERNAME with your login username, DATA_FOLDER with the folder to back up (you should put your proper restic command there, actually), and LOG_FILE with the path to the log file to back up. If your env variables are in .bash_profile instead of .bashrc, then make that change too. If your Mac is mobile or backing up over a network, I highly recommend using the --hostname flag; see this thread

  2. This particular script is configured to run every 3rd day of the week (Wednesday; 0 is Sunday, 6 is Saturday) at 10pm. You can change this, of course.

  3. Run launchctl load -w ~/Library/LaunchAgents/net.restic.backup.plist to permanently load the task; the -w persists it through restarts (I think). Note that this will cause your backup to run when the computer is ON. If it is sleeping during the scheduled time, it will run when you log back in. If the computer is OFF, it will skip that particular run. See https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/ScheduledJobs.html for more info.

You can then invoke a backup to test it with launchctl start ~/Library/LaunchAgents/net.restic.backup (no .plist extension – start goes by the Label in the XML doc)

You can use unload -w similarly to stop the scheduled task.

6 Likes

Very useful, thanks ! :+1:

1 Like

Epilogue: If you backup to a network location, and your network interface takes a few moments to come online like mine does, you might want to prepend the command (the third argument to ProgramArguments) with something like sleep 300 to wait 5 minutes before running the backup. However, if your computer powers down before 5 minutes, I don’t know what will happen, but my guess is that the backup will not run for that time period. Still, if you turn on your computer and usually leave it on for more than a few minutes it should help.

I found another blog article on the same topic, so I’m including it here just for reference and diversity, even though it’s a bit like hijacking the thread :stuck_out_tongue:

http://www.jussihuotari.com/2017/01/14/computer-backup-using-restic-on-mac/

Would love to see systemd for macOS! The network-online.target would be of great help here.
This https://blog.slaunchaman.com/2010/07/01/how-to-run-a-launchdaemon-that-requires-networking/ could also be of help if somebody is working on automating macOS restic backups to some network storage.

I have written couple of scripts and launch agents for unmonitored backup. I’d love to get some feedback on it. Should I post it in this thread itself or make another threads? Or maybe start a “script showcase” kind of thread?

@amar No point in creating a separate thread about the same thing, I suggest you just post your scripts here.

Very well. Here it goes:


Purpose: backing up personal data (as of now 5.3GB) from Mac to B2 using two scripts (backup and maintenance) and schedule them both using launch agents.

(All links are from Github)

restic.backup.sh:

  • It has a include file that is fed to --files-from and an exclude file [0].
  • Then it runs check with --with-cache to keep B2 cost low (as it will run 4 times a day)
  • Then it just runs stats and resets all the credential env vars.
  • Every command’s output is appended to a single log file.
  • Frequency: everyday at 0800, 1200, 1600, 2200 (launch agent amar.restic.backup.plist)

restic.maintain.sh:

  • runs forget with --prune keeping last 10, 7 daily, 5 weekly, 12 monthly, and 3 yearly snapshots
  • runs check without cache then prints stats.
  • Same env vars and logging method as the backup script.
  • Frequency: Every Monday and Thursday at 1330 (launch agent amar.restic.maintenance.plist).

[0] Restic file/dir include/exclude files, credentials file, and a file with env vars are as described in this gist here.

Issues and things I have not figured out:

  1. How can I trigger desktop notifications whenever the scripts run (and possibly an email too, with summary of what happened - esp. for fail cases)?
  2. I could not find any option to compress data - did I miss something? (this is a trial backup set – I have actual data set that’s a lot larger than this)
  3. For subsequent backups I would like to see what actually changed i.e.
    • What files/folders were new
    • What were modified (changed/deleted etc)
    • And if that means a little bigger log output, I can live with that. The thing is every backup is adding ~20MB files to repo and I can’t see why (whether it’s the Mail/V5 folder and I wanted to make sure).

Or in general please suggest anything that I should change to make it better, simpler, and more portable.