First of all make sure that rsync is installed on the server: apt install rsync
Create a backup user, for example backup1
(in ubuntu there is already a user named backup
):
useradd backup1 -m
ls -al /home/backup1/
Create a ssh key-pair for this user:
ssh-keygen -t ecdsa -P '' -q -f key1
ls -l key1*
cat key1
cat key1.pub
Add the public key to /home/backup1/.ssh/authorized_keys
:
mkdir -p /home/backup1/.ssh
chown backup1: /home/backup1/.ssh
chmod 700 /home/backup1/.ssh
cat key1.pub >> /home/backup1/.ssh/authorized_keys
chown backup1: /home/backup1/.ssh/authorized_keys
chmod 600 /home/backup1/.ssh/authorized_keys
ls -al /home/backup1/.ssh/
cat /home/backup1/.ssh/authorized_keys
Try to login with this key:
ssh -p 22 -i key1 backup1@localhost
You should be able to login without a password.
Try to copy something:
mkdir -p /home/backup1/test1
touch /home/backup1/test1/file1.txt
touch /home/backup1/test1/file2.txt
ls -al /home/backup1/test1
rsync -a -e "ssh -p 22 -i key1" backup1@localhost:~/test1 .
ls -al test1
Let’s find out the command that the client is sending to the server through SSH.
Let’s try the same rsync command again, with the added SSH switch -v
(verbose):
rsync -a -e "ssh -p 22 -i key1 -v" backup1@localhost:~/test1 .
Then let’s look for the debug line that says “Sending command”:
rsync -a -e "ssh -p 22 -i key1 -v" backup1@localhost:~/test1 . 2>&1 | grep "Sending command"
It should be something like this:
rsync --server --sender -logDtpre.iLsfxC . ~/test1
We can restrict the SSH key key1
to execute only this command and nothing else.
For this we need to add something like this before the public key on /home/backup1/.ssh/authorized_keys
:
command="rsync --server --sender -logDtpre.iLsfxC . ~/test1" ecdsa-sha2-nistp256 AAAAE2Vj....
To make it even more secure, we can also add the options no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding
. The file /home/backup1/.ssh/authorized_keys
now should look like this:
command="rsync --server --sender -logDtpre.iLsfxC . ~/test1",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMbMdR9uW4SMeinpVvr6UQZaFybkiVZxm2DRYxFlCuxHchpTMGR7U4gZGZwY4D5LQDDy1Py4TWSsEizda4LecgQ= root@server
Let’s check that now we cannot login with key1
anymore, but we can still use it to rsync
:
ssh -p 22 -i key1 backup1@localhost # should fail
rm -rf test1
rsync -a -e "ssh -p 22 -i key1" backup1@localhost:~/test1 .
ls -l test1
rm -rf test1
rsync -a -e "ssh -p 22 -i key1" backup1@localhost: .
ls -l test1
Install bindfs
:
apt list bindfs
apt show bindfs
apt install bindfs
Create mount directories:
mkdir -p /mnt/backup-server/scripts
mkdir -p /mnt/backup-server/apps
Add these lines to /etc/fstab
for mounting directories read-only:
/opt/docker-scripts /mnt/backup-server/scripts fuse.bindfs perms=0000:u=rD,force-user=backup1,force-group=nogroup 0 0
/var/ds /mnt/backup-server/apps fuse.bindfs perms=0000:u=rD,force-user=backup1,force-group=nogroup 0 0
Since we are using docker-scripts for installing and managing apps, these two directories
are what we need to backup: /opt/docker-scripts
and /var/ds
.
Mount them:
mount -a
ls -al /mnt/backup-server/scripts
ls -al /mnt/backup-server/apps
Test that they are read-only:
sudo -u backup1 ls -al /mnt/backup-server/scripts
sudo -u backup1 touch /mnt/backup-server/scripts/test1.txt
For convenience, we can combine the command and the key in a bash script named backup-server.sh
that looks like this:
#!/bin/bash
server=127.0.0.1
port=22
cd $(dirname $0)
rsync -a -e "ssh -p $port -i $0" backup1@${server}: .
exit 0
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIGHMv+mlPZg/V6TmLADsfZcpMRcfxykJGzXAF65tuQ4AoAoGCCqGSM49
AwEHoUQDQgAExsx1H25bhIx6KelW+vpRBloXJuSJVnGbYNFjEWUK7EdyGlMwZHtT
iBkZnBjgPktAMPLU/LhNZKwSLN1rgt5yBA==
-----END EC PRIVATE KEY-----
Let’s try it:
chmod 700 backup-server.sh
rm -rf test1/
./backup-server.sh
ls -l test1/
Now we can move this script to the client (backup server), making sure to set
the proper values for the variables server
and port
, and it should work.
Let’s also fix the directory on the server that is being backed up. We should edit
/home/backup1/.ssh/authorized_keys
and change ~/test1
to /mnt/backup-server
On the client (computer that is receiving the backup), let’s place the script backup-server.sh
on a directory like /var/backup
:
mkdir -p /var/backup
mv backup-server.sh /var/backup/
cd /var/backup/
./backup-server.sh
Let’s also create a cron job that runs this script periodically each week:
cat <<EOF > /etc/cron.d/backup-server
# backup the server each tuesday
0 0 * * TUE root /var/backup/backup-server.sh
EOF