I maintain several Ubuntu systems and needed a simple bash script
that would backup / mirror these machines. Google pointed me to
rsync
. This article describes what I did with it.
Synopsis
remote_mirror
is a bash function that calls
rsync
under the hood. For example, the following mirrors
192.168.1.102:/etc
into
/backup/mirror/192.168.1.102/etc
.
remote_mirror 192.168.1.102 /etc
Here is its output:
mirror@dl-desktop:~$ remote_mirror 192.168.1.102 /etc
[2025-02-15 13:28:57] [remote_mirror] 192.168.1.102 /etc
[2025-02-15 13:28:57] [rsync] receiving incremental file list
[2025-02-15 13:28:57] [rsync] etc/openvpn/openvpn-status.log
[2025-02-15 13:28:58] [rsync]
[2025-02-15 13:28:58] [rsync] sent 511 bytes received 157,592 bytes 105,402.00 bytes/sec
[2025-02-15 13:28:58] [rsync] total size is 14,464,271 speedup is 91.49
Below, note that we require sudo
, as find
alone would emit “Permission denied” warnings.
mirror@dl-desktop:~$ sudo find /backup/mirror/192.168.1.102/etc -type d | sort
/backup/mirror/192.168.1.102/etc
/backup/mirror/192.168.1.102/etc/acpi
/backup/mirror/192.168.1.102/etc/acpi/events
/backup/mirror/192.168.1.102/etc/alternatives
...
Calls to remote_mirror
, and its local equivalent
local_mirror
, are collected in a batch script which is
called by cron
once a day. This happens on a local machine
where /backup
is mounted to an external hard drive.
Preparations
The crux of our problem is multifold:
- the process must preserve file and directory ownership;
- it must be exhaustive and complete with respect to file and directory permissions;
- it cannot require manual entry of passwords;
- it takes place in a secure way
To handle this, we create a mirror
user account on each
machine. Anticipating ssh
, we use ssh-copy-id
so that the local mirror
user may access remote
mirror
accounts without need for a password.
To read/write files with arbitrary owners and permissions will
require privilege escalation. The simplest way forward is to work with
sudoers
. Specifically, we allow all mirror
accounts to run /usr/bin/rsync
with the
NOPASSWD
modifier. This takes the following form – use
visudo
:
mirror ALL=(ALL) NOPASSWD: /usr/bin/rsync
rsync parameters
Running as local mirror
, the rsync
call
associated with the example looks like this:
sudo \
rsync -av \
-e "sudo -u mirror ssh" \
--relative \
--delete \
--rsync-path="sudo rsync -a" \
192.168.1.102:/etc /backup/mirror/192.168.1.102
Breaking this down:
The initial sudo
ensures that we can write files with
arbitrary ownership and permissions.
The -e "sudo -u mirror ssh"
specifies a remote shell
spawned by local mirror
which will be able to
ssh
without a passowrd.
--relative
will preserve the full source pathd. Without
it, remote_mirror 192.168.1.102 /var/lib
would get mapped
to /backup/mirror/192.168.1.102/lib
.
--delete
imposes mirror-like sematics.
--rsync-path="sudo rsync -a"
ensures that we can read
files with arbitrary ownership and permissions.
loggable
We provide logger
and timestamp
functions
to faciliate logging.