Compare commits

..

6 Commits

Author SHA1 Message Date
Frederik Ring
b558a57de9 Merge pull request #17 from offen/local-prune
Use find instead of mc for pruning local backups
2021-08-20 10:09:46 +02:00
Frederik Ring
278df9b2f7 use find instead of mc for pruning local backups 2021-08-20 10:01:46 +02:00
Frederik Ring
0782af88f4 fix blank variable when creating target 2021-08-19 16:35:21 +02:00
Frederik Ring
f82577fcb5 add prefix option to entrypoint script 2021-08-19 13:55:15 +02:00
Frederik Ring
7f261a54b6 Merge pull request #15 from offen/prune-prefix
Allow passing prefix to limit pruning ops
2021-08-19 13:45:10 +02:00
Frederik Ring
0069faa7fd allow passing prefix to limit pruning ops 2021-08-19 13:41:19 +02:00
6 changed files with 95 additions and 25 deletions

View File

@@ -51,11 +51,12 @@ AWS_S3_BUCKET_NAME="<xxx>"
# **IMPORTANT, PLEASE READ THIS BEFORE USING THIS FEATURE**: # **IMPORTANT, PLEASE READ THIS BEFORE USING THIS FEATURE**:
# The mechanism used for pruning backups is not very sophisticated # The mechanism used for pruning backups is not very sophisticated
# and applies its rules to **all files in the target directory**, # and applies its rules to **all files in the target directory** by default,
# which means that if you are storing your backups next to other files, # which means that if you are storing your backups next to other files,
# these might become subject to deletion too. When using this option # these might become subject to deletion too. When using this option
# make sure the backup files are stored in a directory used exclusively # make sure the backup files are stored in a directory used exclusively
# for storing them or you might lose data. # for storing them or to configure BACKUP_PRUNING_PREFIX to limit
# removal to certain files.
# Define this value to enable automatic pruning of old backups. The value # Define this value to enable automatic pruning of old backups. The value
# declares the number of days for which a backup is kept. # declares the number of days for which a backup is kept.
@@ -71,6 +72,15 @@ AWS_S3_BUCKET_NAME="<xxx>"
# BACKUP_PRUNING_LEEWAY="10m" # BACKUP_PRUNING_LEEWAY="10m"
# In case your target bucket or directory contains other files than the ones
# managed by this container, you can limit the scope of rotation by setting
# a prefix value. This would usually be the non-parametrized part of your
# BACKUP_FILENAME. E.g. if BACKUP_FILENAME is `db-backup-%Y-%m-%dT%H-%M-%S.tar.gz`,
# you can set BACKUP_PRUNING_PREFIX to `db-backup-` and make sure
# unrelated files are not affected.
# BACKUP_PRUNING_PREFIX="backup-"
########### BACKUP ENCRYPTION ########### BACKUP ENCRYPTION
# Backups can be encrypted using gpg in case a passphrase is given # Backups can be encrypted using gpg in case a passphrase is given

View File

@@ -103,32 +103,62 @@ fi
info "Backup finished" info "Backup finished"
echo "Will wait for next scheduled backup." echo "Will wait for next scheduled backup."
prune () { probe_expired () {
target=$1 local target=$1
rule_applies_to=$( local is_local=$2
if [ -z "$is_local" ]; then
mc rm $MC_GLOBAL_OPTIONS --fake --recursive --force \ mc rm $MC_GLOBAL_OPTIONS --fake --recursive --force \
--older-than "${BACKUP_RETENTION_DAYS}d" \ --older-than "${BACKUP_RETENTION_DAYS}d" \
"$target" \ "$target"
| wc -l else
) find $target* -type f -mtime $BACKUP_RETENTION_DAYS
if [ "$rule_applies_to" == "0" ]; then fi
echo "No backups found older than the configured retention period of $BACKUP_RETENTION_DAYS days." }
echo "Doing nothing."
exit 0 probe_all () {
local target=$1
local is_local=$2
if [ -z "$is_local" ]; then
mc ls $MC_GLOBAL_OPTIONS "$target"
else
find $target* -type f
fi
}
delete () {
local target=$1
local is_local=$2
if [ -z "$is_local" ]; then
mc rm $MC_GLOBAL_OPTIONS --recursive --force \
--older-than "${BACKUP_RETENTION_DAYS}d" \
"$target"
else
find $target* -delete -type f -mtime $BACKUP_RETENTION_DAYS
fi
}
prune () {
local target=$1
local is_local=$2
if [ ! -z "$BACKUP_PRUNING_PREFIX" ]; then
target="$target/${BACKUP_PRUNING_PREFIX}"
fi fi
total=$(mc ls $MC_GLOBAL_OPTIONS "$target" | wc -l) rule_applies_to=$(probe_expired "$target" "$is_local" | wc -l)
if [ "$rule_applies_to" == "0" ]; then
echo "No backups found older than the configured retention period of ${BACKUP_RETENTION_DAYS} days."
echo "Doing nothing."
else
total=$(probe_all "$target" "$is_local" | wc -l)
if [ "$rule_applies_to" == "$total" ]; then if [ "$rule_applies_to" == "$total" ]; then
echo "Using a retention of ${BACKUP_RETENTION_DAYS} days would prune all currently existing backups, will not continue." echo "Using a retention of ${BACKUP_RETENTION_DAYS} days would prune all currently existing backups, will not continue."
echo "If this is what you want, please remove files manually instead of using this script." echo "If this is what you want, please remove files manually instead of using this script."
exit 1 else
fi delete "$target" "$is_local"
mc rm $MC_GLOBAL_OPTIONS \
--recursive --force \
--older-than "${BACKUP_RETENTION_DAYS}d" "$target"
echo "Successfully pruned ${rule_applies_to} backups older than ${BACKUP_RETENTION_DAYS} days." echo "Successfully pruned ${rule_applies_to} backups older than ${BACKUP_RETENTION_DAYS} days."
fi
fi
} }
if [ ! -z "$BACKUP_RETENTION_DAYS" ]; then if [ ! -z "$BACKUP_RETENTION_DAYS" ]; then
@@ -137,10 +167,10 @@ if [ ! -z "$BACKUP_RETENTION_DAYS" ]; then
sleep "$BACKUP_PRUNING_LEEWAY" sleep "$BACKUP_PRUNING_LEEWAY"
if [ ! -z "$AWS_S3_BUCKET_NAME" ]; then if [ ! -z "$AWS_S3_BUCKET_NAME" ]; then
info "Pruning old backups from remote storage" info "Pruning old backups from remote storage"
prune "backup-target/$bucket" prune "backup-target/$AWS_S3_BUCKET_NAME"
fi fi
if [ -d "$BACKUP_ARCHIVE" ]; then if [ -d "$BACKUP_ARCHIVE" ]; then
info "Pruning old backups from local archive" info "Pruning old backups from local archive"
prune "$BACKUP_ARCHIVE" prune "$BACKUP_ARCHIVE" "local"
fi fi
fi fi

