#!/usr/bin/env bash set -Eeuo pipefail SCRIPT_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P)" ENV_FILE="${DOCKERBACKUP_ENV:-$SCRIPT_ROOT/.env}" SOURCE_BASE_DIR="/dockervolumes" BACKUP_ROOT="/dockerbackups" CONTAINERS_FILE="$SCRIPT_ROOT/containers.txt" BACKUP_HOSTNAME="$(hostname -s)" BACKUP_METHODS="rclone smb" KEEP_COUNT=5 PULL_IMAGES=1 START_TIMEOUT=90 WAIT_INTERVAL=3 START_RETRIES=1 LOCK_FILE="/run/lock/zorruno-docker-backup.lock" ZSTD_EXTRA_OPTS="-T0 -12" MQTT_REPORT_ENABLED=0 MQTT_HOST="" MQTT_PORT=1883 MQTT_USERNAME="" MQTT_PASSWORD_FILE="" MQTT_STATUS_TOPIC="viewroad-status/dockerbackup/$BACKUP_HOSTNAME" MQTT_COMMAND_TOPIC="viewroad-commands/dockerbackup/$BACKUP_HOSTNAME/run" RCLONE_ENABLED=0 RCLONE_REMOTE="" RCLONE_HOST_SUBDIR=1 RCLONE_EXTRA_ARGS="" SMB_ENABLED=0 SMB_MOUNT="" SMB_HOST_SUBDIR=1 SMB_RSYNC_ARGS="-a" if [[ -f "$ENV_FILE" ]]; then set -a # shellcheck disable=SC1090 . "$ENV_FILE" set +a fi # Ease migration from the original prune script's .env names. if [[ -n "${SOURCE_DIR:-}" && "$BACKUP_ROOT" == "/dockerbackups" ]]; then BACKUP_ROOT="$SOURCE_DIR" fi timestamp() { date '+%F %T'; } log() { local line line="$(timestamp) [$1] $2" printf '%s\n' "$line" >&2 if [[ -n "${BACKUP_RUN_LOG:-}" ]]; then printf '%s\n' "$line" >>"$BACKUP_RUN_LOG" fi return 0 } die() { log ERROR "$1"; exit "${2:-1}"; } is_true() { case "${1,,}" in 1|true|yes|on|enabled) return 0 ;; *) return 1 ;; esac } require_command() { command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1" 3 } require_positive_integer() { [[ "$2" =~ ^[1-9][0-9]*$ ]] || die "$1 must be a positive integer (received: $2)" 2 } resolve_path() { if [[ "$1" = /* ]]; then printf '%s\n' "$1"; else printf '%s/%s\n' "$SCRIPT_ROOT" "$1"; fi } run_id() { date '+%Y-%m-%d_%H-%M-%S'; }