#!/usr/bin/env bash # ============================================================================== # Sovereign Map Platform - Full Autonomous Backup System # منصة الخرائط السيادية - نظام النسخ الاحتياطي الشامل والأتمتة لنقل السيرفر # ============================================================================== # Architect: Hamza Ayed - Founding Tech Architect & Sovereign Mobility Strategist # Stack: PostGIS 15, Martin Tile Server, GraphHopper, Redis, NestJS, React # ============================================================================== set -euo pipefail # ANSI Color Codes GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[1;33m' RED='\033[0;31m' CYAN='\033[0;36m' NC='\033[0m' # No Color TIMESTAMP=$(date +"%Y%m%d_%H%M%S") ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" BACKUP_BASE_DIR="${1:-$ROOT_DIR/backups}" BACKUP_DIR="$BACKUP_BASE_DIR/sovereign_backup_$TIMESTAMP" ARCHIVE_NAME="sovereign_map_full_backup_$TIMESTAMP.tar.gz" echo -e "${CYAN}==================================================================${NC}" echo -e "${CYAN} 🛡️ منصة خرائط سيرو السيادية | إطلاق النسخ الاحتياطي الشامل${NC}" echo -e "${CYAN}==================================================================${NC}" echo -e "📁 مسار المشروع (Project Root): ${YELLOW}$ROOT_DIR${NC}" echo -e "📦 مجلد النسخة الاحتياطية: ${YELLOW}$BACKUP_DIR${NC}" echo -e "⏰ توقيت البدء: ${YELLOW}$(date)${NC}" echo -e "------------------------------------------------------------------" mkdir -p "$BACKUP_DIR" mkdir -p "$BACKUP_DIR/database" mkdir -p "$BACKUP_DIR/configs" mkdir -p "$BACKUP_DIR/geodata" mkdir -p "$BACKUP_DIR/styles" # 1. PostgreSQL + PostGIS Full Database Dump echo -e "\n${BLUE}[1/5] 🐘 جاري تصدير قاعدة بيانات PostGIS المكانية بالكامل...${NC}" DB_CONTAINER="map-db" if docker ps --format '{{.Names}}' | grep -q "^${DB_CONTAINER}$"; then echo -e " ✅ تم العثور على الحاوية: ${GREEN}$DB_CONTAINER${NC}" # Custom compressed dump (-Fc: Fast, compressed, supports selective restore) echo -e " ⏳ جاري إنشاء Custom Dump المضغوط (موصى به للاستعادة)..." docker exec "$DB_CONTAINER" pg_dump -U mapuser -d mapdb -Fc > "$BACKUP_DIR/database/mapdb_custom.dump" # Plain text SQL schema & functions (for auditing and quick inspection) echo -e " ⏳ جاري تصدير مخطط الجداول والدوال المكانية (Schema-only SQL)..." docker exec "$DB_CONTAINER" pg_dump -U mapuser -d mapdb --schema-only > "$BACKUP_DIR/database/mapdb_schema.sql" DUMP_SIZE=$(du -h "$BACKUP_DIR/database/mapdb_custom.dump" | cut -f1) echo -e " ✅ تم تصدير قاعدة البيانات بنجاح! الحجم: ${GREEN}$DUMP_SIZE${NC}" else echo -e " ${YELLOW}⚠️ تحذير: حاوية $DB_CONTAINER ليست قيد التشغيل حالياً!${NC}" echo -e " سيتم تخطي تفريغ الداتابيز المباشر. إذا كان لديك dump سابق سيتم تضمينه." fi # 2. Redis State Backup echo -e "\n${BLUE}[2/5] ⚡ جاري حفظ حالة الذاكرة اللحظية والتخزين المؤقت (Redis)...${NC}" REDIS_CONTAINER="map-redis" if docker ps --format '{{.Names}}' | grep -q "^${REDIS_CONTAINER}$"; then echo -e " ⏳ تفعيل BGSAVE في Redis..." docker exec "$REDIS_CONTAINER" redis-cli bgsave || true sleep 2 # Copy dump.rdb if accessible docker cp "$REDIS_CONTAINER:/data/dump.rdb" "$BACKUP_DIR/database/redis_dump.rdb" 2>/dev/null || echo " ℹ️ لم يتوفر dump.rdb فوري (ذاكرة كاش خفيفة)." echo -e " ✅ اكتملت إجراءات Redis." fi # 3. Critical Configuration Files echo -e "\n${BLUE}[3/5] ⚙️ جاري نسخ ملفات التكوين والبيئة والهندسة المعمارية...${NC}" cp -f "$ROOT_DIR/.env" "$BACKUP_DIR/configs/.env.backup" 2>/dev/null || echo " ⚠️ لم يُعثر على .env" cp -f "$ROOT_DIR/docker-compose.yml" "$BACKUP_DIR/configs/" 2>/dev/null || true cp -f "$ROOT_DIR/docker-compose.map2.yml" "$BACKUP_DIR/configs/" 2>/dev/null || true cp -rf "$ROOT_DIR/infrastructure/docker" "$BACKUP_DIR/configs/" 2>/dev/null || true # Styles (Vector & Raster styles) cp -f "$ROOT_DIR"/style*.json "$BACKUP_DIR/styles/" 2>/dev/null || true echo -e " ✅ تم حفظ ملفات التكوين وأنماط الخرائط (Styles)." # 4. Sovereign Geodata, Offline Tiles & Routing Graphs echo -e "\n${BLUE}[4/5] 🗺️ جاري أرشفة البيانات الجغرافية السيادية والأوفلاين...${NC}" if [ -d "$ROOT_DIR/data/mbtiles" ]; then echo -e " ⏳ جاري نسخ مربعات الارتفاع والصور الفضائية المحلية (MBTiles)..." cp -rf "$ROOT_DIR/data/mbtiles" "$BACKUP_DIR/geodata/" fi if [ -f "$ROOT_DIR/infrastructure/osm-data/jordan-latest.osm.pbf" ]; then echo -e " ⏳ جاري نسخ حزمة خريطة الأردن المفتوحة (OSM PBF)..." cp -f "$ROOT_DIR/infrastructure/osm-data/jordan-latest.osm.pbf" "$BACKUP_DIR/geodata/" fi if [ -d "$ROOT_DIR/infrastructure/osm-data/routing-packages" ]; then echo -e " ⏳ جاري نسخ حزم توجيه Valhalla المحسوبة محلياً..." cp -rf "$ROOT_DIR/infrastructure/osm-data/routing-packages" "$BACKUP_DIR/geodata/" fi # Add restore script directly into the backup folder for self-contained recovery cp -f "$ROOT_DIR/infrastructure/scripts/restore_sovereign_map.sh" "$BACKUP_DIR/restore_sovereign_map.sh" 2>/dev/null || true chmod +x "$BACKUP_DIR/restore_sovereign_map.sh" 2>/dev/null || true # 5. Manifest & Checksums echo -e "\n${BLUE}[5/5] 🔒 جاري توليد بصمات التحقق والنزاهة الرقمية (SHA256)...${NC}" cat < "$BACKUP_DIR/MANIFEST.txt" Sovereign Map SaaS Platform Backup Manifest =========================================== Timestamp: $TIMESTAMP Backup Date: $(date -u +"%Y-%m-%dT%H:%M:%SZ") Hostname: $(hostname) PostgreSQL Version: 15-3.3 (PostGIS) Project Root: $ROOT_DIR Architect: Hamza Ayed (Siro / Intaleq) EOF cd "$BACKUP_DIR" find . -type f ! -name "checksums.sha256" -exec sha256sum {} + > "$BACKUP_DIR/checksums.sha256" 2>/dev/null || \ find . -type f ! -name "checksums.sha256" -exec shasum -a 256 {} + > "$BACKUP_DIR/checksums.sha256" # Package into a unified compressed tarball echo -e " 📦 ضغط الحزمة الكاملة في ملف أرشيف موحد..." cd "$BACKUP_BASE_DIR" tar -czf "$ARCHIVE_NAME" "sovereign_backup_$TIMESTAMP" TOTAL_ARCHIVE_SIZE=$(du -h "$BACKUP_BASE_DIR/$ARCHIVE_NAME" | cut -f1) echo -e "\n${GREEN}==================================================================${NC}" echo -e "${GREEN} 🎉 تم إنجاز النسخة الاحتياطية بنجاح تام!${NC}" echo -e "${GREEN}==================================================================${NC}" echo -e "📁 مجلد النسخة المفكوكة: ${CYAN}$BACKUP_DIR${NC}" echo -e "📦 ملف الأرشيف المضغوط: ${YELLOW}$BACKUP_BASE_DIR/$ARCHIVE_NAME${NC} (${GREEN}$TOTAL_ARCHIVE_SIZE${NC})" echo -e "🔒 بصمات التحقق: ${CYAN}$BACKUP_DIR/checksums.sha256${NC}" echo -e "------------------------------------------------------------------" echo -e "${YELLOW}🚀 أمر النقل المباشر إلى السيرفر الجديد (One-Liner Transfer Command):${NC}" echo -e "${CYAN}rsync -avzP -e \"ssh -i ~/.ssh/your-key\" \"$BACKUP_BASE_DIR/$ARCHIVE_NAME\" root@:/home/hamzadoctor/backups/${NC}" echo -e "${GREEN}==================================================================${NC}"