View File

@@ -17,6 +17,7 @@ BACKUP_ARCHIVE="${BACKUP_ARCHIVE:-/archive}"
BACKUP_RETENTION_DAYS="${BACKUP_RETENTION_DAYS:-}" BACKUP_RETENTION_DAYS="${BACKUP_RETENTION_DAYS:-}"
BACKUP_PRUNING_LEEWAY="${BACKUP_PRUNING_LEEWAY:-10m}" BACKUP_PRUNING_LEEWAY="${BACKUP_PRUNING_LEEWAY:-10m}"
BACKUP_PRUNING_PREFIX="${BACKUP_PRUNING_PREFIX:-}"
BACKUP_STOP_CONTAINER_LABEL="${BACKUP_STOP_CONTAINER_LABEL:-true}" BACKUP_STOP_CONTAINER_LABEL="${BACKUP_STOP_CONTAINER_LABEL:-true}"
AWS_S3_BUCKET_NAME="${AWS_S3_BUCKET_NAME:-}" AWS_S3_BUCKET_NAME="${AWS_S3_BUCKET_NAME:-}"

View File

@@ -25,6 +25,10 @@ services:
AWS_S3_BUCKET_NAME: backup AWS_S3_BUCKET_NAME: backup
BACKUP_FILENAME: test.tar.gz BACKUP_FILENAME: test.tar.gz
BACKUP_CRON_EXPRESSION: 0 0 5 31 2 ? BACKUP_CRON_EXPRESSION: 0 0 5 31 2 ?
BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-7}
BACKUP_FORCE_PRUNE: ${BACKUP_FORCE_PRUNE:-}
BACKUP_PRUNING_LEEWAY: 5s
BACKUP_PRUNING_PREFIX: test
volumes: volumes:
- ./local:/archive - ./local:/archive
- app_data:/backup/app_data:ro - app_data:/backup/app_data:ro

View File

@@ -29,4 +29,27 @@ fi
echo "[TEST:PASS] All containers running post backup." echo "[TEST:PASS] All containers running post backup."
docker-compose down
# The second part of this test checks if backups get deleted when the retention
# is set to 0 days (which it should not as it would mean all backups get deleted)
# TODO: find out if we can test actual deletion without having to wait for a day
BACKUP_RETENTION_DAYS="0" docker-compose up -d
sleep 5
docker-compose exec backup backup
docker run --rm -it \
-v compose_backup_data:/data alpine \
ash -c '[ $(find /data/backup/ -type f | wc -l) = "1" ]'
echo "[TEST:PASS] Remote backups have not been deleted."
if [ "$(find ./local -type f | wc -l)" != "1" ]; then
echo "[TEST:FAIL] Backups should not have been deleted, instead seen:"
find ./local -type f
fi
echo "[TEST:PASS] Local backups have not been deleted."
docker-compose down --volumes docker-compose down --volumes

View File

@@ -33,6 +33,8 @@ services:
AWS_S3_BUCKET_NAME: backup AWS_S3_BUCKET_NAME: backup
BACKUP_FILENAME: test.tar.gz BACKUP_FILENAME: test.tar.gz
BACKUP_CRON_EXPRESSION: 0 0 5 31 2 ? BACKUP_CRON_EXPRESSION: 0 0 5 31 2 ?
BACKUP_RETENTION_DAYS: 7
BACKUP_PRUNING_LEEWAY: 5s
volumes: volumes:
- pg_data:/backup/pg_data:ro - pg_data:/backup/pg_data:ro
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock