#!/bin/bash # Sharenet Backup Script # This script creates backups of databases and configuration files set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration BACKUP_TYPE="${BACKUP_TYPE:-production}" # production or ci-cd APP_NAME="${APP_NAME:-sharenet}" BACKUP_DIR="${BACKUP_DIR:-/opt/APP_NAME/backups}" RETENTION_DAYS="${RETENTION_DAYS:-7}" DRY_RUN="${DRY_RUN:-false}" # Functions log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } show_help() { cat << EOF Sharenet Backup Script Usage: $0 [OPTIONS] Options: --type TYPE Backup type: production or ci-cd (default: production) --app-name NAME Application name (default: sharenet) --backup-dir DIR Backup directory (default: /opt/APP_NAME/backups) --retention DAYS Number of days to keep backups (default: 7) --dry-run Show what would be done without executing --help Show this help message Environment Variables: BACKUP_TYPE Set backup type (production/ci-cd) APP_NAME Set application name BACKUP_DIR Set backup directory path RETENTION_DAYS Set retention period in days DRY_RUN Set to 'true' for dry run mode Examples: $0 # Backup production environment $0 --type ci-cd # Backup CI/CD environment $0 --app-name myapp # Backup specific application $0 --dry-run # Show what would be backed up DRY_RUN=true $0 # Dry run mode EOF } backup_database() { log_info "Backing up database..." if [ "$DRY_RUN" = "true" ]; then log_warning "DRY RUN MODE - No changes will be made" echo "Would run: docker-compose exec -T postgres pg_dump -U \${POSTGRES_USER:-sharenet} \${POSTGRES_DB:-sharenet} > \$BACKUP_DIR/db_backup_\$DATE.sql" return fi # Check if we're in the application directory if [ ! -f "docker-compose.yml" ]; then log_error "docker-compose.yml not found. Please run this script from the application directory." exit 1 fi # Check if postgres container is running if ! docker-compose ps | grep -q "postgres.*Up"; then log_error "PostgreSQL container is not running" exit 1 fi # Create backup directory if it doesn't exist mkdir -p "$BACKUP_DIR" # Get current timestamp local timestamp=$(date +%Y%m%d_%H%M%S) local backup_file="$BACKUP_DIR/db_backup_${timestamp}.sql" # Backup database log_info "Creating database backup: $backup_file" docker-compose exec -T postgres pg_dump -U ${POSTGRES_USER:-sharenet} ${POSTGRES_DB:-sharenet} > "$backup_file" # Verify backup was created if [ -f "$backup_file" ] && [ -s "$backup_file" ]; then log_success "Database backup created: $backup_file" log_info "Backup size: $(du -h "$backup_file" | cut -f1)" else log_error "Database backup failed or is empty" exit 1 fi } backup_configuration() { log_info "Backing up configuration files..." if [ "$DRY_RUN" = "true" ]; then log_warning "DRY RUN MODE - No changes will be made" echo "Would run: tar -czf \$BACKUP_DIR/config_backup_\$DATE.tar.gz .env docker-compose.yml nginx/" return fi # Create backup directory if it doesn't exist mkdir -p "$BACKUP_DIR" # Get current timestamp local timestamp=$(date +%Y%m%d_%H%M%S) local backup_file="$BACKUP_DIR/config_backup_${timestamp}.tar.gz" # Check which files exist local files_to_backup="" [ -f ".env" ] && files_to_backup="$files_to_backup .env" [ -f "docker-compose.yml" ] && files_to_backup="$files_to_backup docker-compose.yml" [ -d "nginx" ] && files_to_backup="$files_to_backup nginx/" if [ -z "$files_to_backup" ]; then log_warning "No configuration files found to backup" return fi # Backup configuration files log_info "Creating configuration backup: $backup_file" tar -czf "$backup_file" $files_to_backup # Verify backup was created if [ -f "$backup_file" ] && [ -s "$backup_file" ]; then log_success "Configuration backup created: $backup_file" log_info "Backup size: $(du -h "$backup_file" | cut -f1)" else log_error "Configuration backup failed or is empty" exit 1 fi } cleanup_old_backups() { log_info "Cleaning up old backups (keeping last $RETENTION_DAYS days)..." if [ "$DRY_RUN" = "true" ]; then log_warning "DRY RUN MODE - No changes will be made" echo "Would run: find \$BACKUP_DIR -name \"*.sql\" -mtime +$RETENTION_DAYS -delete" echo "Would run: find \$BACKUP_DIR -name \"*.tar.gz\" -mtime +$RETENTION_DAYS -delete" return fi # Count files before cleanup local sql_count=$(find "$BACKUP_DIR" -name "*.sql" 2>/dev/null | wc -l) local tar_count=$(find "$BACKUP_DIR" -name "*.tar.gz" 2>/dev/null | wc -l) # Remove old database backups find "$BACKUP_DIR" -name "*.sql" -mtime +$RETENTION_DAYS -delete 2>/dev/null || true # Remove old configuration backups find "$BACKUP_DIR" -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete 2>/dev/null || true # Count files after cleanup local sql_count_after=$(find "$BACKUP_DIR" -name "*.sql" 2>/dev/null | wc -l) local tar_count_after=$(find "$BACKUP_DIR" -name "*.tar.gz" 2>/dev/null | wc -l) log_info "Cleaned up $((sql_count - sql_count_after)) old database backups" log_info "Cleaned up $((tar_count - tar_count_after)) old configuration backups" } backup_production() { log_info "Backing up production environment..." # Check if we're in the application directory if [ ! -f "docker-compose.yml" ]; then log_error "docker-compose.yml not found. Please run this script from the application directory." exit 1 fi # Backup database backup_database # Backup configuration backup_configuration # Clean up old backups cleanup_old_backups log_success "Production backup completed successfully" } backup_ci_cd() { log_info "Backing up CI/CD environment..." # For CI/CD, we mainly backup configuration and registry data log_info "CI/CD backup focuses on configuration and registry data..." # Backup configuration if available if [ -f "docker-compose.yml" ] || [ -f ".env" ] || [ -d "nginx" ]; then backup_configuration else log_warning "No configuration files found for CI/CD backup" fi # Clean up old backups cleanup_old_backups log_success "CI/CD backup completed successfully" } # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in --type) BACKUP_TYPE="$2" shift 2 ;; --app-name) APP_NAME="$2" shift 2 ;; --backup-dir) BACKUP_DIR="$2" shift 2 ;; --retention) RETENTION_DAYS="$2" shift 2 ;; --dry-run) DRY_RUN="true" shift ;; --help|-h) show_help exit 0 ;; *) log_error "Unknown option: $1" show_help exit 1 ;; esac done # Replace APP_NAME placeholder in BACKUP_DIR BACKUP_DIR=$(echo "$BACKUP_DIR" | sed "s/APP_NAME/$APP_NAME/g") # Main backup logic case "$BACKUP_TYPE" in production) backup_production ;; ci-cd) backup_ci_cd ;; *) log_error "Invalid backup type: $BACKUP_TYPE" log_error "Valid types: production, ci-cd" exit 1 ;; esac log_success "Backup completed successfully"