I make frequent backups to a local drive which I want to sync daily to a remote server.
The target server is configured for SSH key (no password) access only. Since my primary SSH key for that server is passphrase-protected, I've created a second SSH key (not passphrase protected) + user to use for unattended backups - this way I do not have to be present to enter my passphrase when cron runs.
I'm using cron and rsync, and all of the commands work individually, but fail when combined.
The furthest I've got while troubleshooting is running
env -i sh -c "rsync -lrstRO --delete --exclude 'lost+found' /Backups/auto-daily-backups/./ [email protected]:/backups/desktop/"
which returns the error
Permission denied (publickey).
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(226) [sender=3.1.0]
Any tips on how to troubleshoot this further?
Here's what I've tried so far and I'm out of ideas:
- Cron is definitely running
ps aux | grep cron
Nothing unusual in /var/log/syslog
Sep 7 13:22:01 desktop CRON[6735]: (tom) CMD (sh /home/tom/Documents/Scripts/offsite-backup)
SSH in Terminal to remote server as the backup user works
ssh [email protected]
- Running the command in Terminal works perfectly
rsync -lrstRO --delete --exclude 'lost+found' /Backups/auto-daily-backups/./ [email protected]:/backups/desktop/
Manually specifying the path to the backups-user key has no effect
rsync -lrstRO --delete --exclude 'lost+found' -e 'ssh -i /home/tom/.ssh/backups-only' /Backups/auto-daily-backups/./ [email protected]:/backups/desktop/
Replacing the non-functioning command with a simple test command works
echo "Hello world" > ~/Desktop/test.txt
Shouting/swearing at the computer had no effect (but made me feel better temporarily).
Edit 1:
Here's my crontab file and the script it calls.
...
# m h dom mon dow command
MAILTO=""
* * * * * sh /home/tom/Documents/Scripts/offsite-backup
and
#!/bin/bash
rsync -lrstRO --delete --exclude 'lost+found' /Backups/auto-daily-backups/./ [email protected]:/backups/desktop/
Edit 2:
Just to clarify, /var/log/auth.log
on the target server contains the line Sep 11 08:23:01 <hostname> CRON[24421]: pam_unix(cron:session): session closed for user root
This is confusing because I'm no longer running cron every minute locally, but a new entry still appears every minute in the server logs. Crontab files for all users (including root) on the server are empty & do nothing.
Also, user 'backups-only' was created only on the server and with limited rights, with a dedicated SSH key copied to my desktop machine. I'm assuming this is the way to go because everything works when running the commands manually.
The crontab file posted above is for me, user 'tom' on my desktop machine. My intent is to have it call the script which should log in to the server as user 'backups-only'. I just tried running the backup script (rather than the command inside it) and it successfully connected & worked. I ran it on my desktop as user 'tom', same user who created the cron job that won't work. Here's the output from the server log corresponding with that successful login
Sep 11 08:35:31 <hostname> sshd[25071]: error: Could not load host key: /etc/ssh/ssh_host_ed25519_key
Sep 11 08:35:32 <hostname> sshd[25071]: Accepted publickey for backups-only from <desktop IP> port 54242 ssh2: RSA e2:e6:07:27:c1:continues...
Sep 11 08:35:32 <hostname> sshd[25071]: pam_unix(sshd:session): session opened for user backups-only by (uid=0)
Sep 11 08:35:32 <hostname> systemd-logind[638]: New session 12 of user backups-only.
Sep 11 08:36:00 <hostname> sshd[25133]: Received disconnect from <desktop IP>: 11: disconnected by user
Sep 11 08:36:00 <hostname> sshd[25071]: pam_unix(sshd:session): session closed for user backups-only
Since everything is working fine from the command line, the error
Permission denied (publickey)
means that the SSH part ofrsync
is using a different identity file than the specified username.From Jan's comment on the original question, we can specify the identity file in the
rsync
command using-e 'ssh -i /path/to/identity.file' ...
.Using the below command to start off with a fresh environment in cron and specifying the complete path to the file apparently solves the issue:
I'm still really interested in this finding. It probably has to do with cron, the fact that it starts with minimal environment variables, and the ssh-agent. I'll be setting up the same scenario ina a couple of days to test it out and report back.
I just have solved this problem that has kept me busy ..
Unable to connect in RSYNC over SSH, despite having stipulated the identity for SSH ...Nothing is done ... Rsync says "permission denied" and ssh tells me "read_passphrase: can not open /dev/tty: No device or address of this type"
But I read a post that explained that the crontab has its own environment that is not the same as root. I already knew that but I did not understand the impact it could have on SSH when using the SSH-AGENT
But my SSH key exchanges are done with PassPhrase ... so if the environment is different and my RSYNC over SSH expects a passphrase that can not be entered => SSH debug info also indicate the error:
On my machine I use "Keychain" to have the SSH agent launched so I do not have to reenter the passphrase every time I try a remote connection. Keychain generates a file that contains the following information
==> The SSH-AGENT command returns the same info.
So, in the end, it is these information related to the current session that allow future authentications of the current session, without the need to enter the passphrase because already done previously and memorized ...
==> The solution is there ... it is enough in the script launched by the crontab, and to "source" the file containing this information or to do it on the command line ds the crontab ...
=> With this sourcing, no more worry. The information of SSH_AUTH_SOCK and SSH_AGENT_PID are loaded in the environment of the Crontab and are therefore known, the RSYNC over SSH works without any problem.
It has kept me busy but now, it works :)
Caveat for those who use SSH Agent Forwarding:
If you see this behaviour when debugging a script on a remote host, it's because even with the
-e "ssh -i /path/to/key"
flag, ssh will use your local (forwarded) key rather than the one on the server.Concrete example: I have a script on the dev server that pulls in data from the "data server" using rsync over ssh. When I log into the dev server and run it, all is well, but when running from cron, I get the permission denied. Adding some verbosity to the SSH process (flag
-vv
) I noticed the following:What clued me off here is that by pure chance, I happen to have a different username on the local host ("nighty") than on the dev server ("juanr").
Notice how it marks the key on the dev server as "explicit", but still uses the forwarded key from my laptop to log in. Doing an
ssh-copy-id
at this point resolves nothing, because it simply reinstalls the forwarded key rather than the one from the dev server. If you use ssh-copy-id with agent forwarding, you need to specify which key to install with the -i flag:ssh-copy-id -i ~/.ssh/id_rsa.pub user@host
.A little late to the party, but I had the same issue. Local user
crontab -l
showed my daily backup task:Worked when I called
/repos/local-bin/backup-backups daily-6
directly. Worked when I called the underlyingrsync
command by itself. Worked when Issh
-ed into the systems I was attempting to back up.ssh-add -l
showed my environment's agent/keychain had the keys I needed stored properly and readily available.So, following the advice of the main answer, I added
env
to/repos/local-bin/backup-backups
, made the cron task run immediately, copied the output fromenv
, addedexport
before each of the lines, opened up a new terminal, ranenv -i sh
, and pasted theexport
commands into it. Then I ran myssh
command from earlier and it failed. Finally! I noticed that the cron environment was receiving a pid for an ssh agent, though, so it should be working...I ran
ssh-add -l
, saw that the latest SSH keys I created weren't added to this environment's agent/keychain... but some of my other keys were?? Which is weird, because it was working with the agent I was using outside of this environment... oh wait! I'm using KDE's wallet/agent outside of this (my desktop) environment, and using ssh-agent directly inside of this environment (my terminal environment)! So I pressed Ctrl+Alt+F2 to drop out of KDE, ranssh-add -l
, saw that it, too, was missing the keys I needed, and ran myadd-ssh-keys
script. Normally this is done automatically around boot/login time, but these were newly minted SSH keys that needed to be added to both my KDE keychain (which I had done properly) and my non-KDE ssh-agent (which I forgot to do). Hopefully this helps someone else avoid a few hours of hair pulling :)Have you already tried the old trick of cleaning up the hosts files? I mean:
It's worth trying as ssh will rebuild it and you will get rid of stale stuff. You can of course also remove the parts belonging to a given IP / Host.
More questions: Is your cron job running under your UID or is it running as user cron or root?
Use the
rrsync
script together with a dedicated ssh key as follows:REMOTE server
LOCAL computer
REMOTE computer
Prepend to the newly added line the following
So that the result looks like
LOCAL
Put in your
crontab
the following script withx
permission:Source: http://www.guyrutenberg.com/2014/01/14/restricting-ssh-access-to-rsync/
To try and debug add to the ssh part "ssh -v" this way you can get verbose mode with some helpful information.
Edit: From the man page:
I think you haven't configured the sshd_config file properly. Verify that
PermitRootLogin yes
andPubkeyAuthentication yes
for remote maintenance.