This repository helps setting up backups using borgmatic on a given server, using docker-compose
.
It includes a borgmatic-exporter
container to export metrics for Prometheus.
The metrics are written to a text file in ./data/borgmatic-exporter/metrics/
, ready to be fed to a node-exporter textfile collector.
This repository is to be cloned to, say, /data/app-borgmatic
.
By default, Borgmatic expects a configurations files inside /etc/borgmatic.d/
.
This directory is bind-mounted to ./config/borgmatic.d/
, so that the configuration can be added by hand.
It is possible to use multiple configuration files with different configuration values, to backup different parts of the server with a different backup policy. This is for example useful to apply different retentions for logs and backup dumps.
To use this, just add several .yaml
files inside ./config/borgmatic.d/
.
Each invocation of borgmatic
will apply these files independently, in sequence.
-
Be root on the server
-
Clone this repo to
/data/app-borgmatic
. -
Create an SSH keypair for backups, without passphrase, and without overwriting existing keys:
yes n | ssh-keygen -f ~/.ssh/id_borgmatic -N ''
-
Authorize the key on backup server. We're not using
ssh-copy-id
because some Ubuntu versions don't have SFTP mode ofssh-copy-id
, which is needed by Hetzner's storage boxes.Note: Adding the
command=...,restrict
part to the line containing the key prevents SFTP/SSH use for anything other than remote borg commands, which helps mitigate the situation where an attacker completely compromises the server:
sftp -P <port> -o StrictHostKeyChecking=accept-new <user>@<host> << EOF
mkdir .ssh
touch -ac .ssh/authorized_keys
get .ssh/authorized_keys /tmp/authorized_keys
!grep -q "$(cat /root/.ssh/id_borgmatic.pub)" /tmp/authorized_keys || echo 'command="borg serve --umask=077 --info",restrict' $(cat /root/.ssh/id_borgmatic.pub) >> /tmp/authorized_keys
put /tmp/authorized_keys .ssh/authorized_keys
!rm /tmp/authorized_keys
bye
EOF
Additional restrictions can be set, to restrict Borg to specific repositories, or force append-only mode:
command="borg serve --umask=077 --info --append-only --restrict-to-repository /home/something.borg/ --restrict-to-repository /home/something-else.borg/",restrict ssh-rsa ...
- Create
./config/borgmatic.d/*.yaml
file(s) from the provided example:
cp config.example.yaml config/borgmatic.d/config.yaml
Or if using multiple configuration files:
cp config.example.yaml config/borgmatic.d/main.yaml
cp config.example.yaml config/borgmatic.d/something.yaml
-
Modify it/them...
-
MAKE SURE TO
chmod
THE RESULTING FILE(S), it/they will contain the passphrase:
for f in config/borgmatic.d/*.yaml; do
chown root: "$f"; chmod 600 "$f"
done
- Create a
docker-compose.override.yml
, and modify as needed:
cp docker-compose.override.example.yml docker-compose.override.yml
-
Crontabs for both borgmatic and borgmatic-exporter are set using environment variables.
-
Start the containers:
docker compose up -d
- Initialize the borg repository (multiple repositories will be initialized as defined in configuration files):
docker compose exec borgmatic borgmatic init --encryption repokey
# if append-only is wanted:
docker compose exec borgmatic borgmatic init --encryption repokey --append-only
The repository encryption uses repokey, which stores the encryption in the repository, and uses the passphrase from the config file for decryption. This means there are two items you should keep somewhere safe:
- the passphrase
- the key, needs to be exported:
docker compose exec borgmatic borgmatic key export
yes, that's two borgmatic borgmatic
in a row: the first is the docker-compose
service, the second issues a borgmatic
command within that container.
To be able to use Borg's FUSE mount capacities, we need to add some settings to the docker-compose
file.
These are bundled in docker-compose.restore.yml
, including a volume mounted to a location on the host for restored files to go.
So to restore backups:
- Stop the running
borgmatic
container:
docker compose down
-
Modify the
.env
to usedocker-compose.restore.yml
(the line is commented) -
Start the new restore container:
docker compose up -d
- Run a shell on the container and mount needed archive(s)
docker compose exec borgmatic bash
borgmatic mount --archive latest --mount-point /mnt
- Copy/restore needed files to the bind mount defined in
docker-compose.restore.yml
:
cp /mnt/data/backups/foo /restore
- Unmount, exit and remove the restore container:
umount /mnt && exit
docker compose down
- Don't forget to change the
.env
back to what it was, and to start the borgmatic container again.
As long as you have the passphrase and SSH key for the repository, you can inspect/export/mount the borgmatic repository from any machine.
Just install Borgmatic (using this repo or locally on your machine) and use the same configuration file(s) as the one configured for the client server.
You then have access to, for example:
borgmatic list
borgmatic info
borgmatic extract ...
borgmatic mount ...
Metrics are written to a text file, ready to be included in node-exporter
through its textfile
collector.
You will need to edit the node-exporter
's docker-compose.yml
to add a volume and a matching command argument:
volumes:
- ...
- /data/app-borgmatic/data/borgmatic-exporter/metrics:/data/borgmatic-metrics:ro
command:
- "--collector.textfile.directory=/data/borgmatic-metrics"
The syntax when running a borgmatic
or borg
command inside a container implies multiple borgmatic
next to each other.
The first borgmatic
is the service name, the second is the borgmatic
command from inside the container.
Here are some examples:
- Run
borgmatic
inside theborgmatic
container:
docker compose exec borgmatic borgmatic ...
- If multiple config files and/or repositories are set, you will need to specify which repository for some commands:
docker compose exec borgmatic borgmatic list --repository foo
- If a
borg
command isn't natively handled byborgmatic
, you can issue theborg
subcommand to arbitrarily run aborg
command. This has the advantage of using the borgmatic configuration, simplifying the underlyingborg
command:
docker compose exec borgmatic borgmatic borg ...