Spent a fair bit of time figuring this out so here goes in case it’s useful for anyone else.
I wanted to run as root from launchd to backup files owned by multiple users. I am backing up to Wasabi, and also wanted to keep the API and storage keys in Keychain instead of storing them in environment variables, etc.
There appear to be two key requirements to get this to work:
- copy the Keychain entries for duplicacy from the user to the System keychain
- ensure UserName and SessionCreate keys are not set in the plist
You will find setting those keys is often suggested as necessary for accessing Keychain entries through launchd in other instances, but in this case duplicacy fails with a ‘password not found’ error -25308 if they are set.
Here is a sample plist:
<?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>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/opt/X11/bin:/usr/local/sbin</string>
</dict>
<key>Label</key>
<string>com.duplicacy-util.repository-name</string>
<key>ProgramArguments</key>
<array>
<string>/var/root/gobackup.sh</string>
</array>
<key>LowPriorityIO</key>
<false/>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>3</integer>
<key>Minute</key>
<integer>00</integer>
</dict>
<key>Nice</key>
<integer>-20</integer>
<key>ProcessType</key>
<string>Background</string>
</dict>
</plist>
gobackup.sh switches to the repository directory and runs duplicacy as usual.
Because I want to wake my sleeping MacBook with lid closed to run the backup and it doesn’t have an external display attached, I schedule the wakeup in Energy Saver for one minute after launchd time, wait a couple minutes for WiFi to connect while running caffeinate to prevent it going right back to sleep, and then call duplicacy:
#!/bin/bash
/usr/bin/caffeinate -s -t 180 &
sleep 2m
cd /Users
/usr/bin/caffeinate -s /usr/bin/nice /usr/local/bin/duplicacy backup -storage wasabi
Not sure if the -storage flag is needed for this to work. It looks like maybe it is reflected in the Keychain entries. In my case, I initialized the repository and ran an initial backup operation to store the keys in the root user Keychain before copying them to the System keychain by running the following as root:
duplicacy init -e -storage-name wasabi repository-name wasabi://<storage-path>
duplicacy backup -storage wasabi
I’m actually using duplicacy-util which has the benefit of emailing completion reports among other features, and that works as well with .duplicacy-util directory and config in /var/root.