Securing rsync with SSH keys

I have been researching quite a bit on how to implement a linux based rsync server which allows passwordless logins from remote systems, constraining them as much as possible.

My goals are:

  • Login using a non-root user
  • Being able to make full backups using fake-super on the server side
  • Constraining the ssh account to rsync only

After having looked at quite a few options such as rssh, I found out that rsync includes a script called rrsync. It can be found at /usr/share/rsync/rrsync or a similar path in /usr/share, depending on your distribution. If you do not have rrsync on your system you can download it here.

It is intended to be used with ssh keys and to be more precise: the command= option of the authorized_keys file.

First let us create a new key-pair on the client and copy the public key to the server:

user@client1:~$ ssh-keygen -f ~/.ssh/id_backup -C "backup/client1"
user@client1:~$ scp ~/.ssh/id_backup.pub backup@server:~/

On the server edit the authorized_keys file in the .ssh folder of your backup user to read:

command="/usr/share/rsync/rrsync  /var/backup/client1/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-rsa AAAA[... your full pubkey here...]

This entry will allow the owner of the corresponding private key to use rsync via ssh being restricted to /var/backup/client1/.

The following example would rsync a full back of client1 to the server:

client1 ~ # rsync -ahvxz --delete --partial --rsync-path='rsync --server --fake-super' --rsh='ssh -i .ssh/id_backup' / backup@server:/

A few things to note about this command line:

  • --rsync-path specifies options for the remote (server) side.
  • You need to have --server before --fake-super, else rrsync will complain.
  • --fake-super will tell the server to store attributes such as file ownership as extended attributes. This means that on the server all files will belong to your backup user, but when you restore them they will once again have their original owner.
  • The remote path is relative to the path specified in your command= option, hence we use / here.

I am using different keys restricted to different paths for different systems to backup. You might want to use some additional options for your rsync client, e.g. excluding paths such as /tmp. I would suggest having a look at the --exclude-from option.