لماذا تختار Kamal بدلاً من Kubernetes لنشر تطبيقاتك على VPS؟
Kubernetes مصمم لحل مشكلات التنسيق على نطاق واسع — اكتشاف الخدمات، التوسع الأفقي التلقائي، مساحات الأسماء لفرق متعددة — وهي مشكلات لا وجود لها على خادم VPS واحد أو مجموعة صغيرة. ولتثبيته فقط عبر kubeadm تطلب الوثائق الرسمية 2 غيغابايت من الذاكرة العشوائية لكل جهاز و2 CPU لبنية التحكم، قبل تشغيل أي تطبيق. Kamal يستهدف نطاقاً مختلفاً: يأخذ ملف Dockerfile الخاص بك، يبني الصورة، يرفعها إلى السجل، يشغّلها على خوادمك عبر SSH، ويحوّل حركة المرور بلا انقطاع بفضل kamal-proxy. كل الإعداد يتضمن ملف config/deploy.yml واحداً يُحفظ مع الكود. لا بنية تحكم لصيانتها، لا شهادات API للتجديد، لا YAML موزعة على عشرة موارد. تحتفظ ببساطة تشغيل VPS — وصول SSH مباشر، docker ps مقروء، سجلات في ملف — مع الحصول على سير عمل نشر احترافي مع تراجع فوري وفحوصات صحة وHTTPS تلقائي.
ما يقدمه لك Kamal v2
- نشر بدون توقف — ينتظر kamal-proxy نجاح فحوصات الصحة على الحاوية الجديدة قبل تحويل حركة المرور، مع إتمام الطلبات الجارية على الحاوية القديمة
- أمر واحد — ينفذ
kamal deploy البناء والرفع إلى السجل والنشر عبر SSH والتحقق دون تدخل يدوي - HTTPS تلقائي من Let's Encrypt — يتولى kamal-proxy تجديد شهادات TLS؛ لا حاجة لإعداد Certbot منفصل
- تراجع فوري — يُعيد
kamal rollback [VERSION] توجيه الوكيل إلى صورة موجودة مسبقاً على الخادم في ثوانٍ - إدارة أسرار منظمة — يدعم
.kamal/secrets القراءة من 1Password وBitwarden أو متغيرات البيئة دون تخزين قيم نصية في المستودع - دعم متعدد الخوادم والأدوار — خوادم الويب وعمال Sidekiq وملحقات Postgres وRedis في ملف واحد، تُنشر بالتوازي
- تطبيقات متعددة على VPS واحد — منذ Kamal 2، تتشارك عدة تطبيقات في kamal-proxy واحد دون تعارض
- متوافق مع أي تقنية — Rails وDjango وNode.js وGo وPHP: يتطلب Kamal فقط ملف Dockerfile وسجل حاويات
المتطلبات المسبقة قبل النشر باستخدام Kamal
على جانب VPS، يحتاج Kamal إلى خادم Linux يمكن الوصول إليه عبر SSH بمفتاح (لا كلمة مرور)؛ لا تفرض وثائقه توزيعة ولا حجمًا معينًا، لكن خصّص 2 vCPU و2 غيغابايت من ذاكرة الوصول العشوائي على الأقل لتطبيق ويب قياسي مع قاعدة بياناته. يمكن لـ Kamal تثبيت Docker بنفسه خلال أول kamal setup (سكربت get.docker.com)، لكن ذلك يتطلب وصولًا بصلاحيات root عبر SSH — إذ يتصل Kamal بحساب root افتراضيًا. يلزم فتح المنفذَين 80 و443 ووجود سجل DNS من النوع A يشير إلى IP الخادم قبل تفعيل SSL. على جهازك المحلي، ثمة خياران: تثبيت الحزمة gem install kamal (يتطلب بيئة Ruby) أو استخدام صورة Docker الرسمية. الإصدار الحالي هو 2.12.0 (يونيو 2026). احضر أيضاً سجل حاويات — Docker Hub أو GitHub Container Registry أو سجلاً خاصاً — مع بيانات اعتماده.
Kamal v1 مقابل Kamal v2: ما الذي تغيّر
صدر Kamal 2 في سبتمبر 2024 (مُدرَج افتراضياً في Rails 8 الصادر في نوفمبر 2024)، ليستبدل Traefik بـ kamal-proxy، وكيل عكسي داخلي طوّرته 37signals. التغيير جوهري: Traefik تصريحي (ترسل إليه إعداداً وينسجم معه)، بينما Kamal أمري. كانت النسخة 1 تستطلع واجهة Traefik API باستمرار لمعرفة ما إذا اكتمل النشر — وهو مصدر لسباقات الظروف. مع kamal-proxy، الأوامر مباشرة ومتزامنة. على صعيد الإعداد، يختفي قسم traefik: من deploy.yml ليحلّ محله قسم proxy: بمفاتيح host وssl وapp_port. تنتقل الأسرار من .env إلى .kamal/secrets، وهو ملف shell يمكنه استدعاء أدوات خارجية. يُحوَّل الإعداد يدويًا، ثم يُرحّل kamal upgrade الخوادم: يزيل Traefik ويشغّل kamal-proxy ثم يعيد تشغيل التطبيق والملحقات على الشبكة الجديدة. ويضيف Kamal 2 تشغيل تطبيقات متعددة على وكيل واحد، ووضع الصيانة kamal app maintenance ثم kamal app live للعودة إلى الخدمة.
التثبيت والنشر الأول مع Kamal v2
تثبيت Kamal على جهازك المحلي
نفّذ
gem install kamal (يتطلب بيئة Ruby)، أو إذا كنت تفضل تجنب Ruby استخدم اختصار Docker: alias kamal='docker run -it --rm -v "${PWD}:/workdir" ...'. تحقق من التثبيت بـ kamal version — الإصدار الحالي هو 2.12.0.تهيئة الإعداد في مشروعك
في المجلد الجذر للمشروع نفّذ
kamal init. سيُنشئ Kamal ملفَّي config/deploy.yml و.kamal/secrets. أدخل في deploy.yml: اسم الخدمة وعنوان الصورة وقائمة الخوادم وإعدادات السجل.إعداد الأسرار ومتغيرات البيئة
أضف
.kamal/secrets إلى .gitignore. في هذا الملف أعلن الأسرار كمتغيرات shell: KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD أو بقراءتها من 1Password. في config/deploy.yml أشر إليها ضمن env.secret: للقيم الحساسة وenv.clear: للمتغيرات العادية.إعداد الوكيل وشهادة SSL
في
config/deploy.yml أضف قسم proxy: مع host: app.votre-domaine.com وssl: true وapp_port: 3000. سيحصل kamal-proxy تلقائياً على شهادة Let's Encrypt. تأكد من أن سجل DNS يشير إلى IP الخادم قبل هذه الخطوة.تجهيز الخادم (مرة واحدة فقط)
نفّذ
kamal setup. يتصل Kamal عبر SSH، يثبّت Docker إن لزم، يتحقق من السجل، يُشغّل kamal-proxy وينشر النسخة الأولى من التطبيق. هذا الأمر هو خطوة التهيئة الوحيدة.نشر التحديثات اللاحقة
عند كل تحديث نفّذ
kamal deploy. يبني Kamal الصورة ويرفعها ويشغّل حاوية جديدة بجانب القديمة، ينتظر نجاح فحص الصحة، يحوّل الوكيل إلى الحاوية الجديدة ويوقف القديمة. العملية مرئية في الوقت الفعلي.التحقق من الحالة وعرض السجلات
بعد النشر:
kamal app details يعرض الإصدار الجاري على كل خادم، kamal app logs -f يتابع السجلات، kamal app exec -i 'bin/rails console' يفتح وحدة تحكم داخل الحاوية في الإنتاج.إدارة الملحقات (قاعدة البيانات، الذاكرة التخزينية المؤقتة)
أعلن Postgres ضمن مفتاح
accessories: في deploy.yml، مع ربط المنفذ بالمضيف المحلي port: "127.0.0.1:5432:5432" وعدم نشره على كل الواجهات. kamal accessory boot db يشغّل الخدمة على الخادم الصحيح. لا تمر الملحقات عبر kamal-proxy بل تتصل بالتطبيق مباشرة عبر متغيرات البيئة.
الإعداد متعدد الخوادم والنشر المتوازي
يُوزّع Kamal النشر على جميع خوادم الدور بالتوازي بشكل افتراضي. لتنظيم نشر تدريجي أضف boot: limit: 2 wait: 10 — سيُنشر Kamal على خادمَين في كل مرة مع فاصل 10 ثوانٍ. تتيح الأدوار تمييز الخوادم: web: لخوادم HTTP وworkers: بأمر مختلف كـ bundle exec sidekiq. لكل دور خوادمه وأسراره ومتغيراته. يعمل kamal-proxy على كل خادم من الدور الرئيسي (web افتراضيًا)، ولا تشغّله الأدوار الأخرى مثل workers. مع عدة خوادم ويب ضع موزّع أحمال أمامها: فـ HTTPS التلقائي في kamal-proxy يفترض النشر على خادم واحد.
متغيرات البيئة والأسرار — أفضل الممارسات
الفصل بين المتغيرات الواضحة والأسرار صريح في Kamal 2. في deploy.yml، تذهب المتغيرات غير الحساسة ضمن env: clear:، والأسرار ضمن env: secret: — تُقرأ قيمها من .kamal/secrets وقت النشر وتُكتب في ملف بيئة على الخادم بدل تمريرها نصًا واضحًا في أمر docker run. لا يُحقن سر من .kamal/secrets إلا إذا أُدرج ضمن env: secret:، في الجذر لكل الأدوار أو في الدور أو الملحق الذي يستخدمه. يعرض kamal secrets print القيم المحلولة للتحقق من قراءة مدير كلمات المرور قبل النشر.
إذا أدخل نشر ما انحداراً، لا تنتظر دورة البناء التالية: نفّذ kamal rollback [VERSION] لإعادة توجيه kamal-proxy فوراً إلى صورة موجودة مسبقاً على الـ VPS. استعرض الإصدارات المتاحة بـ kamal app images. لا يعيد التراجع البناء — يُعيد توجيه الوكيل في ثوانٍ.
HTTPS التلقائي مع kamal-proxy وLet's Encrypt
يتولى kamal-proxy دورة حياة TLS الكاملة: يستمع على المنفذين 80 و443، يستجيب لتحديات ACME من Let's Encrypt، يحصل على الشهادة، يخزّنها على الخادم ويجدّدها تلقائياً قبل انتهاء صلاحيتها. الشرط الوحيد أن يحلّ اسم المضيف المُعلن في proxy: host: إلى IP الخادم وأن يكون المنفذان 80 و443 مفتوحين — تُطلب الشهادة عند أول اتصال HTTPS، ويفشل تحدي ACME ما لم ينتشر DNS بعد. على خادم يستضيف عدة تطبيقات، يوجّه الوكيل حسب اسم المضيف ويُدير شهادة منفصلة لكل نطاق. ويفترض هذا HTTPS التلقائي النشر على خادم واحد؛ وما زاد على ذلك فأنهِ TLS على موزّع أحمال.
استكشاف الأخطاء — مشاكل شائعة عند النشر باستخدام Kamal
انتهاء مهلة SSH: تحقق من إمكانية الوصول إلى IP الخادم وفتح المنفذ 22، وتشغيل وكيل SSH. فشل فحص الصحة: فحص الصحة الافتراضي يطرق GET /up — أعلن مساراً مختلفاً بـ proxy: healthcheck: path: /health إذا لم يستجب تطبيقك على هذا المسار. تحقق أيضاً من تطابق app_port: مع المنفذ الفعلي. خطأ في مصادقة السجل: نفّذ kamal registry login ثم أعد المحاولة. تعارض المنافذ: إذا شغل عملية خارجية المنفذَين 80 أو 443، لن يبدأ kamal-proxy؛ حدّدها بـ ss -tlnp | grep -E '80|443'. فشل kamal setup عند تثبيت Docker: يتطلب التثبيت التلقائي وصولًا بصلاحيات root عبر SSH، أو ثبّت Docker يدويًا مسبقًا.
دمج Kamal في خط أنابيب CI/CD مع GitHub Actions
يتضمن سير عمل GitHub Actions النموذجي لـ Kamal 2 مهمتَين: مهمة اختبار (تُشغَّل عند كل push) ومهمة نشر مشروطة (تُفعَّل عند الدفع إلى main أو نشر إصدار). في مهمة النشر: ثبّت Ruby وحزمة Kamal، ثم نفّذ kamal deploy مع حقن الأسرار من GitHub Secrets. العناصر الأساسية في .github/workflows/deploy.yml: مهمة النشر تعتمد على مهمة الاختبار (needs: test)، وتهيّئ متغير KAMAL_REGISTRY_PASSWORD: ${{ secrets.KAMAL_REGISTRY_PASSWORD }}، وتثبّت Kamal بإصدار محدد، ثم تنفّذ kamal deploy. يُعدّ وكيل SSH عبر webfactory/[email protected] مع مفتاح خاص محفوظ في GitHub Secrets.
Kamal v1 مقابل Kamal v2 — ملخص الفروق
مرّر الجدول أفقيًا
| Kamal v1 | Kamal v2 | |
|---|---|---|
| الوكيل العكسي | Traefik (تصريحي، يستطلع API) | kamal-proxy (أمري، أوامر مباشرة) |
| الأسرار | .env في جذر المشروع | .kamal/secrets (shell مُقيَّم، يدعم مديري كلمات المرور) |
| SSL | يُدار عبر Traefik وACME | يُدار عبر kamal-proxy (Let's Encrypt مدمج) |
| تطبيقات متعددة | غير مدعوم بشكل أصلي | أصلي: عدة تطبيقات بوكيل واحد |
| الترقية | — | kamal upgrade يُرحّل الخوادم (الإعداد يُحوَّل يدويًا) |
| إعداد الوكيل في deploy.yml | قسم traefik: | قسم proxy: مع host وssl وapp_port |
Kamal على VPS ServOrbit — من الأمر إلى النطاق المُشغَّل
يستوفي VPS Cloud من ServOrbit بنظام Ubuntu 24.04 جميع متطلبات Kamal منذ التسليم: وصول SSH بمفتاح، شبكة 1 Gbit/s وعنوان IP مخصص. مسار العمل النموذجي: أنشئ سجل DNS من النوع A يشير إلى app.votre-domaine.com ثم نفّذ kamal setup — يثبّت Kamal Docker ويُشغّل kamal-proxy ويحصل على شهادة Let's Encrypt وينشر تطبيقك في تمريرة واحدة. من تلك اللحظة، كل kamal deploy من طرفيتك أو خط أنابيب CI يُطبّق التحديث دون توقف. لاستضافة مشاريع متعددة على نفس الـ VPS بنطاقات وشهادات مستقلة، أضف تطبيقاً في ملف deploy.yml ثانٍ يشير إلى نفس الخادم — يوجّه kamal-proxy حسب اسم المضيف دون إعادة إعداد.