So today, I was setting up a cronjob on my trusty MacBook Pro. The goal was to backup some folders from a remote Linux server via rsync. The script is simple. It goes something like this:

rsync -avz -e "ssh -i ~/.ssh/my_rsa_keyfile" myuser@myserver:remotedir/ ~/localdir/

Launched by hand, it works seamlessly. Call it from a cron job via crontab, and I get a permission denied error. I then enabled ssh -v option to gather a little intel on what was actually going on. As it turns out, the exact error was:

`read_passphrase: can't open /dev/tty: Device not configured`

Quite puzzling. Long story short, the error message was misleading. It took me an embarrassingly long time to figure out what the real problem was. The identity file I was using has a passphrase, which is saved in macOS Keyring. When the ssh -i command is launched via cron, no Keyring is used. Not unless you explicitly instruct ssh to do. See, my ~/.ssh/config file was something like this:

Host *
    ServerAliveInterval 360
    AddKeysToAgent yes

[...]

Host myserver
    HostName 123.123.123.123
    User myuser

See, in myserver section there was no Usekeychain option. Launching the script interactively worked because of AddkeysToAgent in the general section. It enables the ssh-agent for the current terminal session, for all hosts. But cron jobs, well, they don’t run in the same session, and certainly don’t run the agent. I could eval the agent in the script, of course, but the simplest solution was to update myserver section:

Host myserver
    HostName 123.123.123.123
    Usekeychain yes
    User myuser

Now ssh knows it should use the keychain when resolving myserver RSA key, even when no agent is running. I am not sure why I did not have Usekeychain there; I do have it enabled for other hosts in the same file. As said, I wasted way too much time on this issue. At least, I hope my experience will be useful to someone else, or, more likely, to my future self in a few months or years.