My Blog

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 -R flag 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:22 means that a connection to localhost:2222 on the remote server will be forwarded to localhost:22 on 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 running systemctl status sshd. To start/stop sshd you can use systemctl start sshd and systemctl stop sshd respectively.

    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 -N flag 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.