feat: Add backup and security hardening

This commit is contained in:
2025-11-08 00:28:17 +01:00
parent 8de3f16ee6
commit 96f521a474
23 changed files with 5696 additions and 939 deletions

View File

@@ -0,0 +1,142 @@
#!/bin/sh
# Full system backup script
# Backs up entire system except excluded directories
set -e
# Config
CONFIG_FILE="/etc/backup.conf"
LOG_DIR="${HOME}/.local/var/log"
LOG_FILE="${LOG_DIR}/backup.log"
LOCK_FILE="/tmp/backup-full.lock"
# Ensure log directory exists
mkdir -p "$LOG_DIR"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
echo "$*"
}
error() {
printf "${RED}✖${NC} %s\n" "$1"
log "ERROR: $1"
}
info() {
printf "${BLUE}${NC} %s\n" "$1"
log "INFO: $1"
}
success() {
printf "${GREEN}✓${NC} %s\n" "$1"
log "SUCCESS: $1"
}
# Load config
if [ ! -f "$CONFIG_FILE" ]; then
error "Configuration file not found: $CONFIG_FILE"
exit 1
fi
# shellcheck source=/dev/null
. "$CONFIG_FILE"
# Create lock file
if [ -f "$LOCK_FILE" ]; then
error "Backup already running (lock file exists: $LOCK_FILE)"
exit 1
fi
trap 'rm -f "$LOCK_FILE"' EXIT
touch "$LOCK_FILE"
# Check cooldown
if [ -f "$LAST_BACKUP_FILE" ]; then
LAST_BACKUP=$(cat "$LAST_BACKUP_FILE")
NOW=$(date +%s)
ELAPSED=$((NOW - LAST_BACKUP))
if [ "$ELAPSED" -lt "$BACKUP_COOLDOWN" ]; then
REMAINING=$((BACKUP_COOLDOWN - ELAPSED))
error "Backup cooldown active. Wait ${REMAINING}s before next backup"
exit 0
fi
fi
# Start backup
log "=========================================="
log "Starting FULL SYSTEM BACKUP"
log "=========================================="
# Check NAS connectivity
info "Checking NAS connectivity..."
if ! ping -c 1 -W 2 "$NAS_HOST" >/dev/null 2>&1; then
error "NAS host $NAS_HOST is not reachable"
exit 1
fi
if ! ssh -p "$NAS_PORT" -o ConnectTimeout=5 -o BatchMode=yes \
"${NAS_USER}@${NAS_HOST}" "echo test" >/dev/null 2>&1; then
error "SSH connection to NAS failed"
exit 1
fi
success "NAS is reachable"
# Create backup directory name with timestamp
BACKUP_NAME="full-$(date +%Y%m%d-%H%M%S)"
BACKUP_DEST="${NAS_USER}@${NAS_HOST}:${NAS_PATH}/${BACKUP_NAME}"
info "Backup destination: ${BACKUP_DEST}"
# Build exclude arguments for rsync
EXCLUDE_ARGS=""
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
EXCLUDE_ARGS="$EXCLUDE_ARGS --exclude=$pattern"
done
# Run rsync backup
info "Starting rsync (this may take a while)..."
# shellcheck disable=SC2086
if rsync -avz --delete --numeric-ids \
--rsync-path="mkdir -p ${NAS_PATH}/${BACKUP_NAME} && rsync" \
-e "ssh -p ${NAS_PORT}" \
$EXCLUDE_ARGS \
/ \
"$BACKUP_DEST" >> "$LOG_FILE" 2>&1; then
success "Backup completed successfully!"
# Update last backup timestamp
LAST_BACKUP_FILE="${HOME}/.local/var/backup/last-backup"
mkdir -p "$(dirname "$LAST_BACKUP_FILE")"
date +%s > "$LAST_BACKUP_FILE"
# Log backup size
BACKUP_SIZE=$(ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
"du -sh '${NAS_PATH}/${BACKUP_NAME}' 2>/dev/null | cut -f1" || echo "unknown")
info "Backup size: $BACKUP_SIZE"
# Clean up old backups (keep last N)
info "Cleaning up old backups (keeping last ${RETENTION_COUNT})..."
ssh -p "$NAS_PORT" "${NAS_USER}@${NAS_HOST}" \
"cd '${NAS_PATH}' && ls -t | grep '^full-' | tail -n +$((RETENTION_COUNT + 1)) | xargs -r rm -rf" \
>> "$LOG_FILE" 2>&1 || true
else
error "Backup failed! Check $LOG_FILE for details"
exit 1
fi
log "=========================================="
log "Backup completed at $(date)"
log "=========================================="