#!/bin/bash # Laravel Timebank Master Backup Script # Orchestrates database and storage backups with health checks # Usage: ./backup-all.sh [backup_type] [options] # backup_type: daily (default), weekly, monthly # options: --storage-only, --database-only, --verify, --notify set -e # Exit on any error # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" BACKUP_ROOT_DIR="$PROJECT_ROOT/backups" LOG_FILE="$BACKUP_ROOT_DIR/backup.log" HEALTH_CHECK_FILE="$BACKUP_ROOT_DIR/health_check.json" # Create backup directories mkdir -p "$BACKUP_ROOT_DIR/logs" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Logging function with colors log() { local level="$1" local message="$2" local timestamp="[$(date '+%Y-%m-%d %H:%M:%S')]" case "$level" in "INFO") echo -e "${timestamp} ${BLUE}[INFO]${NC} $message" | tee -a "$LOG_FILE" ;; "SUCCESS") echo -e "${timestamp} ${GREEN}[SUCCESS]${NC} $message" | tee -a "$LOG_FILE" ;; "WARNING") echo -e "${timestamp} ${YELLOW}[WARNING]${NC} $message" | tee -a "$LOG_FILE" ;; "ERROR") echo -e "${timestamp} ${RED}[ERROR]${NC} $message" | tee -a "$LOG_FILE" ;; *) echo -e "${timestamp} $level $message" | tee -a "$LOG_FILE" ;; esac } # Function to show usage show_usage() { echo "Usage: $0 [backup_type] [options]" echo "" echo "Backup Types:" echo " daily - Daily backup (default)" echo " weekly - Weekly backup" echo " monthly - Monthly backup" echo "" echo "Options:" echo " --storage-only - Backup only storage files" echo " --database-only - Backup only database" echo " --verify - Verify backups after creation" echo " --notify - Send notification on completion" echo " --help - Show this help message" echo "" exit 0 } # Health check function health_check() { log "INFO" "Starting backup health check" local status="healthy" local issues=() # Check disk space (warn if less than 1GB free) local available_space=$(df "$BACKUP_ROOT_DIR" | awk 'NR==2 {print $4}') local available_mb=$((available_space / 1024)) if [ "$available_mb" -lt 1024 ]; then status="warning" issues+=("Low disk space: ${available_mb}MB available") fi # Check if backup scripts exist and are executable for script in "backup-database.sh" "backup-storage.sh"; do if [ ! -x "$SCRIPT_DIR/$script" ]; then status="error" issues+=("Script not found or not executable: $script") fi done # Check environment file if [ ! -f "$PROJECT_ROOT/.env" ]; then status="error" issues+=("Environment file (.env) not found") fi # Generate health check report cat > "$HEALTH_CHECK_FILE" </dev/null; then log "SUCCESS" "Database backup verified: $(basename "$latest_db_backup")" else log "ERROR" "Database backup verification failed: $(basename "$latest_db_backup")" verification_passed=false fi else log "WARNING" "No recent database backup found" fi # Verify storage backups local latest_storage_backup=$(find "$BACKUP_ROOT_DIR/storage" -name "*.tar.gz" -type f -mtime -1 | head -n 1) if [ -n "$latest_storage_backup" ]; then if tar -tzf "$latest_storage_backup" >/dev/null 2>&1; then log "SUCCESS" "Storage backup verified: $(basename "$latest_storage_backup")" else log "ERROR" "Storage backup verification failed: $(basename "$latest_storage_backup")" verification_passed=false fi else log "WARNING" "No recent storage backup found" fi return $verification_passed } # Notification function send_notification() { local subject="$1" local message="$2" local status="$3" # Try multiple notification methods # Method 1: Email (if mail is available and configured) if command -v mail >/dev/null 2>&1; then echo "$message" | mail -s "$subject" "${BACKUP_NOTIFY_EMAIL:-$USER@localhost}" 2>/dev/null || true fi # Method 2: System notification (if notify-send is available) if command -v notify-send >/dev/null 2>&1 && [ -n "$DISPLAY" ]; then notify-send "$subject" "$message" 2>/dev/null || true fi # Method 3: Webhook (if BACKUP_WEBHOOK_URL is set) if [ -n "$BACKUP_WEBHOOK_URL" ] && command -v curl >/dev/null 2>&1; then curl -X POST "$BACKUP_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d "{\"subject\":\"$subject\",\"message\":\"$message\",\"status\":\"$status\"}" \ 2>/dev/null || true fi # Method 4: Log file notification marker log "INFO" "NOTIFICATION: $subject - $message" } # Parse command line arguments BACKUP_TYPE="daily" STORAGE_ONLY=false DATABASE_ONLY=false VERIFY=false NOTIFY=false while [[ $# -gt 0 ]]; do case $1 in daily|weekly|monthly) BACKUP_TYPE="$1" shift ;; --storage-only) STORAGE_ONLY=true shift ;; --database-only) DATABASE_ONLY=true shift ;; --verify) VERIFY=true shift ;; --notify) NOTIFY=true shift ;; --help) show_usage ;; *) log "ERROR" "Unknown option: $1" show_usage ;; esac done # Main execution main() { log "INFO" "============================================" log "INFO" "Starting Timebank $BACKUP_TYPE backup process" log "INFO" "Time: $(date)" log "INFO" "============================================" local start_time=$(date +%s) local backup_success=true local status_message="" # Pre-backup health check if ! health_check; then log "ERROR" "Health check failed, aborting backup" exit 1 fi # Database backup if [ "$STORAGE_ONLY" = false ]; then log "INFO" "Starting database backup..." if "$SCRIPT_DIR/backup-database.sh" "$BACKUP_TYPE"; then log "SUCCESS" "Database backup completed" else log "ERROR" "Database backup failed" backup_success=false fi fi # Storage backup if [ "$DATABASE_ONLY" = false ]; then log "INFO" "Starting storage backup..." if "$SCRIPT_DIR/backup-storage.sh" "$BACKUP_TYPE"; then log "SUCCESS" "Storage backup completed" else log "ERROR" "Storage backup failed" backup_success=false fi fi # Backup verification if [ "$VERIFY" = true ]; then if verify_backups; then log "SUCCESS" "Backup verification passed" else log "WARNING" "Backup verification had issues" fi fi # Calculate execution time local end_time=$(date +%s) local execution_time=$((end_time - start_time)) local execution_time_formatted=$(date -d@$execution_time -u +%H:%M:%S) # Generate final status if [ "$backup_success" = true ]; then status_message="Backup completed successfully in $execution_time_formatted" log "SUCCESS" "$status_message" # Generate backup summary log "INFO" "Backup Summary:" log "INFO" " - Type: $BACKUP_TYPE" log "INFO" " - Duration: $execution_time_formatted" log "INFO" " - Location: $BACKUP_ROOT_DIR" if [ "$NOTIFY" = true ]; then send_notification "Timebank Backup Success" "$status_message" "success" fi else status_message="Backup completed with errors in $execution_time_formatted" log "ERROR" "$status_message" if [ "$NOTIFY" = true ]; then send_notification "Timebank Backup Failed" "$status_message" "error" fi exit 1 fi log "INFO" "============================================" log "INFO" "Backup process finished" log "INFO" "============================================" } # Trap to handle interrupts trap 'log "ERROR" "Backup interrupted by user"; exit 1' INT TERM # Run main function main "$@"