|
|
#!/bin/bash |
|
|
|
|
|
set -e |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log() { |
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [RESTIC] $*" |
|
|
} |
|
|
|
|
|
log_success() { |
|
|
echo -e "\033[32m[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $*\033[0m" |
|
|
} |
|
|
|
|
|
log_error() { |
|
|
echo -e "\033[31m[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $*\033[0m" |
|
|
} |
|
|
|
|
|
log_warn() { |
|
|
echo -e "\033[33m[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $*\033[0m" |
|
|
} |
|
|
|
|
|
|
|
|
cleanup() { |
|
|
log "Performing cleanup operations..." |
|
|
|
|
|
if [[ -n "$BACKUP_PID" ]]; then |
|
|
kill "$BACKUP_PID" 2>/dev/null || true |
|
|
fi |
|
|
} |
|
|
|
|
|
trap cleanup EXIT |
|
|
|
|
|
|
|
|
prepare_config() { |
|
|
USER_HOME="${HOME:-/home/user}" |
|
|
local config_file="$USER_HOME/config/restic.conf" |
|
|
|
|
|
if [[ ! -f "$config_file" ]]; then |
|
|
log "Configuration file does not exist, creating from template..." |
|
|
mkdir -p "$(dirname "$config_file")" |
|
|
|
|
|
if [[ -f "$USER_HOME/config/restic.conf" ]]; then |
|
|
|
|
|
cp "$USER_HOME/config/restic.conf" "$config_file" |
|
|
|
|
|
|
|
|
if [[ "$USER_HOME" != "/home/user" ]]; then |
|
|
sed -i "s|/home/user|$USER_HOME|g" "$config_file" |
|
|
fi |
|
|
|
|
|
log_success "Created configuration from template: $USER_HOME/config/restic.conf" |
|
|
else |
|
|
|
|
|
cat > "$config_file" << EOF |
|
|
# Basic restic configuration |
|
|
RESTIC_ENABLED="false" |
|
|
RESTIC_REPOSITORY_PATH="$USER_HOME/data/restic-repo" |
|
|
RESTIC_PASSWORD="" |
|
|
RESTIC_BACKUP_PATHS="$USER_HOME" |
|
|
RESTIC_BACKUP_INTERVAL="3600" |
|
|
RESTIC_MAINTENANCE_INTERVAL="86400" |
|
|
RESTIC_LOG_FILE="$USER_HOME/log/restic.log" |
|
|
RESTIC_CACHE_DIR="$USER_HOME/.cache/restic" |
|
|
RESTIC_BACKUP_ON_STARTUP="true" |
|
|
RESTIC_AUTO_PRUNE="true" |
|
|
RESTIC_KEEP_DAILY="7" |
|
|
RESTIC_KEEP_WEEKLY="4" |
|
|
RESTIC_KEEP_MONTHLY="6" |
|
|
EOF |
|
|
log_success "Created basic configuration file" |
|
|
fi |
|
|
else |
|
|
log "Configuration file already exists: $config_file" |
|
|
fi |
|
|
} |
|
|
|
|
|
|
|
|
load_config() { |
|
|
local config_file="${1:-${HOME:-/home/user}/config/restic.conf}" |
|
|
|
|
|
if [[ -f "$config_file" ]]; then |
|
|
log "Loading configuration file: $config_file" |
|
|
|
|
|
|
|
|
local temp_config="/tmp/restic_config_$$" |
|
|
|
|
|
|
|
|
grep -E '^[^#]*=' "$config_file" | \ |
|
|
sed 's/\([^"]*"[^"]*"\)[[:space:]]*#.*/\1/' | \ |
|
|
sed 's/^\([^#]*\)=\(.*\)$/\1=${\1:-\2}/' > "$temp_config" |
|
|
|
|
|
source "$temp_config" |
|
|
rm -f "$temp_config" |
|
|
|
|
|
log_success "Configuration loaded (environment variables take precedence)" |
|
|
else |
|
|
log_warn "Configuration file does not exist: $config_file" |
|
|
log "Using environment variables and default values" |
|
|
fi |
|
|
} |
|
|
|
|
|
|
|
|
ensure_directories() { |
|
|
local dirs=( |
|
|
"$(dirname "$RESTIC_REPOSITORY_PATH")" |
|
|
"$(dirname "$RESTIC_LOG_FILE")" |
|
|
"$RESTIC_CACHE_DIR" |
|
|
) |
|
|
|
|
|
for dir in "${dirs[@]}"; do |
|
|
mkdir -p "$dir" 2>/dev/null || true |
|
|
done |
|
|
} |
|
|
|
|
|
|
|
|
setup_password() { |
|
|
if [[ -z "${RESTIC_PASSWORD:-}" ]]; then |
|
|
|
|
|
RESTIC_PASSWORD="$(openssl rand -base64 32)" |
|
|
log_success "Password auto-generated" |
|
|
fi |
|
|
|
|
|
export RESTIC_REPOSITORY="$RESTIC_REPOSITORY_PATH" |
|
|
export RESTIC_PASSWORD |
|
|
export RESTIC_CACHE_DIR |
|
|
} |
|
|
|
|
|
|
|
|
check_restic() { |
|
|
if ! command -v restic &> /dev/null; then |
|
|
log_error "Restic command not found" |
|
|
return 1 |
|
|
fi |
|
|
|
|
|
local version |
|
|
version=$(restic version | head -n1) |
|
|
log_success "Found: $version" |
|
|
} |
|
|
|
|
|
|
|
|
init_repository() { |
|
|
log "Checking repository..." |
|
|
|
|
|
if restic snapshots > /dev/null 2>&1; then |
|
|
log_success "Repository already exists" |
|
|
else |
|
|
log "Initializing repository..." |
|
|
if restic init; then |
|
|
log_success "Repository initialized successfully" |
|
|
else |
|
|
log_error "Repository initialization failed" |
|
|
return 1 |
|
|
fi |
|
|
fi |
|
|
} |
|
|
|
|
|
|
|
|
find_backup_script() { |
|
|
local script_paths=( |
|
|
"$(dirname "$0")/../utils/restic-backup.sh" |
|
|
"./script/utils/restic-backup.sh" |
|
|
"./restic-backup.sh" |
|
|
) |
|
|
|
|
|
for script_path in "${script_paths[@]}"; do |
|
|
if [[ -f "$script_path" ]]; then |
|
|
echo "$script_path" |
|
|
return 0 |
|
|
fi |
|
|
done |
|
|
|
|
|
log_error "restic-backup.sh script not found" |
|
|
return 1 |
|
|
} |
|
|
|
|
|
|
|
|
perform_backup() { |
|
|
local backup_script |
|
|
if ! backup_script=$(find_backup_script); then |
|
|
log_error "Cannot find backup script, falling back to built-in backup functionality" |
|
|
return 1 |
|
|
fi |
|
|
|
|
|
log "Using backup script: $backup_script" |
|
|
|
|
|
|
|
|
bash "$backup_script" -c "${config_file:-${HOME:-/home/user}/config/restic.conf}" |
|
|
return $? |
|
|
} |
|
|
|
|
|
|
|
|
run_maintenance() { |
|
|
log "Starting maintenance tasks..." |
|
|
|
|
|
|
|
|
log "Checking repository integrity..." |
|
|
if restic check; then |
|
|
log_success "Repository check passed" |
|
|
else |
|
|
log_error "Repository check failed" |
|
|
return 1 |
|
|
fi |
|
|
|
|
|
|
|
|
log "Cleaning old snapshots..." |
|
|
local args=("forget") |
|
|
|
|
|
[[ -n "${RESTIC_KEEP_HOURLY:-}" ]] && args+=("--keep-hourly" "${RESTIC_KEEP_HOURLY}") |
|
|
[[ -n "${RESTIC_KEEP_DAILY:-}" ]] && args+=("--keep-daily" "${RESTIC_KEEP_DAILY}") |
|
|
[[ -n "${RESTIC_KEEP_WEEKLY:-}" ]] && args+=("--keep-weekly" "${RESTIC_KEEP_WEEKLY}") |
|
|
[[ -n "${RESTIC_KEEP_MONTHLY:-}" ]] && args+=("--keep-monthly" "${RESTIC_KEEP_MONTHLY}") |
|
|
[[ "${RESTIC_AUTO_PRUNE:-true}" == "true" ]] && args+=("--prune") |
|
|
|
|
|
if restic "${args[@]}"; then |
|
|
log_success "Cleanup completed" |
|
|
else |
|
|
log_warn "Cleanup failed" |
|
|
fi |
|
|
|
|
|
log_success "Maintenance tasks completed" |
|
|
} |
|
|
|
|
|
|
|
|
main_service() { |
|
|
log "Starting restic service..." |
|
|
|
|
|
|
|
|
if [[ "${RESTIC_BACKUP_ON_STARTUP:-true}" == "true" ]]; then |
|
|
perform_backup |
|
|
fi |
|
|
|
|
|
|
|
|
local last_backup=$(date +%s) |
|
|
local last_maintenance=$(date +%s) |
|
|
|
|
|
while true; do |
|
|
local current_time=$(date +%s) |
|
|
|
|
|
|
|
|
if [[ $((current_time - last_backup)) -ge "${RESTIC_BACKUP_INTERVAL:-3600}" ]]; then |
|
|
if perform_backup; then |
|
|
last_backup=$current_time |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
if [[ $((current_time - last_maintenance)) -ge "${RESTIC_MAINTENANCE_INTERVAL:-86400}" ]]; then |
|
|
if run_maintenance; then |
|
|
last_maintenance=$current_time |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
sleep 60 |
|
|
done |
|
|
} |
|
|
|
|
|
|
|
|
main() { |
|
|
log "======= Restic Service Startup =======" |
|
|
|
|
|
|
|
|
prepare_config |
|
|
|
|
|
|
|
|
local config_file="${1:-${HOME:-/home/user}/config/restic.conf}" |
|
|
load_config "$config_file" |
|
|
|
|
|
|
|
|
ensure_directories |
|
|
|
|
|
|
|
|
if [[ "${RESTIC_ENABLED:-false}" != "true" ]]; then |
|
|
log_warn "Restic service is disabled" |
|
|
log "To enable: set RESTIC_ENABLED=true in environment variables or configuration file" |
|
|
exit 0 |
|
|
fi |
|
|
|
|
|
|
|
|
check_restic || exit 1 |
|
|
setup_password |
|
|
|
|
|
|
|
|
log "Backup service configuration:" |
|
|
log " Repository path: $RESTIC_REPOSITORY_PATH" |
|
|
log " Backup paths: $RESTIC_BACKUP_PATHS" |
|
|
log " Backup interval: ${RESTIC_BACKUP_INTERVAL:-3600} seconds" |
|
|
log " Maintenance interval: ${RESTIC_MAINTENANCE_INTERVAL:-86400} seconds" |
|
|
log " Backup on startup: ${RESTIC_BACKUP_ON_STARTUP:-true}" |
|
|
|
|
|
|
|
|
init_repository || exit 1 |
|
|
|
|
|
|
|
|
main_service |
|
|
} |
|
|
|
|
|
|
|
|
main "$@" |