You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
4.3 KiB
Bash

#!/bin/bash
############################
# LOGGING & ERROR HANDLING #
############################
# Ensure you set the SCRIPT_DIR variable correctly as the error handling will not catch it
# Change the LOG_RETENTION if you wish for more or less.
readonly SCRIPT_DIR="/path/to/script/dir"
readonly LOG_DIR="${SCRIPT_DIR}/backupLogs"
readonly DATETIME="$(date '+%Y-%m-%d_%H:%M:%S')"
readonly BACKUP_LOG="${LOG_DIR}/backupLog_"${DATETIME}".log"
readonly LOG_RETENTION="14"
exec 3<&1 4<&2
trap "exec 2<&4 1<&3" 0 1 2 3
exec > >(tee >(ts "%Y-%m-%d_%H:%M:%S" > "${BACKUP_LOG}")) 2>&1
set -eEuo pipefail
# Uncomment the below to debug the script
# set -x
# trap 'err_report' ERR
# function err_report() {
# sleep 5
# curl \
# -T "${BACKUP_LOG}" \
# -H "Filename: backupLog_"${DATETIME}".log" \
# -H prio:high \
# -H "Title: Backup Failed on ${HOSTNAME}" \
# ntfyUser:ntfyPassword@ntfyDomain/ntfyTopic
# }
################
# RSYNC SCRIPT #
################
# Configure variables from here...
readonly RSYNC_SOURCE_01="/path/to/dir/to/backup-01"
readonly RSYNC_DEST_01="/path/to/dir/to/backup/to-01"
readonly RSYNC_MANIFEST_01="${SCRIPT_DIR}/rsyncManifest"
readonly RSYNC_RETENTION_DAYS_01="9"
# ...to here
readonly RSYNC_DEST_PATH_01="${RSYNC_DEST_01}/${DATETIME}"
readonly RSYNC_LATEST_LINK_01="${RSYNC_DEST_01}/latest"
# Creates the backup directory
mkdir -p "${RSYNC_DEST_01}"
# -avP will tell rsync to run in archive mode, be verbose, keep partial files if interrupted, and show progress
rsync -avP --delete --prune-empty-dirs --include-from="${RSYNC_MANIFEST_01}" \
"${RSYNC_SOURCE_01}/" \
--link-dest "${RSYNC_LATEST_LINK_01}" \
"${RSYNC_DEST_PATH_01}"
# This will update the latest hardlink
rm -rf "${RSYNC_LATEST_LINK_01}"
ln -s "${RSYNC_DEST_PATH_01}" "${RSYNC_LATEST_LINK_01}"
# The hacky fix for the NFS destination timestamp bug
touch "${RSYNC_DEST_PATH_01}"/timestamp.fix
# This will prune excess version folders.
cd "${RSYNC_DEST_01}"
rm -rf `ls -t | tail -n +"${RSYNC_RETENTION_DAYS_01}"`
#################
# RESTIC SCRIPT #
#################
# Configure all but first and last accordingly.
readonly RESTIC_PASSWORD_01="${SCRIPT_DIR}/.resticPassword"
readonly RESTIC_SOURCE_01="/path/to/dir/to/backup-01"
readonly RESTIC_REPO_01="/path/to/restic/repo-01"
readonly RESTIC_RETENTION_DAYS_01="7"
readonly RESTIC_RETENTION_WEEKS_01="4"
readonly RESTIC_RETENTION_MONTHS_01="6"
readonly RESTIC_RETENTION_YEARS_01="1"
# If you prefer a keep last retention policy, comment out the above 4 and uncomment the below and configure
# readonly RESTIC_RETENTION_KEEP_LAST_01="2"
readonly RESTIC_TAG_01="tag01"
readonly RESTIC_TAG_02="tag02"
readonly RESTIC_EXCLUDES_01="${SCRIPT_DIR}/resticExcludes"
# --p points to the password file, -r points to the restic repo path
restic backup --verbose \
-p "${RESTIC_PASSWORD_01}" \
-r "${RESTIC_REPO_01}" \
--tag "${RESTIC_TAG_01}" --tag "${RESTIC_TAG_02}" \
--exclude-caches \
--exclude-file="${RESTIC_EXCLUDES_01}" \
"${RESTIC_SOURCE_01}"
# Now we forget snapshots and prune data for the same tags in the repo
restic forget --prune --verbose --tag "${RESTIC_TAG_01}","${RESTIC_TAG_02}" \
-p "${RESTIC_PASSWORD_01}" \
-r "${RESTIC_REPO_01}" \
--keep-daily "${RESTIC_RETENTION_DAYS_01}" \
--keep-weekly "${RESTIC_RETENTION_WEEKS_01}" \
--keep-monthly "${RESTIC_RETENTION_MONTHS_01}" \
--keep-yearly "${RESTIC_RETENTION_YEARS_01}"
# If using a keep last retention policy, comment out the above forget command and uncomment the below
# restic forget --prune --verbose --tag "${RESTIC_TAG_01}","${RESTIC_TAG_02}" \
# -p "${RESTIC_PASSWORD_01}" \
# -r "${RESTIC_REPO_01}" \
# --keep-last "${RESTIC_RETENTION_KEEP_LAST_01}"
# Finally, we verify the integrity of the repo
restic check \
-p "${RESTIC_PASSWORD_01}" \
-r "${RESTIC_REPO_01}"
##############
# TIDYING UP #
##############
# Clean up log files older than 14 days
# find "${LOG_DIR}" -mtime +"${LOG_RETENTION}" -type f -delete
find "${LOG_DIR}"/*.log -mtime +"${LOG_RETENTION}" -type f -delete
# End of script message in log
echo > >(tee >(echo "$(ts "%Y-%m-%d_%H:%M:%S") Backup Script Complete" >> "${BACKUP_LOG}"))
# sleep 5
# curl \
# -T "${BACKUP_LOG}" \
# -H "Filename: backupLog_"${DATETIME}".log" \
# -H prio:low \
# -H "Title: Backup Succeeded on ${HOSTNAME}" \
# ntfyUser:ntfyPassword@ntfyDomain/ntfyTopic