Can’t authenticate using SSH key when running script via launchd

launchdrsyncscriptssh

I have a Bash script that executes an rsync command to sync files with a remote server.

#!/bin/bash
rsync -auvzP  --exclude=.bundle --exclude=node_modules --exclude=tmp  '/Volumes/Norman Data/me/.bash_profile' '/Volumes/Norman Data/me/Documents' --exclude=remote me@example.com:backup/

This works when I run it from the terminal as I have ssh key authentication set up for my user at example.com. However, when launchd calls this script, I get the following error indicating that it cannot find my user's key file or it is invalid:

Permission denied, please try again. Permission denied, please try
again. me@example.com: Permission denied (publickey,password). rsync:
connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at
/BuildRoot/Library/Caches/com.apple.xbs/Sources/rsync/rsync-52/rsync/io.c(453)
[sender=2.6.9] I am specifying my user name in my plist file and when
debugging, the script says it's being run by that same user both when
running it from the terminal and from launchd alike.

My BackupDaemon.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>HOME</key>
        <string>/Volumes/Norman Data/me</string>
    </dict>
    <key>GroupName</key>
    <string>staff</string>
    <key>InitGroups</key>
    <true/>
    <key>Label</key>
    <string>BackupDaemon</string>
    <key>Program</key>
    <string>/Volumes/Norman Data/me/backup</string>
    <key>StandardErrorPath</key>
    <string>/tmp/BackupDaemon.err</string>
    <key>StandardOutPath</key>
    <string>/tmp/BackupDaemon.out</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>16</integer>
        <key>Minute</key>
        <integer>6</integer>
    </dict>
    <key>UserName</key>
    <string>me</string>
</dict>
</plist>

I can't figure out for the life of me what the issue might be or how to even go about further debugging. Any insight anyone has to share will be greatly appreciated. Thx!

Best Answer

So this is what I ended up doing to get it working. For my use case it is sufficient, but I don''t think it's the best solution. Hopefully someone (see @Allan's comments in OP) can come up with a more universal solution.

I added the -e option to my rsync statement which allows you to specify the exact ssh command used.

rsync -auvzP  -e "ssh -i ~/.ssh/id_rsa_scripts" '/Volumes/Norman Data/me/Documents' me@example.com:backup/

The important part in there is ~/.ssh/id_rsa_scripts - I generated a secondary set of keys for that server, with this set having no passphrase. This is different from how I connect to that box via SSH by default and thus why it needed to be specified in the rsync command.

That was the only way I could get it to work when running unattended (as a Global Daemon). Although it is ok under my set of circumstances, a passphrase-less key is not the best idea in many situations, which is why this is not the ** best ** solution.

Hopefully someone can figure out a way to allow launchd to execute a script requiring SSH authentication using keys with a passphrase.