#!/bin/bash # ============================================================================= # IGNY8 Full Backup Script # ============================================================================= # Creates complete backup: database + configuration + code snapshot # Usage: ./backup-full.sh [weekly|monthly] # ============================================================================= set -e # Configuration BACKUP_TYPE="${1:-weekly}" TIMESTAMP=$(date +%Y%m%d_%H%M%S) APP_DIR="/data/app/igny8" BACKUP_ROOT="/data/backups" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log() { echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1" } log_success() { log "${GREEN}✅ $1${NC}" } log_error() { log "${RED}❌ $1${NC}" } # Determine backup directory case $BACKUP_TYPE in weekly) BACKUP_DIR="${BACKUP_ROOT}/weekly/week_$(date +%Y_%W)" ;; monthly) BACKUP_DIR="${BACKUP_ROOT}/monthly/$(date +%Y_%m)" ;; *) log_error "Invalid backup type. Use: weekly or monthly" exit 1 ;; esac mkdir -p "${BACKUP_DIR}" echo "==========================================" echo "IGNY8 Full Backup" echo "==========================================" echo "Type: ${BACKUP_TYPE}" echo "Destination: ${BACKUP_DIR}" echo "" # Step 1: Database backup log "Step 1/4: Backing up database..." /data/app/igny8/scripts/ops/backup-db.sh "${BACKUP_TYPE}" || { log_error "Database backup failed" exit 1 } # Step 2: Configuration backup log "Step 2/4: Backing up configuration files..." CONFIG_BACKUP="${BACKUP_DIR}/config_${TIMESTAMP}.tar.gz" tar -czf "${CONFIG_BACKUP}" \ -C "${APP_DIR}" \ .env \ .env.staging 2>/dev/null \ docker-compose.app.yml \ docker-compose.staging.yml 2>/dev/null \ --ignore-failed-read || true if [[ -f "${CONFIG_BACKUP}" ]]; then log_success "Config backup: ${CONFIG_BACKUP}" else log_error "Config backup failed" fi # Step 3: Code snapshot (without node_modules, __pycache__, etc.) log "Step 3/4: Creating code snapshot..." CODE_BACKUP="${BACKUP_DIR}/code_${TIMESTAMP}.tar.gz" tar -czf "${CODE_BACKUP}" \ -C "/data/app" \ --exclude='igny8/node_modules' \ --exclude='igny8/frontend/node_modules' \ --exclude='igny8/__pycache__' \ --exclude='igny8/**/__pycache__' \ --exclude='igny8/*.pyc' \ --exclude='igny8/**/*.pyc' \ --exclude='igny8/.git' \ --exclude='igny8/backend/staticfiles' \ --exclude='igny8/frontend/dist' \ --exclude='igny8/backend/media' \ --exclude='igny8/logs' \ igny8/ 2>/dev/null || true if [[ -f "${CODE_BACKUP}" ]]; then local size=$(du -h "${CODE_BACKUP}" | cut -f1) log_success "Code backup: ${CODE_BACKUP} (${size})" else log_error "Code backup failed" fi # Step 4: Media files (if they exist) log "Step 4/4: Backing up media files..." MEDIA_DIR="${APP_DIR}/backend/media" if [[ -d "${MEDIA_DIR}" ]] && [[ "$(ls -A ${MEDIA_DIR})" ]]; then MEDIA_BACKUP="${BACKUP_DIR}/media_${TIMESTAMP}.tar.gz" tar -czf "${MEDIA_BACKUP}" -C "${APP_DIR}/backend" media/ 2>/dev/null || true if [[ -f "${MEDIA_BACKUP}" ]]; then local media_size=$(du -h "${MEDIA_BACKUP}" | cut -f1) log_success "Media backup: ${MEDIA_BACKUP} (${media_size})" fi else log "No media files to backup" fi # Create manifest MANIFEST="${BACKUP_DIR}/manifest.txt" cat > "${MANIFEST}" << EOF IGNY8 Full Backup Manifest =========================== Timestamp: ${TIMESTAMP} Type: ${BACKUP_TYPE} Server: $(hostname) Files: $(ls -la "${BACKUP_DIR}") Sizes: $(du -sh "${BACKUP_DIR}"/*) Git Info: $(cd "${APP_DIR}" && git log -1 --format='Commit: %H%nDate: %ci%nMessage: %s' 2>/dev/null || echo 'Not a git repo') EOF echo "" echo "==========================================" echo "BACKUP COMPLETE" echo "==========================================" echo "Location: ${BACKUP_DIR}" echo "" echo "Contents:" ls -lh "${BACKUP_DIR}" echo "" echo "Total size: $(du -sh ${BACKUP_DIR} | cut -f1)" echo "=========================================="