Dec 12, 2020

Backups with restic and docker

Recently I was looking for a backup solution for my dockerized Nextcloud instance. Beside the common well-established but aged tools like borg backup or duplicitiy I found duplicati and restic. At first duplicati seemed very promising. The software comes with an easy to use web interface for configuring and scheduling backup jobs. However, during a initial test run the backup process freezed while trying to analyze the vast number of thumbnails Nextcloud created. Some Github Issues also state that duplicati does not perform well at large file counts. Therefore I decided to give restic a try. Restic is a command line tool which, I my opinion, is well documented and under active development. It supports encryption by design and many different endpoints e.g. AWS S3 or Backblaze B2. Furthermore resitc does have an official Dockerfile and the latest version can be found in the DockerHub.

Backup with restic

At first one must create an empty repository. Using the pulled or self-built docker image you can run this command to initialize the repository:

1
2
3
4
5
6
docker run --rm -ti \
        -e B2_ACCOUNT_ID="$B2_ACCOUNT_ID" \
        -e B2_ACCOUNT_KEY="$B2_ACCOUNT_KEY" \
        -e RESTIC_REPOSITORY="$RESTIC_REPOSITORY" \ # b2://......
        -e RESTIC_PASSWORD="$RESTIC_PASSWORD" \
        restic/restic init

I wrapped this command into a bash function. A .env file provides the environment variables. In case you also want to load an .env file in a bash script you can simply do it by using the command source config.env. Please do not forget to note the passphrase, since you won’t be able to restore your files in case you lose it.

Performing a first backup is quite easy:

1
2
3
4
5
6
7
docker run --rm -ti \
        -v $NEXTCLOUD_FOLDER:/data/nextcloud:ro \
        -e B2_ACCOUNT_ID="$B2_ACCOUNT_ID" \
        -e B2_ACCOUNT_KEY="$B2_ACCOUNT_KEY" \
        -e RESTIC_REPOSITORY="$RESTIC_REPOSITORY" \
        -e RESTIC_PASSWORD="$RESTIC_PASSWORD" \
        restic/restic backup /data

Notice the :ro flag on the bind mount. It ensures that the production data is only mounted in read only mode. After the backup is finished the container destroys itself. If you do not want to create a new container for each command you might want to remove the --rm. Doing so you can run additional restic commands using docker exec. Side note: Docker introduced --mount flag which is more readable than -v. If preferred, you can look up the syntax here: https://docs.docker.com/storage/bind-mounts/.

Restic uses snapshots to incrementally back up data to its repository. Each snapshot can be restored individually using the command restic restore. With restic forget including --prune as parameter, older snapshots can be deleted automatically. For more information see the well documented restic docs.

Currently I have set up a Cronjob on the host system. At nighttime, a shell script gets triggered which temporarily spins up the restic docker container and performing the backup. Overall restic does a great job and is easy to use. However it misses on a compression feature which is under development at the moment.

Some tips on backing up Nextcloud

When backing up Nextcloud make sure to run docker exec --user www-data nextcloud php occ maintenance:mode --on before starting the backup process. It is also advisable to add a little wait time after the command, to make sure that the clients are disconnected. Afterwards the maintenance mode can be turned off using the same command and --off as parameter. For backing up the database, it is recommended to first create a dump of it and then back it up with restic.

backup nextcloud aws s3 backblaze b2