403 lines
20 KiB
Markdown
403 lines
20 KiB
Markdown
# دليل الانتقال السيادي الشامل وخطة استعادة المنصة والنسخ الاحتياطي
|
|
## Sovereign Map Platform: Server Migration, Disaster Recovery & Offline Hosting Runbook
|
|
|
|
**المهندس المعماري والاستراتيجي للمنظومة:** حمزة عايد (Hamza Ayed)
|
|
*Founding Tech Architect & Sovereign Mobility Strategist*
|
|
**المنصة:** سيرو للخرائط السيادية والذكاء المكاني والتكتيكي (Siro Sovereign Map Engine / Map-SaaS)
|
|
**تاريخ التوثيق:** أيلول (سبتمبر) 2026
|
|
**الإصدار:** v2.4 Enterprise Sovereign Edition
|
|
|
|
---
|
|
|
|
## 1. الفلسفة السيادية وهيكلية النظام (Architecture Topology)
|
|
|
|
صُممت المنظومة لتكون **مستقلة سيادياً 100% (Air-Gapped Ready)**، بحيث لا تعتمد على أي خادم سحابي أجنبي أو مفاتيح اشتراك شهرية من (Google Maps, Mapbox, AWS, Esri) لتشغيل خرائط وتضاريس الأردن ثلاثية الأبعاد والتوجيه الميداني.
|
|
|
|
```
|
|
[ Internet / VPN / Tactical Mesh ]
|
|
│
|
|
[ CloudPanel / Nginx ]
|
|
(SSL: map-saas.intaleqapp.com, tiles, api)
|
|
│
|
|
┌──────────────┬──────────────┬────────┴──────┬──────────────┬──────────────┐
|
|
│ :3201 │ :3204 │ :3200 │ :3202 │ :8989 │
|
|
┌────┴─────┐ ┌──────┴──────┐ ┌─────┴──────┐ ┌──────┴──────┐ ┌─────┴──────┐
|
|
│ map-web │ │map-dashboard│ │ map-api │ │ map-martin │ │map-routing │
|
|
│ (React + │ │(Admin/Usage │ │ (NestJS + │ │(Rust Vector │ │(GraphHopper│
|
|
│ MapLibre)│ │ Developer) │ │ Spatial) │ │ + MBTiles) │ │ Engine) │
|
|
└────┬─────┘ └─────────────┘ └─────┬──────┘ └──────┬──────┘ └─────┬──────┘
|
|
│ │ │ │
|
|
│ ▼ ▼ │
|
|
│ ┌──────────────┬──────────────┐ │
|
|
│ │ map-db │ map-redis │ │
|
|
│ │(PostGIS 15 + │ (Cache & Bus │ │
|
|
│ │ Topology) │ Port 6381) │ │
|
|
│ └──────────────┴──────────────┘ │
|
|
│ │
|
|
└──────────────────────────[ Volumes ]───────────────────────┘
|
|
• postgres_data (جداول وخطوط الكنتور والطرق)
|
|
• data/mbtiles (تضاريس 3D DEM + أقمار صناعية)
|
|
• infrastructure/osm-data (شبكة الطرق الخام)
|
|
```
|
|
|
|
---
|
|
|
|
## 2. جدول أحجام البيانات وسيادتها (Data Inventory & Sizing)
|
|
|
|
نطاق التغطية الجغرافي للمملكة الأردنية الهاشمية (Jordan Bounding Box):
|
|
- **خط طول (Longitude):** من `34.8° E` إلى `39.3° E`
|
|
- **دائرة عرض (Latitude):** من `29.1° N` إلى `33.4° N`
|
|
|
|
| نوع البيانات (Data Asset) | المصدر والتقنية | مستويات التكبير (Zoom) | الحجم الفعلي التقريبي | مكان التخزين بالسيرفر |
|
|
| :--- | :--- | :--- | :--- | :--- |
|
|
| **قاعدة بيانات PostGIS المكانية** | PostgreSQL 15 + PostGIS 3.3 | N/A (Geometries) | ~1.5 - 2.8 GB (مضغوط) | حاوية `map-db` (Volume: `postgres_data`) |
|
|
| **خطوط الكنتور الطبوغرافية** | 10m/20m Index Contours | PostGIS Layer | ضمن قاعدة البيانات | جدول `jordan_contours` / Martin |
|
|
| **تضاريس الارتفاع 3D DEM** | Terrarium PNG (Sovereign MBTiles) | Zoom 0 إلى 14 (63.6k بلاطة) | ~930 MB | `data/mbtiles/jordan-dem.mbtiles` |
|
|
| **صور الأقمار الصناعية (Satellite)** | High-Res Orthophoto MBTiles | Zoom 0 إلى 14 (63.6k بلاطة) | ~1.5 GB (~6 GB لـ z15) | `data/mbtiles/jordan-satellite.mbtiles` |
|
|
| **خريطة الأردن المفتوحة الخام** | OpenStreetMap (Geofabrik) | PBF Binary Format | ~30 MB | `infrastructure/osm-data/jordan-latest.osm.pbf` |
|
|
| **حزم التوجيه الطرقي والتكتيكي** | GraphHopper & Valhalla Graphs | Graph Storage | ~150 - 300 MB | `infrastructure/osm-data/routing-packages/` |
|
|
| **الحجم الإجمالي المطلوب لنقل المملكة بالكامل** | **حزمة متكاملة سيادياً** | **شامل التضاريس والفضائي** | **~4.5 إلى 9 GB فقط!** | يمكن نقله في دقائق عبر SSH |
|
|
|
|
---
|
|
|
|
## 3. المرحلة الأولى: أخذ النسخة الاحتياطية من السيرفر الحالي (Source Server Backup)
|
|
|
|
### الخيار (أ): التشغيل التلقائي عبر السكربت الذكي (Automated Script)
|
|
قمنا ببرمجة سكربت أوتوماتيكي يقوم بتفريغ الداتابيز، وفحص الـ Redis، ونسخ الإعدادات والخرائط وتوليد بصمات `SHA256`:
|
|
|
|
```bash
|
|
# الانتقال لمسار المشروع
|
|
cd /home/hamzadoctor/app
|
|
|
|
# تشغيل سكربت النسخ الاحتياطي الشامل
|
|
./infrastructure/scripts/backup_sovereign_map.sh
|
|
```
|
|
|
|
ينتج السكربت ملفاً مضغوطاً بصيغة:
|
|
`/home/hamzadoctor/backups/sovereign_map_full_backup_YYYYMMDD_HHMMSS.tar.gz`
|
|
|
|
---
|
|
|
|
### الخيار (ب): الإجراء اليدوي خطوة بخطوة (Manual Fallback)
|
|
|
|
إذا أردت تنفيذ النسخ يدوياً بأوامر مباشرة:
|
|
|
|
#### 1. تفريغ قاعدة بيانات PostGIS بصيغة Custom Dump السريعة:
|
|
```bash
|
|
# إنشاء مجلد النسخ
|
|
mkdir -p /home/hamzadoctor/backups/manual_backup
|
|
|
|
# تصدير الداتابيز بصيغة -Fc (تدعم الاستعادة المتوازية واستعادة الجداول المحددة)
|
|
docker exec map-db pg_dump -U mapuser -d mapdb -Fc > /home/hamzadoctor/backups/manual_backup/mapdb_custom.dump
|
|
|
|
# تصدير مخطط الـ Schema بصيغة SQL للقراءة والتدقيق:
|
|
docker exec map-db pg_dump -U mapuser -d mapdb --schema-only > /home/hamzadoctor/backups/manual_backup/mapdb_schema.sql
|
|
```
|
|
|
|
#### 2. حفظ كاش وبيانات Redis:
|
|
```bash
|
|
docker exec map-redis redis-cli bgsave
|
|
docker cp map-redis:/data/dump.rdb /home/hamzadoctor/backups/manual_backup/redis_dump.rdb
|
|
```
|
|
|
|
#### 3. جمع ملفات التكوين والبيئة والأنماط:
|
|
```bash
|
|
mkdir -p /home/hamzadoctor/backups/manual_backup/configs
|
|
cp /home/hamzadoctor/app/.env /home/hamzadoctor/backups/manual_backup/configs/.env.backup
|
|
cp /home/hamzadoctor/app/docker-compose*.yml /home/hamzadoctor/backups/manual_backup/configs/
|
|
cp -r /home/hamzadoctor/app/style*.json /home/hamzadoctor/backups/manual_backup/configs/
|
|
```
|
|
|
|
#### 4. ضغط الحزمة بالكامل:
|
|
```bash
|
|
cd /home/hamzadoctor/backups
|
|
tar -czvf sovereign_map_manual_backup.tar.gz manual_backup/
|
|
```
|
|
|
|
---
|
|
|
|
## 4. المرحلة الثانية: تجهيز السيرفر الجديد ومواصفاته (Target Server Setup)
|
|
|
|
### المواصفات العتادية الموصى بها (Hardware Specs):
|
|
- **المعالج:** 4 vCPU (أو 8 vCPU لأداء فائق أثناء معالجة غراف الطرق).
|
|
- **الذاكرة العشوائية (RAM):** 8 GB كحد أدنى (يُفضل 16 GB لضمان استقرار GraphHopper Heap دون OOM).
|
|
- **التخزين:** 80 GB NVMe SSD (لقاعدة البيانات والتضاريس وسجلات النظام).
|
|
- **نظام التشغيل:** Ubuntu 22.04 LTS أو Ubuntu 24.04 LTS x86_64.
|
|
|
|
### إعداد السيرفر الجديد برمجياً:
|
|
|
|
#### 1. تحديث النظام وتثبيت حزم الأدوات الأساسية:
|
|
```bash
|
|
sudo apt update && sudo apt upgrade -y
|
|
sudo apt install -y curl wget git rsync htop ufw unzip jq sqlite3
|
|
```
|
|
|
|
#### 2. ضبط ملف المبادلة (Swap File - حاسم جداً لمنع OOM):
|
|
بسبب استهلاك محرك GraphHopper للذاكرة أثناء بناء شبكة التوجيه، يجب إنشاء 4GB Swap:
|
|
```bash
|
|
sudo fallocate -l 4G /swapfile
|
|
sudo chmod 600 /swapfile
|
|
sudo mkswap /swapfile
|
|
sudo swapon /swapfile
|
|
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
|
|
```
|
|
|
|
#### 3. تثبيت Docker Engine و Docker Compose V2 الرسمي:
|
|
```bash
|
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
|
sudo sh get-docker.sh
|
|
sudo usermod -aG docker $USER
|
|
```
|
|
|
|
#### 4. ضبط الجدار الناري (UFW Firewall):
|
|
```bash
|
|
sudo ufw default deny incoming
|
|
sudo ufw default allow outgoing
|
|
sudo ufw allow 22/tcp # SSH
|
|
sudo ufw allow 80/tcp # HTTP (Reverse Proxy)
|
|
sudo ufw allow 443/tcp # HTTPS (SSL)
|
|
sudo ufw enable
|
|
```
|
|
*(ملاحظة أمنية: لا تفتح المنافذ الداخلية 5432، 6381، 3200، 3201، 3202 للعامة، بل اتركها خلف الـ Nginx Reverse Proxy الداخلي).*
|
|
|
|
---
|
|
|
|
## 5. المرحلة الثالثة: نقل البيانات بين السيرفرين (Direct Server-to-Server Sync)
|
|
|
|
### الطريقة الموصى بها: النقل المباشر فائق السرعة عبر `rsync`:
|
|
|
|
نفّذ الأمر التالي من السيرفر المصدر (أو من جهاز التحكم الخاص بك):
|
|
|
|
```bash
|
|
# نقل ملف النسخة الاحتياطية الشاملة إلى السيرفر الجديد
|
|
rsync -avzP -e "ssh -i ~/.ssh/your-key" \
|
|
/home/hamzadoctor/backups/sovereign_map_full_backup_*.tar.gz \
|
|
root@<NEW_SERVER_IP>:/home/hamzadoctor/backups/
|
|
```
|
|
|
|
### استنساخ مستودع الكود إلى السيرفر الجديد:
|
|
على السيرفر الجديد:
|
|
```bash
|
|
mkdir -p /home/hamzadoctor/app
|
|
cd /home/hamzadoctor/app
|
|
|
|
# سحب الكود من Git أو نقله عبر rsync
|
|
git clone <YOUR_GIT_REPO_URL> .
|
|
# أو نسخ ملفات المشروع عبر rsync من السيرفر القديم:
|
|
# rsync -avzP --exclude 'node_modules' --exclude '.git' root@<OLD_SERVER_IP>:/home/hamzadoctor/app/ /home/hamzadoctor/app/
|
|
```
|
|
|
|
---
|
|
|
|
## 6. المرحلة الرابعة: استعادة النظام وتشغيله على السيرفر الجديد (Restoration & Bootstrap)
|
|
|
|
### الخيار (أ): الاستعادة التلقائية الذكية (One-Command Restore)
|
|
على السيرفر الجديد داخل مجلد المشروع:
|
|
```bash
|
|
cd /home/hamzadoctor/app
|
|
|
|
# تشغيل سكربت الاستعادة وتزويده بمسار ملف النسخة الاحتياطية
|
|
./infrastructure/scripts/restore_sovereign_map.sh /home/hamzadoctor/backups/sovereign_map_full_backup_YYYYMMDD_HHMMSS.tar.gz
|
|
```
|
|
يقوم هذا السكربت بـ:
|
|
1. استخراج الإعدادات والتأكد من ملف `.env`.
|
|
2. تشغيل حاوية `map-db` والانتظار حتى تصبح جاهزة للحقن.
|
|
3. تفعيل إضافات PostGIS واستعادة كافة الجداول والفهارس المكانية بدقة.
|
|
4. تنفيذ `VACUUM ANALYZE` لضمان أقصى سرعة لاستعلامات الخرائط.
|
|
5. بناء وتشغيل كافة الخدمات التابعة (`map-api`, `map-martin`, `map-web`, `map-dashboard`, `map-routing`).
|
|
6. فحص صحة المنافذ والتأكد من استجابتها.
|
|
|
|
---
|
|
|
|
### الخيار (ب): الاستعادة اليدوية خطوة بخطوة
|
|
|
|
```bash
|
|
cd /home/hamzadoctor/app
|
|
|
|
# 1. تجهيز ملف البيئة
|
|
cp .env.example .env
|
|
# قم بمراجعة وتعديل كلمات المرور في .env إذا أردت
|
|
|
|
# 2. تشغيل قاعدة البيانات والكاش
|
|
docker compose up -d db redis
|
|
|
|
# 3. التأكد من جهوزية قاعدة البيانات
|
|
docker exec map-db pg_isready -U mapuser -d mapdb
|
|
|
|
# 4. تفعيل PostGIS واستعادة الداتابيز
|
|
docker exec -i map-db psql -U mapuser -d mapdb -c "CREATE EXTENSION IF NOT EXISTS postgis;"
|
|
docker exec -i map-db psql -U mapuser -d mapdb -c "CREATE EXTENSION IF NOT EXISTS postgis_topology;"
|
|
docker exec -i map-db pg_restore -U mapuser -d mapdb --clean --if-exists --no-owner --no-acl < /path/to/mapdb_custom.dump
|
|
docker exec -i map-db psql -U mapuser -d mapdb -c "VACUUM ANALYZE;"
|
|
|
|
# 5. تشغيل وبناء بقية الخدمات
|
|
docker compose up -d --build api martin web dashboard routing
|
|
```
|
|
|
|
---
|
|
|
|
## 7. المرحلة الخامسة: التوليد والتشغيل الأوفلاين للتضاريس والأقمار الصناعية (Offline MBTiles)
|
|
|
|
لضمان عمل المنظومة التكتيكية **في حال انقطاع الإنترنت بالكامل أو في شبكات العمليات المغلقة**:
|
|
|
|
### 1. تشغيل مولدات التخزين السيادية (Pre-seeding Jordan Tiles):
|
|
قمنا بتجهيز سكربتات بايثون متعددة المسارات (Multi-threaded) لتحميل وتخزين مربعات الأردن كاملة في ملفات SQLite MBTiles قياسية:
|
|
|
|
```bash
|
|
cd /home/hamzadoctor/app
|
|
|
|
# إنشاء مجلد ملفات MBTiles
|
|
mkdir -p data/mbtiles
|
|
|
|
# تحميل وتخزين تضاريس الأردن ثلاثية الأبعاد (DEM z0 إلى z14 ~ 930MB)
|
|
python3 infrastructure/scripts/seed_jordan_dem.py --format mbtiles --threads 16 --output data/mbtiles/jordan-dem.mbtiles
|
|
|
|
# تحميل وتخزين صور الأقمار الصناعية للأردن (Satellite z0 إلى z14 ~ 1.5GB)
|
|
python3 infrastructure/scripts/seed_jordan_satellite.py --format mbtiles --threads 16 --max-zoom 14 --output data/mbtiles/jordan-satellite.mbtiles
|
|
```
|
|
|
|
### 2. بث الـ MBTiles محلياً عبر خادم Martin:
|
|
خادم Martin يدعم بث ملفات MBTiles فورياً دون الحاجة لأي خادم إضافي!
|
|
في ملف `docker-compose.yml`، نقوم بربط مجلد `data/mbtiles`:
|
|
```yaml
|
|
martin:
|
|
image: maplibre/martin:latest
|
|
container_name: map-martin
|
|
ports:
|
|
- "3202:3000"
|
|
environment:
|
|
- WATCH_DB=true
|
|
volumes:
|
|
- ./data/mbtiles:/mbtiles:ro
|
|
command: ["/mbtiles", "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}"]
|
|
```
|
|
بذلك يوفر خادم Martin الروابط المحلية التالية بسرعة استجابة فائقة (Sub-millisecond):
|
|
- **تضاريس DEM 3D:** `https://tiles.intaleqapp.com/jordan-dem/{z}/{x}/{y}`
|
|
- **صور الأقمار:** `https://tiles.intaleqapp.com/jordan-satellite/{z}/{x}/{y}`
|
|
- **الطبقات المتجهة والكنتور:** `https://tiles.intaleqapp.com/jordan_contours/{z}/{x}/{y}`
|
|
|
|
---
|
|
|
|
## 8. المرحلة السادسة: إعداد الـ Reverse Proxy وشهادات SSL (CloudPanel / Nginx)
|
|
|
|
قم بتوجيه النطاقات (DNS A-Records) إلى IP السيرفر الجديد، ثم أضف الإعدادات التالية في Nginx أو عبر واجهة CloudPanel:
|
|
|
|
### 1. بوابة الويب والمناورة التكتيكية (`map-saas.intaleqapp.com`):
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name map-saas.intaleqapp.com;
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name map-saas.intaleqapp.com;
|
|
|
|
# شهادات Let's Encrypt
|
|
ssl_certificate /etc/letsencrypt/live/map-saas.intaleqapp.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/map-saas.intaleqapp.com/privkey.pem;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:3201;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection 'upgrade';
|
|
proxy_set_header Host $host;
|
|
proxy_cache_bypass $http_upgrade;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. خادم مربعات الخرائط والتضاريس السيادي (`tiles.intaleqapp.com`):
|
|
```nginx
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name tiles.intaleqapp.com;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/tiles.intaleqapp.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/tiles.intaleqapp.com/privkey.pem;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:3202;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
# تفعيل كاش المتصفح للبلاطات
|
|
expires 7d;
|
|
add_header Cache-Control "public, no-transform";
|
|
add_header Access-Control-Allow-Origin *;
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. الواجهة الخلفية والذكاء المكاني (`api.map.intaleqapp.com`):
|
|
```nginx
|
|
location / {
|
|
proxy_pass http://127.0.0.1:3200;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 9. الفحوصات والتدقيق التشغيلي بعد الانتقال (Verification Checklist)
|
|
|
|
نفّذ هذه الأوامر على السيرفر الجديد للتأكد من سلامة كافة الأجزاء بنسبة 100%:
|
|
|
|
```bash
|
|
# 1. فحص حاويات Docker
|
|
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
|
|
|
# 2. فحص استجابة الـ API
|
|
curl -I http://localhost:3200/api/health
|
|
|
|
# 3. فحص خادم البلاطات Martin
|
|
curl -s http://localhost:3202/catalog | jq .
|
|
|
|
# 4. فحص اتصال قاعدة البيانات PostGIS والتأكد من جداول خطوط الكنتور
|
|
docker exec -it map-db psql -U mapuser -d mapdb -c "
|
|
SELECT table_name, (xpath('/row/cnt/text()', xml_count))[1]::text::int as row_count
|
|
FROM (
|
|
SELECT table_name, query_to_xml(format('select count(*) as cnt from %I', table_name), false, true, '') as xml_count
|
|
FROM information_schema.tables
|
|
WHERE table_schema = 'public' AND table_name IN ('jordan_contours', 'planet_osm_roads', 'planet_osm_line')
|
|
) t;
|
|
"
|
|
|
|
# 5. فحص محرك التوجيه GraphHopper
|
|
curl -I http://localhost:8989/health
|
|
```
|
|
|
|
---
|
|
|
|
## 10. جدول الصيانة والنسخ الاحتياطي التلقائي اليومي (Daily Automated Cron)
|
|
|
|
لضمان عدم فقدان أي بيانات مستقبلية، قم بإضافة مهمة مجدولة (Cron Job) لتوليد نسخة احتياطية مشفرة كل ليلة في الساعة 3:00 فجراً والاحتفاظ بآخر 7 أيام تلقائياً:
|
|
|
|
```bash
|
|
# فتح جدول المهام
|
|
crontab -e
|
|
```
|
|
أضف السطر التالي:
|
|
```cron
|
|
0 3 * * * /home/hamzadoctor/app/infrastructure/scripts/backup_sovereign_map.sh /home/hamzadoctor/backups >> /home/hamzadoctor/backups/backup.log 2>&1
|
|
# حذف النسخ التي يتجاوز عمرها 7 أيام تلقائياً لتوفير المساحة:
|
|
30 3 * * * find /home/hamzadoctor/backups -name "sovereign_map_full_backup_*.tar.gz" -mtime +7 -delete
|
|
```
|
|
|
|
---
|
|
|
|
## 11. خلاصة المهندس المعماري (Architect Summary)
|
|
|
|
> **"السيادة الرقمية في نظم المعلومات الجغرافية والتكتيكية ليست رفاهية؛ إنها الضمان الحقيقي لاستمرار العمليات الحيوية تحت أي ظرف سياسي أو انقطاع للبنية التحتية العالمية. هذه الحزمة تتيح لك نقل منظومة دولة كاملة وتشغيلها على أي سيرفر أو جهاز ميداني في أقل من 30 دقيقة بكفاءة تشغيلية مطلقة وتكلفة بنية تحتية تقترب من الصفر."**
|
|
> — *حمزة عايد (Hamza Ayed)*
|