Last active
December 20, 2024 10:02
-
-
Save R-omk/8a69c63cb0dc744334353694178a3ad1 to your computer and use it in GitHub Desktop.
script to backup via restic plus rclone
This file contains 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
#!/bin/bash | |
set -e | |
RESTIC_OPTIONS=() | |
command -v rclone >/dev/null 2>&1 || { | |
echo "rclone is not installed. Please install it and try again." >&2 | |
exit 1 | |
} | |
command -v restic >/dev/null 2>&1 || { | |
echo "restic is not installed. Please install it and try again." >&2 | |
exit 1 | |
} | |
# Function to create a template configuration file | |
confinit() { | |
if [ -f "$1" ]; then | |
echo "Configuration file already exists: $1" | |
return 1 | |
fi | |
CONFIG_FILE=$1 | |
# Generate a secure password for RESTIC | |
RESTIC_PASSWORD=$(head -c 24 /dev/urandom | base64) | |
cat <<EOL >"$CONFIG_FILE" | |
# Template configuration file for restic-rclone | |
RCLONENAME='your_rclone_connection' # Specify the name of the rclone connection that restic will use to access the repository; use 'rclone config' to start interactive config management | |
REPONAME='your_repo_name' # Specify the desired repository name, a directory with this name will be used | |
RESTIC_PASSWORD='$RESTIC_PASSWORD' # Warning: If you lose the RESTIC_PASSWORD, you will not be able to restore your backups. | |
EXCLUDE_DIRS='Downloads,.cache,tmp,ignore folder with space' # Add directories to exclude from backup to save space | |
BACKUP_DIR='$HOME' | |
EOL | |
echo "Template configuration file created: $CONFIG_FILE" | |
echo "Use the script as follows:" | |
echo "$0 --config $CONFIG_FILE {check|init|backup|prune|mount}" | |
echo "Important: Please make sure to store the RESTIC_PASSWORD securely, as it will be used to encrypt your backups." | |
echo "Warning: If you lose the RESTIC_PASSWORD, you will not be able to restore your backups." | |
} | |
load_config() { | |
if [ ! -f "$1" ]; then | |
echo "Configuration file not found: $1" | |
return 1 | |
fi | |
source "$1" | |
# Check that all required variables are loaded successfully | |
REQUIRED_VARS=(RESTIC_PASSWORD RCLONENAME REPONAME EXCLUDE_DIRS BACKUP_DIR) | |
for var in "${REQUIRED_VARS[@]}"; do | |
if [ -z "${!var}" ]; then | |
echo "Error: variable '$var' not found in configuration file '$1'" | |
return 1 | |
fi | |
done | |
RESTIC_OPTIONS=(--verbose --pack-size=4 --compression=max -o rclone.args="serve restic --stdio --b2-hard-delete" -r rclone:$RCLONENAME:$REPONAME) | |
} | |
# Function to check rclone connection | |
check() { | |
load_config $1 || exit 1 | |
rclone lsd $RCLONENAME: --dry-run >/dev/null 2>&1 | |
if [ $? -eq 0 ]; then | |
echo "Connection successful." | |
else | |
echo "Connection error." | |
exit 1 | |
fi | |
SNAPSHOTS_OUTPUT=$(RESTIC_PASSWORD=$RESTIC_PASSWORD restic "${RESTIC_OPTIONS[@]}" snapshots 2>&1) | |
if [ $? -eq 0 ]; then | |
echo "Repository exists. Here are the snapshots:" | |
echo "$SNAPSHOTS_OUTPUT" | |
echo "" | |
echo "Size:" | |
rclone size $RCLONENAME:$REPONAME | |
else | |
echo "No repository found at the specified location." | |
echo "Please initialize the repository using the 'init' command." | |
fi | |
} | |
# Function to initialize the restic repository | |
init_repo() { | |
load_config $1 || exit 1 | |
RESTIC_PASSWORD=$RESTIC_PASSWORD restic "${RESTIC_OPTIONS[@]}" init --repository-version=latest | |
} | |
# Function to perform backup | |
backup() { | |
load_config $1 || exit 1 | |
# Create a list of exclusions | |
EXCLUDES=() | |
IFS=',' read -ra ADDR <<<"$EXCLUDE_DIRS" | |
for dir in "${ADDR[@]}"; do | |
EXCLUDES+=("--exclude=$BACKUP_DIR/$dir") | |
done | |
# Perform backup | |
RCLONE_TRANSFERS=8 RCLONE_CHECKERS=16 RESTIC_PASSWORD=$RESTIC_PASSWORD restic "${RESTIC_OPTIONS[@]}" backup --one-file-system --tag default "${EXCLUDES[@]}" "$BACKUP_DIR" | |
} | |
# Function to remove unnecessary snapshots from the repository | |
# This function is used to clean up the repository and free up space | |
# It removes snapshots that are no longer needed based on the retention policy | |
prune() { | |
load_config $1 || exit 1 | |
# Perform cleanup | |
RCLONE_TRANSFERS=24 RCLONE_CHECKERS=64 RESTIC_PASSWORD=$RESTIC_PASSWORD restic "${RESTIC_OPTIONS[@]}" forget --prune --tag=default --keep-last 100 --keep-daily 7 --keep-weekly 5 --keep-monthly 12 --keep-yearly 75 | |
} | |
# Function to mount the restic repository | |
mount_repo() { | |
load_config $1 || exit 1 | |
if [ -z "$2" ]; then | |
echo "You must specify a directory to mount." | |
return 1 | |
fi | |
# Perform mounting | |
RESTIC_PASSWORD=$RESTIC_PASSWORD restic "${RESTIC_OPTIONS[@]}" mount "$2" | |
} | |
if [ "$#" -eq 0 ]; then | |
echo "Usage: $0 [--config <config_file>] {confinit|check|init|backup|prune|mount}" | |
echo "Note: If --config option is not specified, the configuration file will be created in $HOME/.restic_rclone_backup_config" | |
exit 1 | |
fi | |
# Handle --config option | |
if [[ "$1" == "--config" && -n "$2" ]]; then | |
CONFIG_FILE="$2" | |
shift 2 | |
else | |
CONFIG_FILE="$HOME/.restic_rclone_backup_config" | |
fi | |
case "$1" in | |
confinit) | |
confinit "$CONFIG_FILE" | |
;; | |
check) | |
check "$CONFIG_FILE" | |
;; | |
init) | |
init_repo "$CONFIG_FILE" | |
;; | |
backup) | |
backup "$CONFIG_FILE" | |
;; | |
prune) | |
prune "$CONFIG_FILE" | |
;; | |
mount) | |
mount_repo "$CONFIG_FILE" "$2" | |
;; | |
*) | |
echo "Invalid command: $1" | |
exit 1 | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment