Skip to content

Instantly share code, notes, and snippets.

@evanesoteric
Created July 27, 2025 17:10
Show Gist options
  • Select an option

  • Save evanesoteric/85505609b645cb92dc2d2d23f3f35d1a to your computer and use it in GitHub Desktop.

Select an option

Save evanesoteric/85505609b645cb92dc2d2d23f3f35d1a to your computer and use it in GitHub Desktop.
This script backs up a user's home directory to a remote server using rsync.
#!/bin/bash
# ==============================================================================
# REMOTE RSYNC BACKUP SCRIPT
# ==============================================================================
# This script backs up a user's home directory to a remote server using rsync.
# It incorporates file logging, an execution timer, and a configurable port.
# ==============================================================================
# --- Configuration ---
# Set the details for your remote backup server and script options below.
# Remote server SSH user and IP address/hostname
REMOTE_USER="root"
REMOTE_HOST="192.168.0.2"
REMOTE_PORT="22" # Default SSH port. Change to your custom port if needed.
# The base directory on the remote server where backups will be stored.
REMOTE_BASE_DIR="/mnt/Pool0/Backups"
# The source directory to back up on this local machine.
# Default is the current user's home directory.
SOURCE_DIR="${HOME}"
# --- Logging Configuration ---
ENABLE_LOGGING=true
LOG_FILE="${HOME}/remote_backup.log"
# --- Exclude Patterns ---
# List of directories and file patterns to exclude from the backup.
# Paths should be relative to the SOURCE_DIR.
# Add a trailing slash '/' to match a directory specifically.
EXCLUDE_PATTERNS=(
# --- General System/Cache Folders ---
".cache/"
".local/share/Trash/"
".thumbnails/"
# --- Development / Package Manager Caches & Modules ---
"node_modules/"
".npm/"
".cargo/"
".rustup/"
"__pycache__/"
"venv/"
"env/"
".venv/"
".env/"
"go/"
)
# --- Script Logic ---
# (You shouldn't need to edit below this line)
# Exit script on first error and on pipeline error
set -e
set -o pipefail
# Reset BASH time counter
SECONDS=0
# --- Logging Setup ---
# If logging is enabled, redirect stdout/stderr to both the console and a log file.
if [ "${ENABLE_LOGGING}" = true ]; then
# Create/clear the log file for this run.
: > "${LOG_FILE}"
# Use 'tee' to send output to the log file while also displaying it.
# This redirects both stdout and stderr to the tee command.
exec &> >(tee -a "${LOG_FILE}")
fi
# 1. Set up variables
# ------------------------------------------------------------------------------
# Get the current username and hostname to create a unique backup directory name.
CURRENT_USER="${USER}"
HOSTNAME=$(hostname)
BACKUP_SUBDIR="${CURRENT_USER}@${HOSTNAME}"
# Construct the full remote destination for rsync.
REMOTE_DEST_RSYNC="${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_BASE_DIR}/${BACKUP_SUBDIR}"
# Construct the path on the remote server for the mkdir command.
REMOTE_DEST_PATH="${REMOTE_BASE_DIR}/${BACKUP_SUBDIR}"
# Define the SSH and rsync remote shell commands with the custom port
SSH_CMD="ssh -p ${REMOTE_PORT}"
RSYNC_RSH="ssh -p ${REMOTE_PORT}"
echo ">>> Starting Backup for: ${BACKUP_SUBDIR}"
echo " Source: ${SOURCE_DIR}"
echo " Destination: ${REMOTE_DEST_RSYNC}"
echo " Port: ${REMOTE_PORT}"
echo "----------------------------------------------------"
# 2. Ensure remote directory exists
# ------------------------------------------------------------------------------
# Use SSH to create the specific backup directory on the remote server.
# The '-p' flag ensures that parent directories are created if they don't exist.
echo "--> Checking/Creating remote directory..."
${SSH_CMD} "${REMOTE_USER}@${REMOTE_HOST}" "mkdir -p '${REMOTE_DEST_PATH}'"
if [ $? -ne 0 ]; then
echo "!!! ERROR: Could not create directory on remote server. Aborting."
exit 1
fi
echo " Remote directory is ready."
# 3. Build rsync command with excludes
# ------------------------------------------------------------------------------
# This loop dynamically builds the --exclude arguments for the rsync command.
rsync_exclude_opts=()
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
rsync_exclude_opts+=( --exclude="$pattern" )
done
# 4. Execute the rsync backup
# ------------------------------------------------------------------------------
# -a: Archive mode (preserves permissions, ownership, timestamps, etc.)
# -v: Verbose mode (shows which files are being transferred).
# -z: Compresses file data during the transfer to save bandwidth.
# --info=progress2: Shows overall transfer progress.
# -e: Specifies the remote shell to use (for setting the port).
#
# NOTE: The --delete flag is NOT used. This means files that you
# delete on your local machine will NOT be deleted from the backup server.
echo "--> Starting file transfer with rsync..."
rsync -avz --info=progress2 -e "${RSYNC_RSH}" \
"${rsync_exclude_opts[@]}" \
"${SOURCE_DIR}/" \
"${REMOTE_DEST_RSYNC}/"
# 5. Final status
# ------------------------------------------------------------------------------
# Calculate and format the elapsed time.
ELAPSED_TIME="$((SECONDS / 3600))hrs $(((SECONDS / 60) % 60))min $((SECONDS % 60))sec"
echo "----------------------------------------------------"
echo ">>> Backup completed successfully!"
echo " Total Time: ${ELAPSED_TIME}"
if [ "${ENABLE_LOGGING}" = true ]; then
echo " Log file available at: ${LOG_FILE}"
fi
echo "----------------------------------------------------"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment