قواعد Rediacc
يعمل كل مستودع Rediacc داخل بيئة معزولة تحتوي على Docker daemon خاص به، ووحدة تخزين LUKS مشفرة، ونطاق IP مخصص. تضمن هذه القواعد أن تطبيقك يعمل بشكل صحيح ضمن هذه البنية.
Rediaccfile
- كل مستودع يحتاج إلى Rediaccfile — سكريبت bash يحتوي على دوال دورة الحياة.
- دوال دورة الحياة:
up()،down(). اختياري:info(). up()يبدأ خدماتك.down()يوقفها.info()يوفر معلومات الحالة (حالة الحاويات، السجلات الأخيرة، الصحة).- يتم تحميل Rediaccfile بواسطة renet — لديه وصول إلى متغيرات الشل، وليس فقط متغيرات البيئة.
متغيرات البيئة المتاحة في Rediaccfile
| المتغير | مثال | الوصف |
|---|---|---|
REDIACC_WORKING_DIR | /mnt/rediacc/mounts/abc123/ | المسار الجذري للمستودع المُركّب |
REDIACC_NETWORK_ID | 6336 | معرّف عزل الشبكة |
REDIACC_REPOSITORY | abc123-... | GUID المستودع |
{SVCNAME}_IP | HEARTBEAT_IP=127.0.24.195 | عنوان IP loopback لكل خدمة (اسم الخدمة بأحرف كبيرة) |
Rediaccfile الأدنى
#!/bin/bash
_compose() {
renet compose -- "$@"
}
up() {
_compose up -d
}
down() {
_compose down
}
Compose
- استخدم
renet compose، ولا تستخدمdocker composeأبداً — يقوم renet بحقن عزل الشبكة، وشبكة المضيف، وعناوين IP loopback، وتسميات الخدمة. - لا تقم بتعيين
network_modeفي ملف compose — يفرض renetnetwork_mode: hostعلى جميع الخدمات. أي قيمة تعيّنها سيتم الكتابة فوقها. - لا تقم بتعيين تسميات
rediacc.*— يقوم renet بالحقن التلقائي لـrediacc.network_idوrediacc.service_ipوrediacc.service_name. - يتم تجاهل تعيينات
ports:في وضع شبكة المضيف. استخدم تسميةrediacc.service_portلتوجيه الوكيل إلى المنافذ غير 80. - سياسات إعادة التشغيل (
restart: always،on-failure، إلخ) آمنة للاستخدام — يقوم renet بإزالتها تلقائياً لتوافق CRIU. يقوم watchdog الموجّه باستعادة الحاويات الموقوفة تلقائياً بناءً على السياسة الأصلية المحفوظة في.rediacc.json. - الإعدادات الخطرة محظورة بشكل افتراضي — يتم رفض
privileged: trueوpid: hostوipc: hostوالـ bind mounts إلى مسارات النظام. استخدمrenet compose --unsafeللتجاوز على مسؤوليتك الخاصة.
متغيرات البيئة داخل الحاويات
يقوم Renet بحقن هذه تلقائياً في كل حاوية:
| المتغير | الوصف |
|---|---|
SERVICE_IP | عنوان IP loopback المخصص لهذه الحاوية |
REDIACC_NETWORK_ID | معرّف عزل الشبكة |
تسمية الخدمات والتوجيه
- The compose service name becomes the auto-route URL prefix.
- Grand repos:
https://{service}.{repo}.{machine}.{baseDomain}(مثال:https://myapp.marketing.server-1.example.com). - Fork repos:
https://{service}-{tag}.{machine}.{baseDomain}— uses the machine wildcard cert to avoid Let’s Encrypt rate limits. - للنطاقات المخصصة، استخدم تسميات Traefik (ملاحظة: النطاقات المخصصة ليست متوافقة مع fork — النطاق ينتمي إلى grand repo).
الشبكات
- كل مستودع يحصل على Docker daemon خاص به في
/var/run/rediacc/docker-<networkId>.sock. - كل خدمة تحصل على عنوان IP loopback فريد ضمن شبكة فرعية /26 (مثال:
127.0.24.192/26). - اربط بـ
SERVICE_IP— تحصل كل خدمة على عنوان IP loopback فريد. - يجب أن تستخدم فحوصات الصحة
${SERVICE_IP}، وليسlocalhost. مثال:healthcheck: test: ["CMD", "curl", "-f", "http://${SERVICE_IP}:8080/health"] - الاتصال بين الخدمات: استخدم عناوين IP loopback أو متغير البيئة
SERVICE_IP. أسماء DNS الخاصة بـ Docker لا تعمل في وضع المضيف. - تعارض المنافذ مستحيل بين المستودعات — كل منها لديه Docker daemon ونطاق IP خاص به.
- إعادة توجيه منافذ TCP/UDP: أضف تسميات لكشف المنافذ غير HTTP:
labels: - "rediacc.tcp_ports=5432,3306" - "rediacc.udp_ports=53"
التخزين
- يتم تخزين جميع بيانات Docker داخل المستودع المشفر — يقع
data-rootالخاص بـ Docker في{mount}/.rediacc/docker/dataداخل وحدة تخزين LUKS. وحدات التخزين المسماة والصور وطبقات الحاويات جميعها مشفرة ومنسوخة احتياطياً ومُفرّعة تلقائياً. - يُوصى بالـ bind mounts إلى
${REDIACC_WORKING_DIR}/...للوضوح، لكن وحدات التخزين المسماة تعمل أيضاً بأمان.volumes: - ${REDIACC_WORKING_DIR}/data:/data # bind mount (موصى به) - pgdata:/var/lib/postgresql/data # named volume (آمن أيضاً) - يتم تركيب وحدة تخزين LUKS في
/mnt/rediacc/mounts/<guid>/. - تلتقط لقطات BTRFS ملف دعم LUKS بالكامل، بما في ذلك جميع البيانات المُركّبة بـ bind.
- مخزن البيانات هو ملف مجموعة BTRFS ذو حجم ثابت على قرص النظام. استخدم
rdc machine query <name> --systemلرؤية المساحة الحرة الفعلية. قم بالتوسعة معrdc datastore resize.
CRIU (الترحيل الحي)
- الاشتراك عبر التسمية: أضف
rediacc.checkpoint=trueللحاويات التي تريد إنشاء نقاط تحقق لها. الحاويات بدون هذه التسمية (قواعد البيانات، الذاكرة المؤقتة) تبدأ من جديد وتتعافى عبر آلياتها الخاصة (WAL، LDF، AOF). backup push --checkpointيلتقط حالة ذاكرة العمليات الجارية + حالة القرص للحاويات المُعلَّمة.repo fork --checkpointيلتقط حالة العمليات قبل التفريع — يستعيد fork تلقائياً عندrepo up.repo down --checkpointيحفظ حالة العمليات قبل التوقف — يستعيد تلقائياً عندrepo upالتالي.repo upيكتشف بيانات checkpoint تلقائياً ويستعيدها إن وُجدت. استخدم--skip-checkpointللبدء من جديد.- استعادة مدركة للتبعيات: يستخدم
depends_onفي compose لبدء قواعد البيانات أولاً (انتظار healthy)، ثم استعادة CRIU لحاويات التطبيق. - تصبح اتصالات TCP قديمة بعد الاستعادة — يجب على التطبيقات التعامل مع
ECONNRESETوإعادة الاتصال. - وضع Docker التجريبي يتم تفعيله تلقائياً على أدوات daemon لكل مستودع.
- يتم تثبيت CRIU أثناء
rdc config machine setup. /etc/criu/runc.confيتم تكوينه معtcp-establishedللحفاظ على اتصالات TCP.- يتم حقن إعدادات أمان الحاويات تلقائياً للحاويات المُعلَّمة — يضيف
renet composeما يلي للحاويات التي تحملrediacc.checkpoint=true:cap_add:CHECKPOINT_RESTORE،SYS_PTRACE،NET_ADMIN(الحد الأدنى لـ CRIU على النواة 5.9+)security_opt:apparmor=unconfined(دعم AppArmor في CRIU ليس مستقراً بعد في المنبع)userns_mode: host(يتطلب CRIU الوصول إلى مساحة اسم init لـ/proc/pid/map_files)
- الحاويات بدون التسمية تعمل بوضع أمان أنظف (بدون capabilities إضافية).
- يتم الحفاظ على ملف تعريف seccomp الافتراضي لـ Docker — يستخدم CRIU
PTRACE_O_SUSPEND_SECCOMP(النواة 4.3+) لتعليق المرشحات مؤقتاً أثناء checkpoint/restore. - لا تقم بتعيين capabilities CRIU يدوياً في ملف compose — يتولى renet ذلك بناءً على التسمية.
- راجع قالب heartbeat للحصول على تطبيق مرجعي متوافق مع CRIU.
أنماط التطبيقات المتوافقة مع CRIU
- تعامل مع
ECONNRESETعلى جميع الاتصالات المستمرة (مجمّعات قواعد البيانات، websockets، طوابير الرسائل). - استخدم مكتبات مجمّعات الاتصال التي تدعم إعادة الاتصال التلقائي.
- أضف
process.on("uncaughtException")كشبكة أمان لأخطاء المقابس القديمة من كائنات المكتبات الداخلية. - يتم إدارة سياسات إعادة التشغيل تلقائياً بواسطة renet (تُزال لـ CRIU، watchdog يتولى الاستعادة).
- تجنب الاعتماد على DNS الخاص بـ Docker — استخدم عناوين IP loopback للاتصال بين الخدمات.
الأمان
- تشفير LUKS إلزامي للمستودعات القياسية. كل مستودع لديه مفتاح تشفير خاص به.
- يتم تخزين بيانات الاعتماد في تكوين CLI (
~/.config/rediacc/rediacc.json). فقدان التكوين يعني فقدان الوصول إلى وحدات التخزين المشفرة. - لا تقم أبداً بإرسال بيانات الاعتماد إلى نظام التحكم بالإصدارات. استخدم
env_fileوقم بتوليد الأسرار فيup(). - عزل المستودع: Docker daemon والشبكة والتخزين لكل مستودع معزولة تماماً عن المستودعات الأخرى على نفس الجهاز.
- عزل الوكلاء: تعمل وكلاء الذكاء الاصطناعي في وضع fork-only بشكل افتراضي. كل مستودع لديه مفتاح SSH خاص به مع تطبيق sandbox من جانب الخادم (ForceCommand
sandbox-gateway). جميع الاتصالات محاطة بـ sandbox مع Landlock LSM، وOverlayFS home overlay، وTMPDIR لكل مستودع. يتم حظر الوصول إلى نظام الملفات بين المستودعات من قبل النواة.
النشر
rdc repo upينفذup()في جميع ملفات Rediaccfile.rdc repo up --mountيفتح وحدة تخزين LUKS أولاً، ثم ينفذ دورة الحياة. مطلوب بعدbackup pushإلى جهاز جديد.rdc repo downينفذdown()ويوقف Docker daemon.rdc repo down --unmountيغلق أيضاً وحدة تخزين LUKS (يقفل التخزين المشفر).- الفروع (
rdc repo fork) تنشئ نسخة CoW (copy-on-write) بـ GUID و networkId جديدين. يشارك الفرع مفتاح تشفير الأصل. - التسلّم (
rdc repo takeover <fork> -m <machine>) يستبدل بيانات المستودع grand ببيانات فرع. يحتفظ grand بهويته (GUID، networkId، النطاقات، الإقلاع التلقائي، سلسلة النسخ الاحتياطية). يتم حفظ بيانات الإنتاج القديمة كفرع احتياطي. الاستخدام: اختبار الترقية على فرع، التحقق، ثم تسلّم الإنتاج. الرجوع بـrdc repo takeover <backup-fork> -m <machine>. - مسارات الوكيل تستغرق حوالي 3 ثوانٍ لتصبح نشطة بعد النشر. تحذير “Proxy is not running” أثناء
repo upهو إعلامي في بيئات ops/dev.
الأخطاء الشائعة
- استخدام
docker composeبدلاً منrenet compose— لن تحصل الحاويات على عزل الشبكة. - سياسات إعادة التشغيل آمنة — يقوم renet بإزالتها تلقائياً ويتولى watchdog الاستعادة.
- استخدام
privileged: true— غير ضروري، إذ يقوم renet بحقن صلاحيات CRIU المحددة عوضاً عن ذلك. - عدم الربط بـ
SERVICE_IP— يسبب تعارض المنافذ بين المستودعات. - ترميز عناوين IP بشكل ثابت — استخدم متغير البيئة
SERVICE_IP؛ يتم تخصيص عناوين IP ديناميكياً لكل networkId. - نسيان
--mountفي أول نشر بعدbackup push— تحتاج وحدة تخزين LUKS إلى فتح صريح. - استخدام
rdc term -cكحل بديل للأوامر الفاشلة — أبلغ عن الأخطاء بدلاً من ذلك. repo deleteينفذ تنظيفاً كاملاً يشمل عناوين IP loopback ووحدات systemd. شغّلrdc machine prune <name>لتنظيف بقايا عمليات الحذف القديمة.