النشر الإنتاجي
يغطي هذا الدليل كل ما يلزم لتشغيل Fenfa في بيئة إنتاجية: الوكيل العكسي مع TLS وإعداد الرمز الآمن واستراتيجية النسخ الاحتياطي والمراقبة.
الهندسة المعمارية
graph LR
USER["Users / CI Pipeline"]
PROXY["Reverse Proxy<br/>Nginx / Caddy<br/>TLS Termination"]
FENFA["Fenfa Server<br/>:8000"]
DB["SQLite<br/>/data/fenfa.db"]
STORAGE["File Storage<br/>Local or S3/R2"]
USER -->|HTTPS :443| PROXY
PROXY -->|HTTP :8000| FENFA
FENFA --> DB
FENFA --> STORAGEإعداد الوكيل العكسي
Caddy (موصى به)
يحصل Caddy تلقائياً على شهادات TLS من Let's Encrypt ويجدّدها:
dist.example.com {
reverse_proxy localhost:8000
}هذا كل شيء. يتولى Caddy HTTPS وHTTP/2 وإدارة الشهادات تلقائياً.
Nginx
server {
listen 443 ssl http2;
server_name dist.example.com;
ssl_certificate /etc/letsencrypt/live/dist.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dist.example.com/privkey.pem;
client_max_body_size 2G;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
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;
# Large file uploads
proxy_request_buffering off;
proxy_read_timeout 600s;
}
}
server {
listen 80;
server_name dist.example.com;
return 301 https://$host$request_uri;
}client_max_body_size
اضبط client_max_body_size بحجم كافٍ لأكبر بنيات لديك. يمكن أن تكون ملفات IPA وAPK مئات الميغابايتات. يسمح المثال أعلاه بما يصل إلى 2 غيغابايت.
الحصول على شهادة TLS
باستخدام Certbot مع Nginx:
sudo certbot --nginx -d dist.example.comباستخدام Certbot المستقل:
sudo certbot certonly --standalone -d dist.example.comقائمة تدقيق الأمان
1. تغيير الرموز الافتراضية
أنشئ رموزاً عشوائية آمنة:
# إنشاء رمز عشوائي من 32 حرفاً
openssl rand -hex 16اضبطها عبر متغيرات البيئة أو الإعداد:
FENFA_ADMIN_TOKEN=$(openssl rand -hex 16)
FENFA_UPLOAD_TOKEN=$(openssl rand -hex 16)2. الربط بـ localhost
قدّم Fenfa فقط عبر الوكيل العكسي:
ports:
- "127.0.0.1:8000:8000" # Not 0.0.0.0:80003. تعيين النطاق الأساسي
أعدّ النطاق العام الصحيح لـ manifests iOS والردود:
FENFA_PRIMARY_DOMAIN=https://dist.example.comManifests iOS
إذا كان primary_domain خاطئاً، سيفشل تثبيت iOS OTA. يحتوي ملف manifest plist على روابط تنزيل يستخدمها iOS لجلب ملف IPA. يجب أن تكون هذه الروابط قابلة للوصول من جهاز المستخدم.
4. رموز رفع منفصلة
أصدر رموز رفع مختلفة لخطوط CI/CD أو أعضاء الفريق المختلفين:
{
"auth": {
"upload_tokens": [
"token-for-ios-pipeline",
"token-for-android-pipeline",
"token-for-desktop-pipeline"
],
"admin_tokens": [
"admin-token-for-ops-team"
]
}
}يتيح هذا إلغاء رموز فردية دون تعطيل خطوط أخرى.
استراتيجية النسخ الاحتياطي
ما يجب نسخه احتياطياً
| المكوّن | المسار | الحجم | التكرار |
|---|---|---|---|
| قاعدة بيانات SQLite | /data/fenfa.db | صغير (أقل من 100 ميغابايت عادةً) | يومي |
| الملفات المرفوعة | /app/uploads/ | قد يكون كبيراً | بعد كل رفع (أو استخدم S3) |
| ملف الإعداد | config.json | صغير جداً | عند التغيير |
نسخ SQLite احتياطياً
# نسخ ملف قاعدة البيانات (آمن أثناء تشغيل Fenfa -- SQLite يستخدم وضع WAL)
cp /data/fenfa.db /backups/fenfa-$(date +%Y%m%d).dbسكريبت نسخ احتياطي آلي
#!/bin/bash
BACKUP_DIR="/backups/fenfa"
DATE=$(date +%Y%m%d-%H%M)
mkdir -p "$BACKUP_DIR"
# Database
cp /path/to/data/fenfa.db "$BACKUP_DIR/fenfa-$DATE.db"
# Uploads (if using local storage)
tar czf "$BACKUP_DIR/uploads-$DATE.tar.gz" /path/to/uploads/
# Cleanup old backups (keep 30 days)
find "$BACKUP_DIR" -name "*.db" -mtime +30 -delete
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -deleteتخزين S3
إذا كنت تستخدم تخزيناً متوافقاً مع S3 (R2 أو AWS S3 أو MinIO)، فالملفات المرفوعة موجودة بالفعل على وحدة تخزين خلفية متكررة. تحتاج فقط إلى نسخ قاعدة بيانات SQLite احتياطياً.
المراقبة
فحص الصحة
راقب نقطة نهاية /healthz:
curl -sf http://localhost:8000/healthz || echo "Fenfa is down"مع مراقبة وقت التشغيل
وجّه خدمة مراقبة وقت التشغيل (UptimeRobot وHetrix إلخ.) إلى:
https://dist.example.com/healthzالاستجابة المتوقعة: {"ok": true} مع HTTP 200.
مراقبة السجلات
يُسجّل Fenfa على stdout. استخدم برنامج تشغيل السجل لوقت تشغيل حاويتك لإعادة توجيه السجلات إلى نظام التجميع:
services:
fenfa:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"Docker Compose الإنتاجي الكامل
version: "3.8"
services:
fenfa:
image: fenfa/fenfa:latest
container_name: fenfa
restart: unless-stopped
ports:
- "127.0.0.1:8000:8000"
environment:
FENFA_ADMIN_TOKEN: ${FENFA_ADMIN_TOKEN}
FENFA_UPLOAD_TOKEN: ${FENFA_UPLOAD_TOKEN}
FENFA_PRIMARY_DOMAIN: https://dist.example.com
volumes:
- fenfa-data:/data
- fenfa-uploads:/app/uploads
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8000/healthz"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
memory: 512M
volumes:
fenfa-data:
fenfa-uploads:الخطوات التالية
- نشر Docker -- أساسيات Docker والإعداد
- مرجع الإعداد -- جميع الإعدادات
- استكشاف الأخطاء -- مشكلات الإنتاج الشائعة