140 lines
7.7 KiB
Bash
Executable File
140 lines
7.7 KiB
Bash
Executable File
#!/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 <<EOF > "$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@<TARGET_SERVER_IP>:/home/hamzadoctor/backups/${NC}"
|
||
echo -e "${GREEN}==================================================================${NC}"
|