Backup remote Linux systems without root access, using rsnapshot and rsync

Why ?

Rsnapshot is a powerfull rotating system snapshot utility.

Rotations process use hardlinks ; only the changed files are copied, the rest is hard linked to the most recent backup.

Rsnapshot can backup locally and remotly, but it requires remote root access in order to copy all system files, which is not really secure.

How ?

Consider we have several servers to backup, and a central backuping server. Each remote will run a cron task to save local content using rsnapshot. Then, our backuping station will access all remotes using dedicated account, copying backups using Rsync.

You’ll say that the problem is not solved. We still have root files that our dedicated account could’nt access. The trick is that a script would have saved each file permissions, before changing all files access rights in order to allow dedicated account to access it.

Using a dedicated account with restricted rights allows backuping station to access through SSH (using authorized_keys).

Backuping scripts explained


This script directories/files permissions from the state file (run

Then run Rsnapshot.

When done, saves current directories/files permissions into the state file. (run

Finally, set permissions to a special user (snapshot:snapshot) to allow secure remote copy.


if [ $# -ne 1 ];then
   echo "Not enough arguments"
   echo "./ [rsnapshot period]"

if [ -f $scriptsRoot/state ];then
   $scriptsRoot/ $scriptsRoot/state

/usr/bin/rsnapshot $1

$scriptsRoot/ $snapshotRoot > $scriptsRoot/state

/bin/cp $scriptsRoot/state $snapshotRoot

/bin/chown -R snapshot:snapshot $snapshotRoot
/bin/chmod -R 700 $snapshotRoot/*

Save each file permissions to a state file.
my $tree = $ARGV[0];

foreach $file (`/usr/bin/find ${tree}`)
 (undef, $inode, $mode, undef, $uid, $gid, $undef, $size, undef, undef, undef, undef, undef) = stat($file);
 $permissions = $mode & 07777;
 printf "%i:%i:%04o:%i:%i:%s\n", $inode, $size, $permissions, $uid, $gid, $file;

Read state file and apply saved permissions to files.
my $stateFile = $ARGV[0];

open(STATE_IN, "<$stateFile");

foreach $line (<STATE_IN>)
 my ($inode, $size, $permissions, $uid, $gid, $file) = split(':', $line, 6);
 if( -f $file || -d $file)
   #add inode / size check here if desired
   chmod(oct($permissions), $file);
   chown($uid, $gid, $file);


Backuping Server

Runs rsync to a remote system.

if [ $# -ne 4 ];then
   echo "Not enough arguments"
   echo "./syncFromRemote [user host remoteDir backupDir]"


if [ -d $4/$2 ];then
   mkdir $4/$2

rsync -avzH -e ssh $1@$2:$3 $4/$2

Runs all backups and send a report mail.


echo "backup started" > $scriptsRoot/.mailtmp
date >> $scriptsRoot/.mailtmp
du -sh $backupRoot/* >> $scriptsRoot/.mailtmp

$scriptsRoot/ [USER] [HOST] $snapshotRoot $backupRoot

echo "backup done" >> $scriptsRoot/.mailtmp
date >> $scriptsRoot/.mailtmp
du -sh $backupRoot/* >> $scriptsRoot/.mailtmp

mail -s "backup log" < $scriptsRoot/.mailtmp

Install process


All scripts can be found in this archive :

Backuping server


We’ll create a public key and push it to each remote. Using snapshot user, backuping server could connect on each remote.

Create snapshot user

sudo adduser \
 --system \
 --shell /bin/sh \
 --group \
 --disabled-password \
 --home /home/snapshot \

Logon snapshot user

` sudo su snapshot`

Create RSA key

ssh-keygen -t rsa

Copy public key to all remotes using scp

scp .ssh/ user@remote_host:

Script files

Copy and to /home/snapshot/scripts folder.

Setting up cron

Logon snapshot user

sudo su snapshot

Create task (example : each day @ 6am)

sudo crontab -e

0 6 * * * /home/snapshot/scripts/


Setting up Rsnapshot

Install Rsnapshot from apt

sudo apt-get install rsnapshot

Edit config file

sudo vim /etc/rsnapshot.conf

Edit following parameters

Edit rsnapshot config
#backups destination
snapshot_root   /var/cache/rsnapshot/

cmd_cp          /bin/cp

#set intervals (keep 3 daily, weekly and monthly backups)
interval        daily   3
interval        weekly  3
interval        monthly 3

#set directories to backup (trailing slash is mandatory)
#separator MUST BE TAB
backup  /etc/                   localhost/
backup  /home/                  localhost/

Test this config

sudo rsnapshot configtest

Syntax OK

Run a backup manually

sudo rsnapshot daily

Create cron jobs, depending on what you set in rsnapshot.conf (daily @3am, weekly @4am, monthly @4am)

sudo crontab -e

Create crons on remotes
0 3 * * *       /usr/bin/rsnapshot daily
0 4 * * 1       /usr/bin/rsnapshot weekly
0 4 1 * *       /usr/bin/rsnapshot monthly

Create remotes dedicated backup user

create a local user called 'snapshot'

Create user snapshot
sudo adduser \
 --system \
 --shell /bin/sh \
 --group \
 --disabled-password \
 --home /home/snapshot \

copy ssh key from backup server and add it to authorized_keys (We’re talking about the public key we’ve made previously)

Ssh keys
sudo mkdir /home/snapshot/.ssh
sudo cp /home/snapshot/.ssh/authorized_keys
sudo chown -R snapshot:snapshot /home/snapshot/.ssh/
  1. And "that’s it". You can test the whole process before cron runs the scripts.

comments powered by Disqus