Passphrase-less SSH keys allows one to automate remote tasks by not requiring user intervention to enter a passphrase to decrypt the key. While this is convenient, is posses a security risk as the plain key can be used by anyone who gets hold of it to access the remote server. To this end, the developers of SSH allowed to restrict via the .ssh/authorized_keys
the commands that can be executed of specific keys. This works great for simple commands, but as using rsync
requires executing remote commands withe different arguments on the remote end, depending on the invocation on the local machine, it gets quite complicated to properly restrict it via .ssh/authorized_keys
.
Luckily, the developers of rsync foresaw this problem and wrote a script called rrsync
(for restricted rsync
) specifically to ease the restricting keys to be used only for rsync
via .ssh/authorized_keys
. If you have rsync
installed, rrsync
should have been distributed along side it. In Debian/Ubuntu machines it can be found under /usr/share/doc/rsync/scripts/rrsync.gz
. If you can find it there, you can download the script directly from here. On the remote machine, copy the script, unpacking if needed, and make it executable:
user@remote:~$ gunzip /usr/share/doc/rsync/scripts/rrsync.gz -c > ~/bin/rrsync
user@remote:~$ chmod +x ~/bin/rrsync
On the local machine, create a new SSH key and leave the passphrase empty (this will allow you to automate the rsync
via cron). Copy the public key to the remote server.
user@local:~$ ssh-keygen -f ~/.ssh/id_remote_backup -C "Automated remote backup"
user@local:~$ scp ~/.ssh/id_remote_backup.pub user@remote:~/
Once the public key is on the remote server edit ~/.ssh/authorized_keys
and append the public key.
user@remote:~$ vim ~/.ssh/authorized_keys
(Vim tip: Use :r! cat id_remote_backup.pub
to directly insert the contents of id_remote_backup.pub into a new line). Now prepend to the newly added line
command="$HOME/bin/rrsync -ro ~/backups/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding
The command="..."
restricts access of that public key by executing the given command and disallowing others. All the other no-*
stuff further restrict what can be done with that particular public key. As the SSH daemon will not start the default shell when accessing the server using this public key, the $PATH
environment variable will be pretty empty (similar to cron), hence you should specify the full path to the rrsync
script. The two arguments to rrsync
are -ro
which restricts modifying the directory (drop it if you want to upload stuff to the remote directory) and the path to the directory you want to enable remote access to (in my example ~/backups/
).
The result should look something like:
command="$HOME/bin/rrsync -ro ~/backups/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-rsa AAA...vp Automated remote backup
After saving the file, you should be able to rsync
files from the remote server to the local machine, without being prompted to for a password.
user@local:~$ rsync -e "ssh -i $HOME/.ssh/id_remote_backup" -av user@remote: etc2/
To things are needed to be noted:
- You need to specify the passphrase-less key in the
rsync
command (the -e "ssh -i $HOME/.ssh/id_remote_backup"
part).
- The remote directory is always relative to the directory given to
rrsync
in the ~/.ssh/authorized_keys
file.