Server Backup Script
devopsAutomated backup script using Restic (restic.net) for encrypted, deduplicated backups to AWS S3. Backs up web applications and MySQL databases with Slack notifications, error handling, and automatic retention policies (7 daily, 4 weekly, 6 monthly).
bash
restic
aws-s3
mysql
Files
backup.sh
1#!/bin/bash 2 3# ============================================ 4# Server Backup Script 5# 6# Automated backup for web servers using Restic 7# (https://restic.net) with AWS S3 storage. 8# 9# Features:10# - MySQL database dumps11# - Encrypted, deduplicated backups12# - Slack notifications (success/failure)13# - Automatic retention policies14#15# Schedule: Daily via cron (e.g., 0 3 * * *)16# ============================================17 18# AWS S3 Configuration19export AWS_ACCESS_KEY_ID="your-access-key"20export AWS_SECRET_ACCESS_KEY="your-secret-key"21export RESTIC_REPOSITORY="s3:s3.eu-central-1.amazonaws.com/your-bucket"22export RESTIC_PASSWORD="your-restic-password"23 24LOG_FILE="/var/log/backup.log"25SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"26WEB_ROOT="/var/www"27 28# Slack notification function29notify_slack() {30 local status=$131 local message=$232 local color=$([[ "$status" == "success" ]] && echo "good" || echo "danger")33 local emoji=$([[ "$status" == "success" ]] && echo ":white_check_mark:" || echo ":x:")34 35 curl -s -X POST "$SLACK_WEBHOOK" \36 -H 'Content-type: application/json' \37 -d "{38 \"attachments\": [{39 \"color\": \"$color\",40 \"text\": \"$emoji *Server Backup*\n$message\",41 \"footer\": \"Restic Backup\",42 \"ts\": $(date +%s)43 }]44 }" > /dev/null45}46 47# Error handler48handle_error() {49 local error_msg="$1"50 echo "$(date): ERROR - $error_msg" >> $LOG_FILE51 notify_slack "error" "Backup failed: $error_msg"52 rm -rf /tmp/db_backups 2>/dev/null53 exit 154}55 56# Set error trap57trap 'handle_error "Unexpected error on line $LINENO"' ERR58 59echo "$(date): Starting backup" >> $LOG_FILE60 61# Dump databases (excluding system DBs)62echo "$(date): Dumping databases..." >> $LOG_FILE63mkdir -p /tmp/db_backups64mysql -N -e "SHOW DATABASES" | grep -v -E "^(information_schema|performance_schema|mysql|sys)$" | while read db; do65 mysqldump --single-transaction --no-tablespaces "$db" > "/tmp/db_backups/${db}.sql" || handle_error "Failed to dump database: $db"66done67 68# Create backup with restic69echo "$(date): Creating restic backup..." >> $LOG_FILE70restic backup \71 --verbose \72 --exclude "$WEB_ROOT/*/node_modules" \73 --exclude "$WEB_ROOT/*/vendor" \74 --exclude "$WEB_ROOT/*/.git" \75 --exclude "$WEB_ROOT/*/storage/logs/*" \76 --exclude "$WEB_ROOT/*/storage/framework/cache/*" \77 --exclude "$WEB_ROOT/*/storage/framework/sessions/*" \78 --exclude "$WEB_ROOT/*/.cache" \79 "$WEB_ROOT" \80 /tmp/db_backups \81 2>> $LOG_FILE82 83# Cleanup database dumps84rm -rf /tmp/db_backups85 86# Prune old backups (keep 7 daily, 4 weekly, 6 monthly)87echo "$(date): Pruning old backups..." >> $LOG_FILE88restic forget \89 --keep-daily 7 \90 --keep-weekly 4 \91 --keep-monthly 6 \92 --prune \93 2>> $LOG_FILE94 95echo "$(date): Backup completed successfully" >> $LOG_FILE96notify_slack "success" "Backup completed successfully"