-
-
Notifications
You must be signed in to change notification settings - Fork 758
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds docker image and associated scripts.
- Loading branch information
1 parent
d7c6399
commit 2ae2bcf
Showing
5 changed files
with
370 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
FROM debian:stretch | ||
|
||
ENV LANG=C.UTF-8 | ||
|
||
COPY ./borg.exe /usr/bin/borg | ||
COPY ./scripts/docker/borgbackup /usr/bin/ | ||
COPY ./scripts/docker/borgserver /usr/bin/ | ||
|
||
ENTRYPOINT ["/usr/bin/borg"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
# Borg Docker Image | ||
|
||
Docker image with [BorgBackup](https://borgbackup.readthedocs.io/en/stable/) client utility and sshfs support. Borg is a deduplicating backup program supporting compresion and encryption. It's very efficient and doesn't need regular full backups while still supporting data pruning. | ||
|
||
## Quick start | ||
|
||
First, pull the image to keep it up to date. Then create and run the borg backup container. In this quick start, the `/etc` and `/home` directories from the host are bind mounted to the container as read only. These are the directories which will be backed up. The backed up data will be stored in the `borg-repo` Docker volume, and the data will be protected with the `my-secret-pw` password. If the host is using SELinux, the `--security-opt label:disable` flag must be used, because we don't want to relabel the `/etc` and `/home` directories while we want the container to have access to them. After the backup is done, data will be pruned according to the default policy and checked for errors. Borg is running in a verbose mode within the container, so the detailed output from backup will be printed. At the end, the container is deleted. This is done by separate `docker rm` command, because the `--rm` option to the `docker run` would remove also the Docker volumes, and we don't want that. Deleting the container and pulling the image from registry every time keeps the container fresh every time the backup is run. | ||
|
||
``` | ||
docker pull borgbackup/borg | ||
docker run \ | ||
-e BORG_REPO=/borg/repo \ | ||
-e BORG_PASSPHRASE=my-secret-pw \ | ||
-e BACKUP_DIRS=/borg/data \ | ||
-e EXCLUDE='*/.cache*;*.tmp;/borg/data/etc/shadow' \ | ||
-e COMPRESSION=lz4 \ | ||
-e PRUNE=1 \ | ||
-v borg-cache:/root/.cache/borg \ | ||
-v borg-repo:/borg/repo \ | ||
-v /etc:/borg/data/etc:ro \ | ||
-v /home:/borg/data/home:ro \ | ||
--security-opt label:disable \ | ||
--entrypoint=/usr/bin/borgbackup \ | ||
--name borg-backup \ | ||
borgbackup/borg | ||
docker rm borg-backup | ||
``` | ||
|
||
### Server side | ||
|
||
To start a borg server: | ||
- generate an ssh-key | ||
- choose where to store ssh details | ||
- choose where to store backup data | ||
|
||
and run the following command: | ||
|
||
``` | ||
docker run \ | ||
-e SSH_KEY=... \ | ||
-v /path/to/ssh/folder:/etc/ssh \ | ||
-v /path/to/local/folder:/backups \ | ||
--entrypoint=/usr/bin/borgserver \ | ||
borgbackup/borg | ||
``` | ||
|
||
## More examples | ||
|
||
Backup docker volumes to remote location (Borg must be running in server mode in that remote location): | ||
``` | ||
docker run \ | ||
-e BORG_REPO='user@hostname:/path/to/repo' \ | ||
-e ARCHIVE=wordpress-$(date +%Y-%m-%d) \ | ||
-e BORG_PASSPHRASE=my-secret-pw \ | ||
-e BACKUP_DIRS=/borg/data \ | ||
-e COMPRESSION=lz4 \ | ||
-e PRUNE=1 \ | ||
-v borg-cache:/root/.cache/borg \ | ||
-v mariadb-data:/borg/data/mariadb:ro \ | ||
-v worpdress-data:/borg/data/wordpress:ro \ | ||
--entrypoint=/usr/bin/borgbackup \ | ||
--name borg-backup \ | ||
borgbackup/borg | ||
``` | ||
|
||
Using sshfs (in case when the Borg is not installed on the remote location): | ||
``` | ||
docker run \ | ||
-e SSHFS='user@hostname:/path/to/repo' \ | ||
-e SSHFS_PASSWORD=my-ssh-password \ | ||
-e BORG_PASSPHRASE=my-secret-pw \ | ||
-e BACKUP_DIRS=/borg/data \ | ||
-e COMPRESSION=lz4 \ | ||
-e PRUNE=1 \ | ||
-v borg-cache:/root/.cache/borg \ | ||
-v mariadb-data:/borg/data/mariadb:ro \ | ||
-v worpdress-data:/borg/data/wordpress:ro \ | ||
--cap-add SYS_ADMIN --device /dev/fuse --security-opt label:disable \ | ||
--entrypoint=/usr/bin/borgbackup \ | ||
--name borg-backup \ | ||
borgbackup/borg | ||
``` | ||
|
||
Using sshfs with ssh key authentification: | ||
``` | ||
docker run \ | ||
-e SSHFS='user@hostname:/path/to/repo' \ | ||
-e SSHFS_IDENTITY_FILE=/root/ssh-key/key \ | ||
-e SSHFS_GEN_IDENTITY_FILE=1 \ | ||
-e BORG_PASSPHRASE=my-secret-pw \ | ||
-e BACKUP_DIRS=/borg/data \ | ||
-e COMPRESSION=lz4 \ | ||
-e PRUNE=1 \ | ||
-v borg-cache:/root/.cache/borg \ | ||
-v borg-ssh-key:/root/ssh-key \ | ||
-v mariadb-data:/borg/data/mariadb:ro \ | ||
-v worpdress-data:/borg/data/wordpress:ro \ | ||
--cap-add SYS_ADMIN --device /dev/fuse --security-opt label:disable \ | ||
--entrypoint=/usr/bin/borgbackup \ | ||
--name borg-backup \ | ||
borgbackup/borg | ||
``` | ||
|
||
Restoring files from specific day to folder on host: | ||
``` | ||
docker run \ | ||
-e BORG_REPO='user@hostname:/path/to/repo' \ | ||
-e ARCHIVE=wordpress-2016-05-25 \ | ||
-e BORG_PASSPHRASE=my-secret-pw \ | ||
-e EXTRACT_TO=/borg/restore \ | ||
-e EXTRACT_WHAT=only/this/file \ | ||
-v borg-cache:/root/.cache/borg \ | ||
-v /opt/restore:/borg/restore \ | ||
--security-opt label:disable \ | ||
--entrypoint=/usr/bin/borgbackup \ | ||
--name borg-backup \ | ||
borgbackup/borg | ||
``` | ||
|
||
Running custom borg command: | ||
``` | ||
docker run \ | ||
-e BORG_REPO='user@hostname:/path/to/repo' \ | ||
-e BORG_PASSPHRASE=my-secret-pw \ | ||
-e BORG_PARAMS='list ::2016-05-26' \ | ||
-v borg-cache:/root/.cache/borg \ | ||
--entrypoint=/usr/bin/borgbackup \ | ||
--name borg-backup \ | ||
borgbackup/borg | ||
``` | ||
|
||
## Environment variables | ||
|
||
Description of all accepted environment variables follows. | ||
|
||
### Core variables | ||
|
||
**BORG_REPO** - repository location | ||
|
||
**ARCHIVE** - archive parameter for Borg repository. If empty, defaults to `"${HOSTNAME}_$(date +%Y-%m-%d)"`. For more info see [Borg documentation](https://borgbackup.readthedocs.io/en/stable/usage.html) | ||
|
||
**BACKUP_DIRS** - directories to back up | ||
|
||
**EXCLUDE** - paths/patterns to exclude from backup. Paths must be separated by `;`. For example: `-e EXCLUDE='/my path/one;/path two;*.tmp'` | ||
|
||
**BORG_PARAMS** - run custom borg command inside of the container. If this variable is set, default commands are not executed, only the one specified in *BORG_PARAMS*. For example `list` or `list ::2016-05-26`. In both examples, repo is not specified, because borg understands the `BORG_REPO` env var and uses it by default | ||
|
||
**BORG_SKIP_CHECK** - set to `1` if you want to skip the `borg check` command at the end of the backup | ||
|
||
**SSH_KEY** - set the ssh key when you start this image in server mode | ||
|
||
### Compression | ||
|
||
**COMPRESSION** - compression to use. Defaults to none. [More info](https://borgbackup.readthedocs.io/en/stable/usage.html#borg-create) | ||
|
||
### Encryption | ||
|
||
**BORG_PASSPHRASE** - `repokey` mode password to encrypt the backed up data. Defaults to none. Only the `repokey` mode encryption is supported by this Docker image. [More info](https://borgbackup.readthedocs.io/en/stable/usage.html#borg-init) | ||
|
||
### Extracting (restoring) files | ||
|
||
**EXTRACT_TO** - directory where to extract (restore) borg archive. If this variable is set, default commands are not executed, only the extraction is done. Repo and archive are specified with *BORG_REPO* and *ARCHIVE* variables. [More info](https://borgbackup.readthedocs.io/en/stable/usage.html#borg-extract) | ||
|
||
**EXTRACT_WHAT** - subset of files and directories which should be extracted | ||
|
||
### Pruning | ||
|
||
**PRUNE** - if set, prune the repository after backup. Empty by default. [More info](https://borgbackup.readthedocs.io/en/stable/usage.html#borg-prune) | ||
|
||
**PRUNE_PREFIX** - filter data to prune by prefix of the archive. Empty by default - prune all data | ||
|
||
**KEEP_DAILY** - keep specified number of daily backups. Defaults to 7 | ||
|
||
**KEEP_WEEKLY** - keep specified number of weekly backups. Defaults to 4 | ||
|
||
**KEEP_MONTHLY** - keep specified number of monthly backups. Defaults to 6 | ||
|
||
### SSHFS | ||
|
||
**SSHFS** - sshfs destination in form of `user@host:/path`. When using sshfs, container needs special permissions: `--cap-add SYS_ADMIN --device /dev/fuse` and if using SELinux: `--security-opt label:disable` or apparmor: `--security-opt apparmor:unconfined` | ||
|
||
**SSHFS_PASSWORD** - password for ssh authentication | ||
|
||
**SSHFS_IDENTITY_FILE** - path to ssh key | ||
|
||
**SSHFS_GEN_IDENTITY_FILE** - if set, generates ssh key pair if *SSHFS_IDENTITY_FILE* is set, but the key file doesn't exist. 4096 bits long rsa key will be generated. After generating the key, the public part of the key is printed to stdout and the container stops, so you have the chance to configure the server part before running first backup | ||
|
||
# Contributor | ||
|
||
The backup script comes from the great work of [pschiffe](https://github.com/pschiffe). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
#!/bin/bash | ||
|
||
set -euo pipefail | ||
|
||
function echoerr { | ||
cat <<< "$@" 1>&2; | ||
} | ||
|
||
function quit { | ||
if [ -n "${SSHFS:-}" ]; then | ||
fusermount -u "$BORG_REPO" | ||
fi | ||
|
||
if [ -n "${1:-}" ]; then | ||
exit "$1" | ||
fi | ||
|
||
exit 0 | ||
} | ||
|
||
if [ -n "${SSHFS:-}" ]; then | ||
if [ -n "${SSHFS_IDENTITY_FILE:-}" ]; then | ||
if [ ! -f "$SSHFS_IDENTITY_FILE" ] && [ -n "${SSHFS_GEN_IDENTITY_FILE:-}" ]; then | ||
ssh-keygen -t rsa -b 4096 -N '' -f "$SSHFS_IDENTITY_FILE" | ||
cat "${SSHFS_IDENTITY_FILE}.pub" | ||
exit 0 | ||
fi | ||
SSHFS_IDENTITY_FILE="-o IdentityFile=${SSHFS_IDENTITY_FILE}" | ||
else | ||
SSHFS_IDENTITY_FILE='' | ||
fi | ||
if [ -n "${SSHFS_PASSWORD:-}" ]; then | ||
SSHFS_PASSWORD="echo ${SSHFS_PASSWORD} |" | ||
SSHFS_PASSWORD_OPT='-o password_stdin' | ||
else | ||
SSHFS_PASSWORD='' | ||
SSHFS_PASSWORD_OPT='' | ||
fi | ||
mkdir -p /mnt/sshfs | ||
eval "${SSHFS_PASSWORD} sshfs -o StrictHostKeyChecking=no ${SSHFS} /mnt/sshfs ${SSHFS_IDENTITY_FILE} ${SSHFS_PASSWORD_OPT}" | ||
BORG_REPO=/mnt/sshfs | ||
fi | ||
|
||
if [ -z "${BORG_REPO:-}" ]; then | ||
echoerr 'Variable $BORG_REPO is required. Please set it to the repository location.' | ||
quit 1 | ||
fi | ||
|
||
# Borg just needs this | ||
export BORG_REPO | ||
|
||
if [ -z "${BORG_PASSPHRASE:-}" ]; then | ||
INIT_ENCRYPTION='--encryption=none' | ||
echoerr 'Not using encryption. If you want to encrypt your files, set $BORG_PASSPHRASE variable.' | ||
else | ||
INIT_ENCRYPTION='--encryption=repokey' | ||
fi | ||
|
||
DEFAULT_ARCHIVE="${HOSTNAME}_$(date +%Y-%m-%d)" | ||
ARCHIVE="${ARCHIVE:-$DEFAULT_ARCHIVE}" | ||
|
||
if [ -n "${EXTRACT_TO:-}" ]; then | ||
mkdir -p "$EXTRACT_TO" | ||
cd "$EXTRACT_TO" | ||
borg extract -v --list --show-rc ::"$ARCHIVE" ${EXTRACT_WHAT:-} | ||
quit | ||
fi | ||
|
||
if [ -n "${BORG_PARAMS:-}" ]; then | ||
borg $BORG_PARAMS | ||
quit | ||
fi | ||
|
||
if [ -z "${BACKUP_DIRS:-}" ]; then | ||
echoerr 'Variable $BACKUP_DIRS is required. Please fill it with directories you would like to backup.' | ||
quit 1 | ||
fi | ||
|
||
# If the $BORG_REPO is a local path and the directory is empty, init it | ||
if [ "${BORG_REPO:0:1}" == '/' ] && [ ! "$(ls -A $BORG_REPO)" ]; then | ||
INIT_REPO=1 | ||
fi | ||
|
||
if [ -n "${INIT_REPO:-}" ]; then | ||
borg init -v --show-rc $INIT_ENCRYPTION | ||
fi | ||
|
||
if [ -n "${COMPRESSION:-}" ]; then | ||
COMPRESSION="--compression=${COMPRESSION}" | ||
else | ||
COMPRESSION='' | ||
fi | ||
|
||
if [ -n "${EXCLUDE:-}" ]; then | ||
OLD_IFS=$IFS | ||
IFS=';' | ||
|
||
EXCLUDE_BORG='' | ||
for i in $EXCLUDE; do | ||
EXCLUDE_BORG="${EXCLUDE_BORG} --exclude ${i}" | ||
done | ||
|
||
IFS=$OLD_IFS | ||
else | ||
EXCLUDE_BORG='' | ||
fi | ||
|
||
borg create -v --stats --show-rc $COMPRESSION $EXCLUDE_BORG ::"$ARCHIVE" $BACKUP_DIRS | ||
|
||
if [ -n "${PRUNE:-}" ]; then | ||
if [ -n "${PRUNE_PREFIX:-}" ]; then | ||
PRUNE_PREFIX="--prefix=${PRUNE_PREFIX}" | ||
else | ||
PRUNE_PREFIX='' | ||
fi | ||
if [ -z "${KEEP_DAILY:-}" ]; then | ||
KEEP_DAILY=7 | ||
fi | ||
if [ -z "${KEEP_WEEKLY:-}" ]; then | ||
KEEP_WEEKLY=4 | ||
fi | ||
if [ -z "${KEEP_MONTHLY:-}" ]; then | ||
KEEP_MONTHLY=6 | ||
fi | ||
|
||
borg prune -v --stats --show-rc $PRUNE_PREFIX --keep-daily=$KEEP_DAILY --keep-weekly=$KEEP_WEEKLY --keep-monthly=$KEEP_MONTHLY | ||
fi | ||
|
||
if [ "${BORG_SKIP_CHECK:-}" != '1' ] && [ "${BORG_SKIP_CHECK:-}" != "true" ]; then | ||
borg check -v --show-rc | ||
fi | ||
|
||
quit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#!/bin/bash -eux | ||
if [ -n "${SSH_KEY:-}" ]; then | ||
dpkg-reconfigure openssh-server | ||
sed -i \ | ||
-e 's/^#PasswordAuthentication yes$/PasswordAuthentication no/g' \ | ||
-e 's/^PermitRootLogin without-password$/PermitRootLogin no/g' \ | ||
/etc/ssh/sshd_config | ||
if [[ $(ls /etc/ssh-keys/ssh_host_*) ]]; then | ||
echo "Already initialized." | ||
else | ||
echo "Initializing ssh-keys folder..." | ||
cp /etc/ssh/ssh_host_* /etc/ssh-keys | ||
fi | ||
chmod 400 /etc/ssh-keys/ssh_host_* | ||
sed -i 's|/ssh/|/ssh-keys/|' /etc/ssh/sshd_config | ||
sed -i '/^#HostKey/s/^#//' /etc/ssh/sshd_config | ||
sed -e "s#SSH_KEY#${SSH_KEY}#g" /home/borg/authorized_keys.sample > /home/borg/.ssh/authorized_keys | ||
chown borg:borg /home/borg/.ssh/authorized_keys | ||
exec /usr/sbin/sshd -D | ||
else | ||
echo "You need to give an SSH_KEY env variable" | ||
quit | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#!/bin/bash -eux | ||
|
||
echo "Building docker image for borg version ${TAG}..." | ||
|
||
vagrant scp stretch64:/vagrant/borg/borg.exe . | ||
docker build --pull -t borgbackup/borg:${TAG} . | ||
docker tag borgbackup/borg:${TAG} borgbackup/borg:latest | ||
|
||
echo "Running smoke test..." | ||
docker run borgbackup/borg --version | ||
|
||
echo "Login and publishing the docker image..." | ||
docker login | ||
docker push borgbackup/borg:${TAG} | ||
docker push borgbackup/borg:latest |