Skip to content

For Maintainers

From the perspective of the recipe maintainer, backup/restore is just more deploy: ... labels. Tools can read these labels and then perform the backup/restore logic.

Tools

Two of the current "blessed" options are, which both implement the backupbot specification

backup-bot-two

backup-bot-two is a recipe which gets deployed on the server, it can perform automatic backups and uses restic. Please see the README.md for the full docs.

abra

abra will read labels and store backups in ~/.abra/backups/... . It also provides an integration for backup-bot-two.

Backup

How to Configure backups

Unless otherwise stated all labels should be added to the main service (which should be named app).

  1. Enable backups for the recipe: You need to enable backups for the recipe by adding the following deploy label:
backupbot.backup=true
  1. Decide wich volumes should be backed up: By default all volumes will be backed up. To disable a certain volume you can add the following deploy label:
backupbot.backup.volumes.{volume_name}=false
  1. Decide which path should be backed up on each volume By default all files get backed up for a volume. To only include certain paths you can add the following deploy label:
backupbot.backup.volumes.{volume_name}.path=/mypath1/foo,/mypath2/bar

Note: You can include multiple paths by providing a comma seperated list Note: All paths are specified relativ to the volume root

  1. Run commands before the backup For certain services like a database it is not reccomend to just backup files, because the backup might end up in a corrupted state. Instead it is reccomended to make a database dump. You can run arbitrary commands in any container before the files are backed up. To do this add the following deploy label to the service on which you want the command being run:
backupbot.backup.pre-hook=mysqldump -u root -pghost ghost --tab /var/lib/foo
  1. Run commands after the backup Sometimes you want to clean up after the backup. You can run arbitrary commands in any container after the files were backed up. To do this add the following deploy label to the service on which you want the command being run:
backupbot.backup.post-hook=rm -rf /var/lib/mysql-files/*

Testing the backup

To test that your backup is configured correctly you can deploy the recipe you are working on in a test app either locally or on a test server.

After the deployment is succesfull run the backup and inspect its content

abra app backup myrecipe.example.com
tar -tf ~/.abra/backups/mybackup

TODO: this is not complete yet

Restore

When restoring an app, it takes the files from a backup and copies them to their correct location. In the case of restoring database tables, you can use the pre-hook & post-hook commands to run the insertion logic.

Pre and Post hooks

To back up some services correctly it involves more than just copying a few files from one location to another. Some services already have specific backup tools that allow taking a coherent snapshot of its data like mysqldump. The pre and post hooks can be used to prepare the files which should get backed up and clean up afterwards.

Here are some examples:

Example 1: Execute simple command

backupbot.backup.pre-hook: "echo 'foo' > /path/to/volume/bar.txt

Example 2: Access environment variable

backupbot.backup.pre-hook: "cat $${POSTGRES_PASSWORD_FILE}"

Example 3: Access secret

backupbot.backup.pre-hook: "cat /var/run/secrets/mysupersecret"
backupbot.backup.pre-hook: 'mysqldump -p"$$(cat /run/secrets/mysupersecret)" mydatabase'

Example 4: Complex script

Sometimes the logic to backup up a service can get quite complex. In that case it might be easier to add a script (via mount or config) inside the container and call that from the pre and post hook:

backupbot.backup.pre-hook: "/scripts/my-pre-backup-scripts"
backupbot.backup.post-hook: "/scripts/my-post-backup-scripts"

Configuration Examples

Mariadb

services:
  db:
    image: mariadb
    volumes:
      - "mariadb:/var/lib/mysql"
    deploy:
      labels:
        backupbot.backup: "true"
        backupbot.backup.pre-hook: "sh -c 'mariadb-dump --single-transaction -u root -p\"$$(cat /run/secrets/db_root_password)\" wordpress | gzip > /var/lib/mysql/dump.sql.gz'"
        backupbot.backup.volume.mariadb.path: "dump.sql.gz"
        backupbot.backup.post-hook: "rm -f /var/lib/mysql/dump.sql.gz"
        backupbot.restore.post-hook: "sh -c 'gzip -d /var/lib/mysql/dump.sql.gz && mariadb -u root -p\"$$(cat /run/secrets/db_root_password)\" wordpress < /var/lib/mysql/dump.sql && rm -f /var/lib/mysql/dump.sql'"

Postgres

version: '3.8'

services:
  db:
    image: "postgres"
    volumes:
      - "postgres:/var/lib/postgresql/data"
    secrets:
      - db_password
    deploy:
      labels:
            backupbot.backup: "true"
            backupbot.backup.pre-hook: "PGPASSWORD=$$(cat $${POSTGRES_PASSWORD_FILE}) pg_dump -U $${POSTGRES_USER} $${POSTGRES_DB} > /var/lib/postgresql/data/backup.sql"
            backupbot.backup.post-hook: "rm -rf /var/lib/postgresql/data/backup.sql"
            backupbot.backup.volume.postgres.path: "backup.sql"

volumes:
  postgres: