feat: Add backup and security hardening
This commit is contained in:
182
scripts/backup-setup/backup-trigger
Normal file
182
scripts/backup-setup/backup-trigger
Normal file
@@ -0,0 +1,182 @@
|
||||
#!/bin/sh
|
||||
# Network-triggered backup daemon
|
||||
# Monitors for NAS availability and triggers backups with safeguards
|
||||
|
||||
set -e
|
||||
|
||||
# Config
|
||||
CONFIG_FILE="/etc/backup.conf"
|
||||
LOG_DIR="${HOME}/.local/var/log"
|
||||
LOG_FILE="${LOG_DIR}/backup-monitor.log"
|
||||
STATE_DIR="${HOME}/.local/var/backup"
|
||||
LAST_BACKUP_FILE="${STATE_DIR}/last-backup"
|
||||
LAST_CHECK_FILE="${STATE_DIR}/last-check"
|
||||
BACKUP_IN_PROGRESS_FILE="${STATE_DIR}/backup-in-progress"
|
||||
|
||||
# Ensure directories exist
|
||||
mkdir -p "$LOG_DIR" "$STATE_DIR"
|
||||
|
||||
# Logging
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Load config
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
log "ERROR: Configuration file not found: $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
. "$CONFIG_FILE"
|
||||
|
||||
# Check if backup is already running
|
||||
is_backup_running() {
|
||||
# Check if any backup lock files exist
|
||||
if ls /tmp/backup-*.lock >/dev/null 2>&1; then
|
||||
return 0 # Backup is running
|
||||
fi
|
||||
|
||||
# Check our own in-progress marker
|
||||
if [ -f "$BACKUP_IN_PROGRESS_FILE" ]; then
|
||||
# Check if marker is stale (older than 6 hours)
|
||||
if [ -n "$(find "$BACKUP_IN_PROGRESS_FILE" -mmin +360 2>/dev/null)" ]; then
|
||||
log "WARNING: Stale backup-in-progress marker found, removing"
|
||||
rm -f "$BACKUP_IN_PROGRESS_FILE"
|
||||
return 1 # Not running
|
||||
fi
|
||||
return 0 # Backup is running
|
||||
fi
|
||||
|
||||
return 1 # Not running
|
||||
}
|
||||
|
||||
# Check if cooldown period has passed
|
||||
check_cooldown() {
|
||||
if [ ! -f "$LAST_BACKUP_FILE" ]; then
|
||||
return 0 # No previous backup, proceed
|
||||
fi
|
||||
|
||||
LAST_BACKUP=$(cat "$LAST_BACKUP_FILE")
|
||||
NOW=$(date +%s)
|
||||
ELAPSED=$((NOW - LAST_BACKUP))
|
||||
|
||||
if [ "$ELAPSED" -lt "$BACKUP_COOLDOWN" ]; then
|
||||
REMAINING=$((BACKUP_COOLDOWN - ELAPSED))
|
||||
log "Cooldown active: ${REMAINING}s remaining until next backup allowed"
|
||||
return 1 # Still in cooldown
|
||||
fi
|
||||
|
||||
return 0 # Cooldown passed
|
||||
}
|
||||
|
||||
# Check if we recently checked (prevent spam checks)
|
||||
check_rate_limit() {
|
||||
CHECK_INTERVAL=300 # 5 minutes between checks
|
||||
|
||||
if [ ! -f "$LAST_CHECK_FILE" ]; then
|
||||
date +%s > "$LAST_CHECK_FILE"
|
||||
return 0 # First check, proceed
|
||||
fi
|
||||
|
||||
LAST_CHECK=$(cat "$LAST_CHECK_FILE")
|
||||
NOW=$(date +%s)
|
||||
ELAPSED=$((NOW - LAST_CHECK))
|
||||
|
||||
if [ "$ELAPSED" -lt "$CHECK_INTERVAL" ]; then
|
||||
return 1 # Too soon since last check
|
||||
fi
|
||||
|
||||
date +%s > "$LAST_CHECK_FILE"
|
||||
return 0 # Can check now
|
||||
}
|
||||
|
||||
# Check if NAS is available
|
||||
check_nas_available() {
|
||||
# Quick ping check
|
||||
if ! ping -c 1 -W 2 "$NAS_HOST" >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# SSH check
|
||||
if ! ssh -p "$NAS_PORT" -o ConnectTimeout=5 -o BatchMode=yes \
|
||||
"${NAS_USER}@${NAS_HOST}" "echo test" >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Trigger backup
|
||||
trigger_backup() {
|
||||
BACKUP_TYPE="${1:-incremental}"
|
||||
|
||||
log "NAS detected, triggering $BACKUP_TYPE backup..."
|
||||
|
||||
# Mark backup in progress
|
||||
touch "$BACKUP_IN_PROGRESS_FILE"
|
||||
|
||||
# Run backup in background
|
||||
(
|
||||
if /usr/local/bin/backup-"$BACKUP_TYPE" >> "$LOG_FILE" 2>&1; then
|
||||
log "Backup completed successfully"
|
||||
else
|
||||
log "ERROR: Backup failed"
|
||||
fi
|
||||
|
||||
# Remove in-progress marker
|
||||
rm -f "$BACKUP_IN_PROGRESS_FILE"
|
||||
) &
|
||||
|
||||
# Don't wait for backup to complete
|
||||
log "Backup started in background (PID: $!)"
|
||||
}
|
||||
|
||||
# Main monitoring loop
|
||||
main() {
|
||||
log "=========================================="
|
||||
log "Backup monitor started"
|
||||
log "Monitoring for NAS: ${NAS_HOST}"
|
||||
log "Check interval: 5 minutes"
|
||||
log "Backup cooldown: ${BACKUP_COOLDOWN}s ($(( BACKUP_COOLDOWN / 3600 ))h)"
|
||||
log "=========================================="
|
||||
|
||||
while true; do
|
||||
# Rate limit checks (every 5 minutes)
|
||||
if ! check_rate_limit; then
|
||||
sleep 60
|
||||
continue
|
||||
fi
|
||||
|
||||
# Skip if backup already running
|
||||
if is_backup_running; then
|
||||
log "Backup already in progress, skipping check"
|
||||
sleep 300 # Sleep 5 minutes
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if NAS is available
|
||||
if check_nas_available; then
|
||||
log "NAS is available at ${NAS_HOST}"
|
||||
|
||||
# Check cooldown before triggering
|
||||
if check_cooldown; then
|
||||
log "Cooldown passed, backup allowed"
|
||||
trigger_backup "incremental"
|
||||
else
|
||||
log "Cooldown active, skipping backup"
|
||||
fi
|
||||
else
|
||||
log "NAS not available (offline or not connected)"
|
||||
fi
|
||||
|
||||
# Sleep before next check (5 minutes)
|
||||
sleep 300
|
||||
done
|
||||
}
|
||||
|
||||
# Handle signals
|
||||
trap 'log "Received shutdown signal, exiting..."; exit 0' TERM INT
|
||||
|
||||
# Start monitoring
|
||||
main
|
||||
Reference in New Issue
Block a user