Last active
May 10, 2025 16:34
-
-
Save alainwolf/147ae04d91f29655d317af5656ccf85f to your computer and use it in GitHub Desktop.
Website Backup (Hosttech, Plesk, Wordpress and others)
This file contains hidden or 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
#!/usr/bin/env bash | |
# **************************************************************************** | |
# Website backup for Webservers | |
# - Set Wordpress into maintenance mode | |
# - Create CACHE_DIR.TAG files to exclude cache directories | |
# - Dump databases into temporary files | |
# - Create archive of all files incl. the database dump | |
# - Transfer archive to remote backup storage | |
# - Send health check notifications to https://healthchecks.io | |
# - Clean-up temporary files | |
# | |
# Edited by Alain Wolf on Fri, 9. May 2025 15:09 | |
# **************************************************************************** | |
# -------------------------------------------------- | |
# Settings | |
# -------------------------------------------------- | |
# Read settings from conf file | |
# shellcheck source=website-backup.conf.sample | |
. "${0}.conf" | |
# Fail on error or unset variable | |
set -e -u | |
# Fail on pipe error | |
set -o pipefail | |
# Logging function | |
log() { | |
echo "$(date +'%Y-%m-%d %H:%M:%S') - $1" | |
} | |
log "Starting backup process" | |
# Send health check notification | |
if [ -n "${healthcheck_uuid}" ]; then | |
log "Sending health check notification to https://healthchecks.io" | |
curl -sS --retry 3 --retry-delay 5 --retry-max-time 30 \ | |
"https://hc-ping.com/${healthcheck_uuid}/start" | |
fi | |
# Create CACHE_DIR.TAG files to exclude cache directories | |
# https://bford.info/cachedir/ | |
for CACHE_DIR in ${CACHE_DIRS}; do | |
# Check if the directory exists | |
if [ ! -d "${CACHE_DIR}" ]; then | |
log "Cache directory ${CACHE_DIR} does not exist, skipping." | |
continue | |
else | |
# Check if a CACHE_DIR.TAG file already exists | |
if [ ! -f "${CACHE_DIR}/CACHEDIR.TAG" ]; then | |
log "Creating CACHEDIR.TAG file in ${CACHE_DIR}" | |
echo "Signature: 8a477f597d28d172789f06886806bc55" >"${CACHE_DIR}/CACHEDIR.TAG" | |
fi | |
fi | |
done | |
# Archive filename | |
ARCHIVE_NAME="backup-$(date +%Y-%m-%d_%H-%M-%S).tar.gz" | |
# Create temporary directory | |
TMP_DIR=$(mktemp -d) | |
log "Created temporary directory ${TMP_DIR}" | |
# Put Wordpress site in maintenance mode | |
# https://developer.wordpress.org/reference/functions/wp_is_maintenance_mode/ | |
if [ -n "${WP_DIR}" ]; then | |
log "Enabling Wordpress maintenance mode." | |
# shellcheck disable=SC2016 | |
echo '<?php $upgrading = time(); ?>' >"${WP_DIR}/.maintenance" | |
fi | |
# Let things settle | |
sleep 5 | |
# Dump databases | |
mkdir -p "${TMP_DIR}/SQL" | |
for DB in ${DB_DATABASES}; do | |
log "Dumping database ${DB}" | |
/usr/bin/mariadb-dump \ | |
--host="${DB_HOST}" --port="${DB_PORT}" --user="${DB_USER}" --password="${DB_PASSWORD}" \ | |
--add-drop-database --add-locks --comments --create-options --dump-date \ | |
--flush-privileges --single-transaction --routines \ | |
--databases "${DB}" >"${TMP_DIR}/SQL/${DB}.sql" | |
done | |
# Let things settle | |
sleep 5 | |
# Create archive | |
log "Creating archive ${ARCHIVE_NAME}" | |
# shellcheck disable=SC2046 | |
tar --create --gzip --file "${TMP_DIR}/${ARCHIVE_NAME}" \ | |
--exclude-caches --exclude-caches-under --exclude-tag=.nobackup \ | |
--directory "${HOME}" $(for dir in ${BACKUP_DIRS}; do echo "${dir}"; done) \ | |
--directory "${TMP_DIR}" SQL | |
# Disable Wordpress maintenance mode | |
if [ -n "${WP_DIR}" ]; then | |
log "Disabling Wordpress maintenance mode." | |
rm -f "${WP_DIR}/.maintenance" | |
fi | |
# Transfer archive | |
log "Transferring archive to ${REMOTE_HOST}:${REMOTE_PATH}" | |
rsync --times "${TMP_DIR}/${ARCHIVE_NAME}" "${REMOTE_HOST}:${REMOTE_PATH}/" | |
# Clean-up | |
log "Cleaning up temporary files" | |
rm -rf "${TMP_DIR}" | |
# Send health check notification | |
if [ -n "${healthcheck_uuid}" ]; then | |
log "Sending health check notification to https://healthchecks.io" | |
curl -sS --retry 3 --retry-delay 5 --retry-max-time 30 \ | |
"https://hc-ping.com/${healthcheck_uuid}" | |
fi | |
log "Backup process completed" |
This file contains hidden or 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
#!/usr/bin/env bash | |
# shellcheck disable=SC2034 | |
# **************************************************************************** | |
# Website backup configuration settings for example.org | |
# | |
# Edited by Alain Wolf on Fri, 10. February 1967 09:01 | |
# **************************************************************************** | |
# -------------------------------------------------------- | |
# Configuration Settings | |
# -------------------------------------------------------- | |
# Wordpress install directory | |
# If set, the script will put Wordpress into maintenance mode during the backup | |
#WP_DIR='/httpdocs' | |
# Database server connection | |
DB_HOST='localhost' | |
DB_PORT='3306' | |
DB_USER='CHANGEME' | |
DB_PASSWORD='CHANGEME' | |
DB_DATABASES=' | |
wp_database | |
' | |
# Directories (and files) to backup (database dumps are always included) | |
BACKUP_DIRS=' | |
httpdocs | |
.local | |
.ssh | |
error_docs | |
logs | |
mta-sts | |
' | |
# Cache directories to exclude from backups | |
CACHE_DIRS=' | |
httpdocs/wp-content/cache | |
httpdocs/wp-content/et-cache | |
httpdocs/wp-content/updraft | |
' | |
# Remote backup storage | |
# SSH connection and login settings are exptected to be set in ~/.ssh/config | |
REMOTE_HOST='mynas.exaple.com' | |
REMOTE_PATH='/volume1/Backups/Hosting/Server/Website' | |
# Health check UUID | |
# If set, the script will send status updates to https://healthchecks.io | |
#healthcheck_uuid='aaaaaaaa-bbbb-cccc-1234-dddddddddddd' | |
# -*- mode: bash; indent-tabs-mode: nil; tab-width: 4; -*- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment