Cron, SSH, Rsync, and a ssh key with a passphrase (Ubuntu)

I recently scheduled some backup tasks on my VPS using backup-manager which is a neat program for this job. Everything is fine for that.
Then I wanted to set up a cron on my home computer to download the backup archives everyday. This wasn’t as easy as it sounded at first.
You might even get those errors:

Permission denied, please try again.
Permission denied, please try again.
Permission denied (publickey,password).
rsync: connection unexpectedly closed (0 bytes received so far) [receiver]
rsync error: unexplained error (code 255) at io.c(635) [receiver=3.0.3]

I need to connect to my VPS using a SSH key that is protected by a passphrase (password). This ssh key is added to my ssh agent (at login time).

The main problem is that cron is run using a restricted environment, meaning it doesn’t give environment variables like SSH_AUTH_SOCK.
This variable is needed by the ssh client in order to communicate with the ssh agent that will provide the information on the ssh key.

Here’s a workaround for it. It’s a quite secure way to fix this.

The technique is to find the socket path in the /tmp directory. Usually for ubuntu, it is /tmp/keyring-*/ssh.
Note that this may not work and might need a little customization if you have multiple ssh-agents running.

So here’s how I do it:

Open your crontab, type:
crontab -e

And add or edit your command to look like mine:

SHELL=/bin/bash
BASH_ENV=/home/YOURUSER/.bashrc
# m    h  dom mon dow   command
  0    9  *   *   *     SSH_AUTH_SOCK="$(find /tmp/keyring*/ -perm 0755 -type s -user YOURUSER -group YOURUSER -name '*ssh' | head -n 1)" /home/YOURUSER/PATH/TO/backup-script >> /home/YOURUSER/backup.log 2>&1

Replace YOURUSER with the concerned user name.

This is quite secure as the find command is very specific with permissions, ownership, type (socket) and names.

Any ideas to improve this are welcome!

11 Replies to “Cron, SSH, Rsync, and a ssh key with a passphrase (Ubuntu)”

  1. I’m trying to get this to work, but my backup.log reads like this:

    Permission denied, please try again.
    Permission denied, please try again.
    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 io.c(635) [sender=3.0.3]
    Permission denied, please try again.
    Permission denied, please try again.
    Permission denied (publickey,password).
    lost connection

    From this I recon that I need to put in the password for the key, but how do I do that for cron?

    Best regards
    Emby

  2. Emby,
    My ssh key is unlocked at login time using seahorse, that might be why I don’t get these errors, so you might have to do that too.
    Try:
    $ ssh yourserver.domain.com
    it will pop up the password prompt window, from there I think there is a checkbox to tell to unlock this key at login time.

  3. Great! It solved my long standing issue. Thanks!

    However, there my be a typo in your command

    find /tmp/keyring*/ -perm 0755 -type s -user YOURUSER -group YOURUSER -name ‘ssh’ | head -n 1

    will not work since the -name is not ssh but socket.ssh

    changing the command to

    find /tmp/keyring*/ -perm 0755 -type s -user YOURUSER -group YOURUSER -name ‘*ssh’ | head -n 1

    did the deal in my hands.

    Thanks again!

  4. Thanks! As a minor update, you can make this more generic using $LOGNAME which under Ubuntu seems to be populated with the username when running a cron job:
    SSH_AUTH_SOCK=”$(find /tmp/keyring*/ -perm 0755 -type s -user $LOGNAME -group $LOGNAME -name ‘*ssh’ | head -n 1)”

    No edits should be needed to migrate between different users.

  5. I’m encountering the same issue on OS X, and I thought I could tweak the SSH_AUTH_SOCK to work on a Mac, but the following seems to have no effect when added to the crontab:

    SSH_AUTH_SOCK="$(find /tmp/launch-* -perm 0700 -type s -user $LOGNAME -group wheel -name 'Listeners' | head -n 1)" && /path/to/command

  6. Thanks for the clue. In Ubuntu 13.04, I had to tweak it to:

    SSH_AUTH_SOCK=$(find /run/user/YOURUSER/keyring*/ -perm 0775 -type s -user YOURUSER -group YOURUSER -name ‘*ssh’ | head -1)

Leave a Reply