How To Securely Backup Your Website And Database With Tarsnap Inside Docker
This is a step-by-step guide on how to securely back up website files and database on your server with Tarsnap running inside a Docker container. If you need secure cloud backups from your computer to Dropbox or Google Drive, check out Rebel Backup.
Intro
Tarsnap is a secure online backup service. One of its main advantages is that the backups it makes are encrypted with a secret key accessible only to you. This means that neither Tarsnap itself, nor anyone with access to its servers, can decrypt your backups unless they have your secret key. While the backups themselves ensure that you don't lose the important data from your server, the encryption lets you not worry about an attacker getting hold of your backups and accessing the sensitive data inside them.
Tarsnap is ideal for running on a server that hosts a website and a database, allowing you to back up the contents of your database, as well as anything else that you would not want to lose, such as your SSL certificate and configuration files.
We assume you're running your web server and database inside Docker containers, and describe how to set up Tarsnap to run in a container alongside them to make periodic backups.
NOTE: We're in no way affiliated with Tarsnap, other than being a happy customer of the service.
Initial Setup
First you would need a Tarsnap account - follow steps 3 and 4 of the Tarsnap Getting Started guide.
Next you need to generate your secret key. This requires Tarsnap to be installed on the system where the generation is to occur. Since we will be running Tarsnap inside a Docker container, we won't necessarily have (or want) Tarsnap on the server host itself. So here you have two options - either install Tarsnap on the server and generate the key there, placing it into an appropriate location, or install Tarsnap on your local computer, generate the key, and securely copy it to the server.
Installing Tarsnap is covered in step 1 of the Getting Started guide, and step 5 shows how to generate the key itself. You can use scp
or an sftp client to securely copy the key from your computer to the server.
Key Security
This part is really important. You need to store your secret key somewhere safe. If you store it only on your server, and you lose the server for whatever reason, you won't be able to restore your backups. It happens - a cloud provider may accidentally wipe out your VPS; an attacker could purposefully destroy the contents of your server; an rm
command might be fed the wrong arguments during administrative work.
Step 6 of the Getting Started guide lists some good options for keeping your secret key safe. Please use more than one. Store it on multiple systems. Store it encrypted in Dropbox or Google Drive using Rebel Backup. Print it out and put it into several locations. If you're renting out a bank vault, put the printout there too.
Docker Compose Entry
We assume you're using docker-compose to configure your containers. If you're using some other method, adapt the following accordingly.
To define our Tarsnap container, first we have to add a corresponding entry to the docker-compose.yml
file. We will call the container backuper
, and the entry should look like this:
... backuper: build: context: Backuper # LINE A image: backuper # Adjust the image name if needed volumes: - ./Backuper/Main-bin:/Main/bin:ro # LINE B - /PATH/TO/TARSNAP/DATA:/tarsnap:rw # LINE C - /PATH/TO/WEBSITE/DATA:/backup/PATH/TO/WEBSITE/DATA:ro # LINE D - /SOME/OTHER/PATH/TO/SERVER/DATA:/backup/SOME/OTHER/PATH/TO/SERVER/DATA:ro # LINE E - /PATH/TO/DATABASE/BACKUP:/backup/PATH/TO/DATABASE/BACKUP:rw # LINE F ...
The context
line under build
(LINE A) defines the subdirectory containinig a Dockerfile
for the Tarsnap container; in our case the subdirectory is called Backuper
.
Under volumes
, we have several items. We mount a directory with the scripts we will be using (more on that below) in LINE B. The Tarsnap directory from the host, which contains the secret key and cache, is mounted in LINE C. Unlike most other directories, this one as mounted as read-write, because it hosts the Tarsnap cache.
Next we have some data directories from the host (presumably used by your containers) that we want to back up (LINE D and E). Adjust these as needed, and use as many as you need. Note that they all are mounted inside the /backup
directory in the Tarsnap container.
If you're using a database, the important part is to make sure not to mount the live data directory of the database server into /backups
. Doing so will screw up your database backups, making them either corrupt or inconsistent.
Instead, during a backup process, we will be creating a database dump, and mounting that inside /backup
, as illustrated by LINE F. Note that the directory is also mounted read-write, since the dumping will be performed from the Tarsnap container.
Tarsnap Container
Now we have to configure the Tarsnap container. In the docker-compose.yml
configuration file, we've specified the subdirectory for the container as Backuper
. The contents of that directory are as follows:
Backuper/ Main-bin/ back-up-postgres.sh back-up.sh run-tarsnap.sh usr/ local/ etc/ tarsnap.conf crontab Dockerfile install
Let's start with the Dockerfile
, which defines the Tarsnap container. Its contents are as follows:
FROM debian:stretch-slim RUN apt-get update && apt-get -y install wget && apt-get -y install gnupg # -------------------------------------------------------------------------------------------------- # This section (2) is copied from https://github.com/atmoz/tarsnap/Dockerfile and somewhat modified ENV TARSNAP_VERSION 1.0.39 ENV TARSNAP_SHA256 5613218b2a1060c730b6c4a14c2b34ce33898dd19b38fb9ea0858c5517e42082 ENV TARSNAP_MAKE_PACKAGES \ ca-certificates \ make \ gcc \ libssl-dev \ zlib1g-dev \ e2fslibs-dev ENV TARSNAP_RUN_PACKAGES \ locales \ openssl COPY . / RUN /install ENV LANG en_US.UTF-8 ENV LANGUAGE en_US.UTF-8 ENV LC_ALL en_US.UTF-8 # -------------------------------------------------------------------------------------------------- # This section (3) installs the proper postgresql-client # NOTE: For some reason "apt-get -y install gnupg" doesn't work here; doing it at the top works though. # NOTE: --no-check-certificate is required to avoid a GPG error. RUN wget --no-check-certificate -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O- | apt-key add - RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main" | tee /etc/apt/sources.list.d/postgresql.list RUN apt-get update && apt install -y postgresql-client-11 # -------------------------------------------------------------------------------------------------- # This section (4) is copied from our Dockerfile-cron RUN apt-get -y install cron ADD crontab /etc/crontab # NOTE: The stuff after cron lets us pass cron output to docker logs. CMD cron && \ echo -n "" && : >> /var/log/cron.log && \ tail -f /var/log/cron.log
Besides building and installing the Tarsnap client (section 2), we install a PostgreSQL client (section 3), and then install and launch cron
, to run our periodic backups (section 4).
If you're using a different database server, e.g. MySQL, adapt the third section to install the necessary database client.
The install
file is taken from atmoz/tarsnap on GitHub and is responsible for performing the Tarsnap installation inside the container.
The Tarsnap configuration file, under Backuper/usr/local/etc/tarsnap.conf
, has the following important bits:
... cachedir /tarsnap/cache keyfile /tarsnap/key ...
These should match the Tarsnap destination directory used in our docker-compose.yml
file (LINE C).
The crontab
file configures cron to run the backups periodically. In our case it has a single line:
15 0,6,12,18 * * * root /Main/bin/back-up.sh >> /var/log/cron.log 2>&1
This runs the backup script - /Main/bin/back-up.sh
- every six hours, at 00:15, 06:15, 12:15, and 18:15 (6:15 pm). Adjust as needed. If you're unfamiliar with crontab
syntax, you can use the following site to generate a timing configuration for you, and put it before the " root"
part of the line.
The backup script - Backuper/Main-bin/back-up.sh
- is called by cron
to do the backing up itself. For clarity, its job has been split into two different subscripts, though, of course, you can keep everything in a single file. Its contents:
#!/bin/sh echo "Backing up ..." /Main/bin/back-up-postgres.sh /Main/bin/run-tarsnap.sh
As you can see, the backing up is split into two parts. First, we create a dump of the database, and put it inside the /backup
directory. Next, with all the data ready inside /backup
, we run Tarsnap to perform the actual backing up.
The contents of back-up-postgres.sh
:
#!/bin/sh # NOTE: The /backup/PATH/TO/DATABASE/BACKUP must be the same as the destination in LINE F from the docker-compose.yml above. cd /backup/PATH/TO/DATABASE/BACKUP && \ rm -f postgres-dump.inprogress PGPASSWORD="YOUR-DATABASE-ROOT-PASSWORD" pg_dumpall -h postgres -U root > postgres-dump.inprogress rm -f postgres-dump && \ mv postgres-dump.inprogress postgres-dump
In this example we're hardcoding the root password for the database server in the script. This can be improved by passing appropriate environment variables to the container.
If you're using MySQL, you would need to use a similar back-up-mysql.sh
script instead, to dump the contents of your MySQL server.
Finally, the run-tarsnap.sh
script feeds /backup
to Tarsnap:
#!/bin/sh /usr/local/bin/tarsnap -c -f "server-$(date +%Y%m%d-%H%M%S)" /backup
You can adjust the backup file name (server-...
) as needed.
Verifying Your Backups
Once your setup is complete and the cron
job is running, you can verify your backups by listing them and extracting a recent one, as described in the Tarsnap Testing / restoring backups section (at end of the page).
Conclusion
We hope you've enjoyed this article, and although the setup might look a bit elaborate, your server will be properly backed up from now on.
And if you're looking for an easy way to securely back up important files on your computer, try Rebel Backup - it lets you make encrypted backups to Dropbox and Google Drive (which may be more cost-effective compared to Tarsnap if you have a lot of data to back up), uses state-of-the-art encryption, and is a breeze to use.
Written by Vasyl Smyrnov, July 9, 2019