Preserve host destinations and zstd options

This commit is contained in:
Codex authored and howard committed 2026-09-20 21:40:30 +12:00
1 parent 261e88f5dc
commit e27387bd93
5 files changed
+17 -4

No files matched your search

+2
View File
@@ -12,10 +12,12 @@ START_TIMEOUT=90
WAIT_INTERVAL=3 WAIT_INTERVAL=3
START_RETRIES=1 START_RETRIES=1
LOCK_FILE="/run/lock/zorruno-docker-backup.lock" LOCK_FILE="/run/lock/zorruno-docker-backup.lock"
ZSTD_EXTRA_OPTS="-T0 -12"
# Rclone destination becomes <remote>/beaver/. # Rclone destination becomes <remote>/beaver/.
RCLONE_ENABLED=0 RCLONE_ENABLED=0
RCLONE_REMOTE="gdrive:dockerbackups" RCLONE_REMOTE="gdrive:dockerbackups"
RCLONE_HOST_SUBDIR=1
RCLONE_EXTRA_ARGS="" RCLONE_EXTRA_ARGS=""
# The SMB share must already be mounted by the operating system. # The SMB share must already be mounted by the operating system.
+4 -1
View File
@@ -68,6 +68,7 @@ Copy `.env.example` to `.env`; `.env` is ignored by Git. Important values:
| `CONTAINERS_FILE` | Absolute path, or path relative to this repository | | `CONTAINERS_FILE` | Absolute path, or path relative to this repository |
| `BACKUP_HOSTNAME` | Host folder/name embedded in archive filenames | | `BACKUP_HOSTNAME` | Host folder/name embedded in archive filenames |
| `BACKUP_METHODS` | Ordered method names, default `rclone smb` | | `BACKUP_METHODS` | Ordered method names, default `rclone smb` |
| `ZSTD_EXTRA_OPTS` | Options passed to `zstd`, default `-T0 -12` |
| `KEEP_COUNT` | Local archives retained per Compose project | | `KEEP_COUNT` | Local archives retained per Compose project |
| `PULL_IMAGES` | Pull images before restarting (`1` or `0`) | | `PULL_IMAGES` | Pull images before restarting (`1` or `0`) |
@@ -79,7 +80,9 @@ RCLONE_REMOTE="gdrive:dockerbackups"
``` ```
Archives are copied beneath `<remote>/<BACKUP_HOSTNAME>/`. The method uses Archives are copied beneath `<remote>/<BACKUP_HOSTNAME>/`. The method uses
`rclone copy`, so it does not delete older destination files. `rclone copy`, so it does not delete older destination files. Set
`RCLONE_HOST_SUBDIR=0` when `RCLONE_REMOTE` already names the final host-specific
destination; otherwise the host name is appended automatically.
### SMB ### SMB
+2
View File
@@ -15,9 +15,11 @@ START_TIMEOUT=90
WAIT_INTERVAL=3 WAIT_INTERVAL=3
START_RETRIES=1 START_RETRIES=1
LOCK_FILE="/run/lock/zorruno-docker-backup.lock" LOCK_FILE="/run/lock/zorruno-docker-backup.lock"
ZSTD_EXTRA_OPTS="-T0 -12"
RCLONE_ENABLED=0 RCLONE_ENABLED=0
RCLONE_REMOTE="" RCLONE_REMOTE=""
RCLONE_HOST_SUBDIR=1
RCLONE_EXTRA_ARGS="" RCLONE_EXTRA_ARGS=""
SMB_ENABLED=0 SMB_ENABLED=0
SMB_MOUNT="" SMB_MOUNT=""
+4 -2
View File
@@ -17,8 +17,10 @@ if ! is_true "$RCLONE_ENABLED" && (( FORCE == 0 )); then log SKIP "rclone method
require_command rclone require_command rclone
[[ -d "$BACKUP_ROOT" ]] || die "Backup root not found: $BACKUP_ROOT" [[ -d "$BACKUP_ROOT" ]] || die "Backup root not found: $BACKUP_ROOT"
read -r -a extra_args <<<"$RCLONE_EXTRA_ARGS" read -r -a extra_args <<<"$RCLONE_EXTRA_ARGS"
args=(copy "$BACKUP_ROOT" "${RCLONE_REMOTE%/}/$BACKUP_HOSTNAME" "${extra_args[@]}") destination="${RCLONE_REMOTE%/}"
is_true "$RCLONE_HOST_SUBDIR" && destination="$destination/$BACKUP_HOSTNAME"
args=(copy "$BACKUP_ROOT" "$destination" "${extra_args[@]}")
(( DRY_RUN )) && args+=(--dry-run) (( DRY_RUN )) && args+=(--dry-run)
log INFO "Copying backups to ${RCLONE_REMOTE%/}/$BACKUP_HOSTNAME" log INFO "Copying backups to $destination"
rclone "${args[@]}" rclone "${args[@]}"
log DONE "rclone backup method completed" log DONE "rclone backup method completed"
+5 -1
View File
@@ -29,6 +29,7 @@ done
CONTAINERS_FILE="$(resolve_path "$CONTAINERS_FILE")" CONTAINERS_FILE="$(resolve_path "$CONTAINERS_FILE")"
require_command docker require_command docker
require_command tar require_command tar
require_command zstd
[[ -d "$SOURCE_BASE_DIR" ]] || die "Docker source directory not found: $SOURCE_BASE_DIR" [[ -d "$SOURCE_BASE_DIR" ]] || die "Docker source directory not found: $SOURCE_BASE_DIR"
[[ -r "$CONTAINERS_FILE" ]] || die "Containers file not readable: $CONTAINERS_FILE" [[ -r "$CONTAINERS_FILE" ]] || die "Containers file not readable: $CONTAINERS_FILE"
@@ -77,6 +78,7 @@ wait_for_project() {
backup_project() { backup_project() {
local project="$1" working_dir="$2" parent base output_dir output attempt local project="$1" working_dir="$2" parent base output_dir output attempt
local -a zstd_args=()
parent="$(dirname "$working_dir")" parent="$(dirname "$working_dir")"
base="$(basename "$working_dir")" base="$(basename "$working_dir")"
output_dir="$BACKUP_ROOT/$project" output_dir="$BACKUP_ROOT/$project"
@@ -91,7 +93,9 @@ backup_project() {
mkdir -p "$output_dir" mkdir -p "$output_dir"
cd "$working_dir" cd "$working_dir"
compose down compose down
if ! tar --one-file-system --zstd -cf "$output" -C "$parent" "$base"; then read -r -a zstd_args <<<"$ZSTD_EXTRA_OPTS"
if ! tar --one-file-system -cf - -C "$parent" "$base" | zstd "${zstd_args[@]}" -o "$output"; then
rm -f -- "$output"
log ERROR "Archive failed; attempting to restart $project" log ERROR "Archive failed; attempting to restart $project"
compose up -d || true compose up -d || true
return 1 return 1