Personal VPS Backups
Introduction
A mechanism that can backup remote folders and databases. The backups should be triggered locally. That is a pull approach.
The problem is, that most tools do a push approach — the remote server pushes its backup to a local machine. Because a push approach is better for enterprise use. I do not have a separate server to do backups on and don’t want to open my local network to the world either.
Using a push approach like a pull approach
One can achieve a pull-like approach by triggering a push backup on the server.
This by itself doesn’t solve the problem that I don’t want to open my local
network to the world though. To tackle this, I open a SSH tunnel with port
forwarding from my local machine to the remote server. The tunnel is initiated
in such a way that the server can reach my local machine using an address like
localhost:2222.
The only requirement on the local machine is that the ssh daemon (sshd) is
started and some credentials are provided to the remote server, so that it can
log into my local machine and push its backup. To negate security risks I
created a user backup on my local machine that has access to a HDD I use for
backups. For this user I set up public key authentication. Now when the server
is compromised, the attacker cannot access any valuable data on my local
machine. Additionally the attacker has to wait for the SSH tunnel to be opened,
which it only is during backups. The only thing the attacker could delete is
the backups on my local machine that are owned by the backup user. So every
now and then one should make a snapshot of a backup that isn’t in reach of this
user.
Building the SSH tunnel
The described SSH tunnel can be opened from the local machine with ssh -N -R 2222:localhost:22 user@host.
The
-Rflag does the port forwarding. The man page of ssh describes the flag as follows:Specifies that connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side.
This is exactly the behavior that I want. The first number specifies the TCP port on the remote server. In my case I want this to be port 2222. The second part of the argument
localhost:22means that a connection tolocalhost:2222on the remote server will be forwarded tolocalhost:22on the local machine. An port 22 happens to be the port where the ssh daemon listens on by default. Make sure the local ssh daemon (sshd) is started though. You can do this by runningsystemctl status sshd. To start/stop sshd you can usesystemctl start sshdandsystemctl stop sshdrespectively.Note that you could access any port on your local machine from your remote server like this. You could for example have a web server running on your local machine using port 80. To access it from your remote server first open the tunnel from your local machine using
ssh -N -R 2222:localhost:80 user@host. Then you can use some http client on you remote server to make http requests to the web server:curl localhost:2222. Port 2222 on the remote server will just forward to port 80 on the local machine.The
-Nflag simply makes ssh not execute any remote commands (like a shell). The man page described this option as useful to do just the port forwarding.
The backup program
I mentioned that I was able to make a push backup feel like a pull-like backup. But what push backup program did I use?
I used a simple backup program called Backupninja. It provides simple configuration files for some simple backup tasks. Configuration files with a .tar suffix pack specified directories with the utility tar. Configuration files with a .pgsql and .mysql suffix run backups of postgresql and mysql/mariadb databases respectively.
These backups are still stored in a specified directory on the remote server. The push them off to your local machine Backupninja provides some options that can be found in the above linked repository. I use a rsync configuration file to push the backup to my local machine.
On Ubuntu servers Backupninja can be installed through the apt package
backupninja.
Creating the config files
Backupninja includes a helper to create configuration files called ninjahelper. This helper leverages a curse based menu and I used it to create the configurations for tar, postgresql and mysql/mariadb. When creating the rsync configuration I couldn’t specify the port to connect to. Ninjahelper wouldn’t let me create a config before verifying the connection to my local machine. So I had to copy the example configuration from here.
You might wonder how Backupninja knows in what order to execute the
configuration files. This is done by prefixing the configurations with 2-digit
numbers. Backupninja starts at the lowest number (00 means disabled though)
and executes the configurations in the order they are listed by the ls
command. For example 15.tar is executed before 20.pgsql is executed. The
.rsync configuration should usually be the highest number because it pushes
everything the previous actions created.