Using rsync for backups

A typical SME or SOHO network will have a small number of users' computers containing data that should be backed up, and a file server where backups can be stored.

The server provides restricted access to the users that is just sufficient for them to perform backups. The users can not log in to the server.

The backup solution uses rsync.

One scheme is to implement an rsync server that allows users to connect. It would be configured something like this (/etc/rsyncd.conf):

    comment = Amanda's backups
    path = /home/amanda/backup
    read only = false
    uid = amanda
    git = users

This allows Amanda to backup her data with one command:

$ rsync -aHv Documents server::amanda/amamac

It works but it's insecure: there's no authentication and data is transmitted across the network in clear text. It is possible to set up authentication using a secrets file; the modified configuration would look like this:

secrets file = /etc/rsyncd.secrets
    comment = Amanda's backups
    path = /home/amanda/backup
    read only = false
    uid = amanda
    gid = users
    auth users = amanda

The secrets file must be manually created and set so that it isn't world readable, e.g:

# echo 'amanda:herpassword' > /etc/rsyncd.secrets
# chmod 600 /etc/rsyncd.secrets

Note how the secrets file contains the password in plain text. A much more secure solution would be to use rsync over ssh.

Assuming Amanda can log in to the server (ssh amanda@server), she can also do this:

$ rsync -aHv Desktop amanda@server:backup/amamac

However, we want to impose some restrictions:

  • only allow access to /home/amanda/backup;
  • only allow access by Amanda;
  • prevent Amanda from logging in to a shell.

There are various ways to achieve these things.


The usual way to prevent shell logins is to set the user's shell to /bin/false (e.g. in /etc/passwd) but doing so also prohibits running commands over ssh because it launches the command in the user's shell. This prevents users configured in this way from using rsync.

A Restricted secure shell, rssh is a shell that can be restricted to a few commands, one of which is rsync.

After installing, a new shell is available called /usr/bin/rssh and what it allows can be configured through /etc/rssh.conf. It can be set to allow rsync only and set as the shell for users allowed to use it. The latest version of rssh is 2.3.4 which was released on November 27th, 2012:

$ rssh -v
rssh 2.3.4

Users restricted by rssh should still be able to perform rsync commands like the one above. However, rssh does not work when the server is running rsync version 3.

$ rsync -aHv Desktop user@server:backup
illegal insecure e option

Searching for answers reveal that this is caused by rsync version 3 because it uses a -e argument to specify protocol information. A suggested work-around is to add --protocol=29 to the above command but it doesn't work when the server is running rsync version 3.

The bug has been reported upstream but the maintainer lacks the interest to fix it. Debian has recorded the issue as Bug 491083 and Red Hat has a patch to rectify it. There are patched downstream packages for Debian and Red Hat.

See also Red Hat Bugzilla 880174 and 877279 in reference to an associated security vulnerability CVE-2012-2251.

On Arch Linux, it's in the AUR. Package version 2.3.4-3, although patched, doesn't work. A revised PKGBUILD that uses the Red Hat patch does work, however.

Restricted ssh command

SSH allows the command that a user can run to be restricted by specifying a command= prefix in the user's ~/.ssh/authorized_keys file. The specified command is executed regardless of the user's request. It goes like this:

command="/usr/bin/rsync --server -lHogDtpr . backup" ssh-rsa cMGLbDz8...71FRa MyUser

This example restricts the user's access to their backup directory. To ascertain the exact command, launch rsync from the client with an additional argument to make ssh verbose:

$ rsync -aH -e 'ssh -v' Desktop user@server:backup
debug1: Sending command: rsync --server -lHogDtpr . backup

With the restricted command in place, access is restricted to the specified path regardless of what's specified by the client. The root of the path must exist (e.g. backup but any other path compnenents would be created if they did not exist.

Once the server is configired, the client command does not need to specify the destination path (if it did, it would be ignored):

$ rsync -aH Desktop user@server:

It's also usual to supply further restrictions so that the prefix becomes

command="/usr/bin/rrsync ~/backup",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding

It's also possible to restrict access by source IP address or hostname too.


This would allow the same SSH key to execute different commands when used from different hosts. Hostname lookup is preferable when clients have dynamic IP addresses; it requires the sshd option UseDNS to be enabled in /etc/ssh/sshd_config.

!The default value for UseDNS is no since SSH version 6.8 but it was yes prior to that.

!Note that this scheme requires that the command in authorized_keys is changed if the command issued by the client changes (such as to support different command-line arguments).

This method works when the user's shell is rssh because the executed command is rsync.


If the need to change the command in authorized_keys to match the client command is undesirable, there is an alternative. There's an upstream utility script called rrsync that restricts access to a directory.

!Note that rssh will prohibit running rrsync because it only allows rsync. So both cannot be used together.

Installing rrsync using command= in the user's ~/.ssh/authporized_keys file makes it the only thing that the user can run. It goes like this:

command="/usr/bin/rrsync ~/backup" ssh-rsa cMGLbDz8...71FRa MyUser

The user would then back up like this:

$ rsync -aH Desktop user@server:

Using rrsync removes the need to match the command in authorized_keys to the client command but it doesn't work with rssh.

Daemon over SSH

Another option is to use the rsyncd daemon over SSH. This connects using ssh and launches a per-use daemon for that user. This approach isn't discussed here.