لماذا تستضيف Cal.com ذاتيًا على خادم VPS
Cal.com تطبيق Next.js يعتمد على PostgreSQL يتولّى جدولة المواعيد وأنواع الأحداث وأوقات التوفّر والمزامنة مع التقاويم (Google وCalDAV وOffice 365). تلبّي الاستضافة الذاتية حاجة محدّدة: التحكم في بيانات توفّر عملائك وحجز مواعيدهم، التي تمرّ عادةً عبر خدمة أمريكية طرف ثالث. على خادم VPS، تلغي قيود الخطة المجانية (نوع حدث واحد، علامة تجارية مفروضة)، وتربط مفاتيح API الخاصة بك لـGoogle/الاجتماعات المرئية، وتضمّن أداة الحجز مباشرةً في موقعك تحت نطاقك. وبما أن Cal.com تطبيق Node دائم مع قاعدة بيانات وبناء إنتاجي، فإنه يتطلّب خادم VPS — إذ لا تستطيع الاستضافة المشتركة تشغيل العملية ولا استضافة PostgreSQL.
فوائد ملموسة لـCal.com المُستضاف ذاتيًا
- أنواع أحداث غير محدودة: مقابلات 15 دقيقة، وعروض توضيحية 30 دقيقة، وورش جماعية، دون حاجز مدفوع (paywall).
- بيانات الحجز لديك: دون أي تسريب لبيانات اتصال العملاء ومواعيدهم إلى خدمة SaaS طرف ثالث.
- علامة بيضاء (white-label) كاملة: يحمل رابط الحجز نطاقك، لا نطاق مطوّر.
- Webhooks وAPI: شغّل الأتمتة (CRM، الفوترة) عند كل موعد يُحجَز.
- تكاملات Google Agenda وCalDAV والاجتماعات المرئية (Jitsi وGoogle Meet) مضبوطة بمفاتيحك الخاصة.
- حجوزات الفريق والتوزيع الدوري (round-robin) لتوزيع المواعيد بين عدة متعاونين.
المتطلبات التقنية
Cal.com أكثر تطلّبًا من متوسط الاستضافة الذاتية بسبب أساسه Next.js وخطوة البناء. خصّص 2 vCPU و4 غيغابايت من RAM و20 غيغابايت من القرص لنسخة فريق مريحة؛ وقد يكفي 2 غيغابايت من RAM للاستخدام الفردي لكن البناء الأولي يكون أضيق. تحتاج إلى Docker وDocker Compose، وقاعدة بيانات PostgreSQL (مشمولة في ملف compose الرسمي)، ونطاق rdv.yourdomain.com موجَّه إلى الخادم VPS، وعدة متغيرات بيئة إلزامية: NEXTAUTH_SECRET وCALENDSO_ENCRYPTION_KEY (مفاتيح مولَّدة عشوائيًا) وNEXT_PUBLIC_WEBAPP_URL مضبوطًا على عنوان HTTPS النهائي. وللمزامنة مع التقويم والاجتماعات المرئية، جهّز معرّفات OAuth الخاصة بـGoogle.
نشر Cal.com خطوة بخطوة
استنساخ مستودع نشر Docker
على الخادم VPS: git clone https://github.com/calcom/docker.git cal-docker && cd cal-docker. يوفّر هذا المستودع ملف docker-compose.yml وملف .env.example لتكييفه.
توليد الأسرار وإعداد البيئة
انسخ .env.example إلى .env، ثم ولّد المفاتيح: openssl rand -base64 32 لـNEXTAUTH_SECRET ولـCALENDSO_ENCRYPTION_KEY. عيّن NEXT_PUBLIC_WEBAPP_URL=https://rdv.yourdomain.com ومعرّفات PostgreSQL. احفظ هذه القيم الثلاث فورًا في مدير الأسرار — لن تتمكن من تغييرها بعد أول تشغيل دون فقدان جميع تكاملاتك.
إضافة NEXTAUTH_URL_INTERNAL لمنع CLIENT_FETCH_ERROR
أضِف NEXTAUTH_URL_INTERNAL=http://calcom:3000 إلى ملف .env. بدون هذا المتغير، يحاول حاوية Next.js حلّ نطاقها العام (rdv.yourdomain.com) من داخل شبكة Docker، حيث لا يستجيب DNS الخارجي — فيفشل كل طلب مصادقة من جهة الخادم بخطأ CLIENT_FETCH_ERROR. يتجاوز NEXTAUTH_URL_INTERNAL هذا الحل بالإشارة مباشرةً إلى اسم خدمة Docker (calcom هو اسم الخدمة في docker-compose.yml). هذا المتغير مستقل عن NEXTAUTH_URL: يجب أن يكون الاثنان موجودَين.
بناء المكدّس وتشغيله
ابدأ بـdocker compose up -d. يبني التشغيل الأول صورة Next.js ويطبّق عمليات ترحيل Prisma على PostgreSQL — وهي الخطوة الأطول، تابِعها بـdocker compose logs -f.
أول تسجيل دخول
افتح الرابط: يوجّهك Cal.com إلى معالج الإعداد الأول (/auth/setup) حيث تنشئ حساب المسؤول الخاص بك. قم بذلك فور انتهاء التثبيت: فهذا المعالج غير محمي بأي شيء ما دام الحساب الأول غير موجود.
إنشاء الحساب وإعداد أوقات التوفّر
حدّد فتراتك الزمنية ونوع حدث أول. اختبر حجزًا من البداية إلى النهاية للتحقق من السلسلة الكاملة قبل توصيل التكاملات.
توصيل التقويم والاجتماعات المرئية
في التكاملات، أضف معرّفات OAuth الخاصة بـGoogle للمزامنة ثنائية الاتجاه للتقويم، وفعّل Jitsi أو Google Meet لتوليد رابط اجتماع مرئي تلقائيًا عند كل حجز.
الوكيل العكسي: nginx وCaddy
يستمع Cal.com على المنفذ 3000 داخل الحاوية. وكيل عكسي بـHTTPS مطلوب لسببين: كشف المنفذ 443 وإعادة توجيه رأس Host الصحيح — وإلا فإن NEXT_PUBLIC_WEBAPP_URL لن يطابق الأصل الفعلي وستنهار عمليات إعادة توجيه المصادقة.
باستخدام Caddy (موصى به، شهادة تلقائية):
rdv.yourdomain.com {
reverse_proxy calcom:3000
}يحصل Caddy على شهادة Let's Encrypt ويجدّدها دون إعداد إضافي.
باستخدام nginx، أضِف هذه الكتلة إلى إعداداتك:
server {
listen 443 ssl;
server_name rdv.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/rdv.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/rdv.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}في كلتا الحالتين، يجب أن يطابق الرابط NEXT_PUBLIC_WEBAPP_URL تمامًا: بدون شرطة مائلة في النهاية، بـHTTPS، مع النطاق الفرعي الصحيح. أي فارق في حرف واحد ينتج حلقات إعادة توجيه لا تنتهي أو شاشة بيضاء.
ثوابت التشغيل الأول الحرجة
ثلاثة متغيرات بيئة مُقيَّدة نهائيًا عند أول تشغيل لـCal.com. تغييرها لاحقًا يُفسد صامتًا جميع التكاملات المخزّنة: يُعيد التطبيق تشغيله بصورة طبيعية ولا يُظهر أي خطأ، لكن Google Calendar وZoom وجميع اتصالات OAuth تتوقف عن العمل — إذ خُزِّنت رموزها المشفَّرة بالمفتاح الأصلي غير المتوافق الآن. هذا السلوك موثَّق في calcom/docker issue #333 وcalcom/cal.diy issue #13290: فقد مستخدمون جميع تكاملاتهم إثر تحديث أعاد إنشاء ملف .env.
CALENDSO_ENCRYPTION_KEY — يشفّر رموز OAuth المخزّنة في قاعدة البيانات. أي تعديل يُلغي صامتًا جميع التكاملات القائمة.
NEXTAUTH_URL — يثبّت ملفات تعريف الارتباط للجلسة. أي تغيير يُعطل المصادقة لجميع المستخدمين النشطين.
NEXT_PUBLIC_WEBAPP_URL — مضمَّن في بناء Next.js وقت الترجمة. تغيير هذه القيمة يستلزم إعادة بناء كاملة وإعادة توصيل جميع التكاملات.
أفضل الممارسات: انسخ هذه القيم الثلاث فورًا إلى مدير الأسرار (Bitwarden، HashiCorp Vault، Ansible Vault). وإن كنت تدير خادمك بنهج البنية التحتية كرمز (infrastructure-as-code)، خزّنها في قبو مشفَّر — لا تجعل ملف .env موضعها الوحيد.
تحديث Cal.com بأمان
نسخ قاعدة بيانات PostgreSQL احتياطيًا
قبل أي تحديث: docker exec cal-docker-db-1 pg_dump -U calcom calcom | gzip > /opt/backup/calcom-$(date +%Y%m%d).sql.gz. عمليات ترحيل Prisma غير قابلة للتراجع — هذه النسخة الاحتياطية هي شبكة الأمان الوحيدة لديك.
التحقق من أن CALENDSO_ENCRYPTION_KEY لم تتغيّر
قارن القيمة الموجودة في ملف .env بتلك المحفوظة في مدير الأسرار. إن اختلفتا، توقّف هنا: استعِد القيمة الأصلية قبل المتابعة. مفتاح مختلف سيُدمّر صامتًا جميع تكاملات OAuth عند إعادة التشغيل.
تنزيل الصورة الجديدة وإعادة التشغيل
حدِّث بـdocker compose pull && docker compose up -d. تابِع بدء التشغيل بـdocker compose logs -f calcom — انتظر رسالة تأكيد جاهزية الخادم قبل الاختبار.
التحقق من التكاملات بعد التحديث
افتح الإعدادات → التكاملات وتأكد من أن كل اتصال قائم (Google Calendar، Zoom، إلخ) لا يزال نشطًا. حالة «غير متصل» تعني تغيُّر المفتاح بين تشغيلَين — استعِد النسخة الاحتياطية وملف .env الأصلي.
تشخيص الأخطاء: CLIENT_FETCH_ERROR وأخطاء Docker الشائعة
CLIENT_FETCH_ERROR عند تحميل الصفحة — منذ مطلع 2026، تواجه جميع تثبيتات Docker الجديدة هذا الخطأ عند أول تحميل. السبب: تحاول حاوية Next.js حلّ NEXTAUTH_URL (نطاقك العام) من داخل شبكة Docker، حيث لا يمكن الوصول إلى DNS الخارجي. الحل: أضِف NEXTAUTH_URL_INTERNAL=http://calcom:3000 إلى ملف .env وأعِد التشغيل بـdocker compose up -d. هذا المتغير يُجبر NextAuth على استدعاء واجهته الخاصة داخليًا دون المرور بالنطاق العام. موثَّق في calcom/cal.diy issue #27668 (فبراير 2026، 8 تعليقات تؤكد الخطأ في جميع توزيعات Docker الحديثة).
ضياع التكاملات بعد تحديث — السبب في الغالب CALENDSO_ENCRYPTION_KEY مختلفة بين تشغيلَين. تحقق من أن ملف .env لم يُستبدَل بـ.env.example أثناء التنزيل. قارن القيمة الحالية بتلك المحفوظة في مدير الأسرار. إن اختلفتا: استعِد قاعدة بيانات PostgreSQL، أعِد المفتاح الأصلي إلى .env، وأعِد التشغيل بـdocker compose up -d.
خطأ «JavaScript heap out of memory» أثناء البناء — المُجمِّع Next.js يعاني من نقص RAM. الحل: fallocate -l 2G /swapfile && mkswap /swapfile && swapon /swapfile، ثم أعِد تشغيل docker compose build. على خادم VPS بسعة 2 غيغابايت، الـswap ضروري غالبًا للبناء الأول والتحديثات الكبرى. أزِل ملف الـswap بعد اكتمال البناء.
حلقة إعادة توجيه أو خطأ «Unable to find valid origin» — NEXT_PUBLIC_WEBAPP_URL لا يطابق الرابط الفعلي. تحقق من أن هذا المتغير يساوي بالضبط https://rdv.yourdomain.com (بدون شرطة مائلة في النهاية، بالنطاق الصحيح وبروتوكول HTTPS)، وأن الوكيل العكسي يُعيد توجيه رأس Host بصورة صحيحة، ثم أعِد التشغيل بـdocker compose up -d --build لإجبار إعادة البناء بالرابط الصحيح.
عمليات ترحيل Prisma متعلّقة عند بدء التشغيل — إن أعادت الحاوية تشغيلها باستمرار مع أخطاء ترحيل، قد لا تكون قاعدة البيانات جاهزة بعد. انتظر بضع ثوانٍ وشغّل docker compose restart calcom. وإن استمرت المشكلة، تحقق من سجلات PostgreSQL بـdocker compose logs db.
أتمِت نسخ قاعدة بيانات PostgreSQL احتياطيًا بمهمة cron يومية. مثال على الأمر المجدوَل: docker exec cal-docker-db-1 pg_dump -U calcom calcom | gzip > /opt/backup/calcom-$(date +%Y%m%d-%H%M).sql.gz. احتفظ بسبعة أيام على الأقل من النسخ الاحتياطية الدورية وأرسِلها إلى تخزين كائنات خارجي (S3-متوافق، Backblaze B2): في حال فقدان الخادم VPS، قاعدة بيانات PostgreSQL هي الجزء الوحيد غير القابل للاستعادة تلقائيًا في نسختك من Cal.com.
للمزيد
بمجرد تشغيل Cal.com، ثمة خطوات لتعزيز التثبيت: تفعيل تنبيهات شهادات SSL لتوقّع انتهاء صلاحيتها، وإعداد مراقبة HTTP (Uptime Kuma، Better Uptime) على https://rdv.yourdomain.com/api/health، وتقييد منفذ الحاوية 3000 على 127.0.0.1 لمنع الوصول المباشر إليه. وللتثبيتات الجماعية، يمكن للوكيل العكسي خدمة عدة نسخ من Cal.com خلف نطاقات فرعية متمايزة من خادم VPS واحد — راجع النشر باستخدام Coolify لإدارة متعددة الخدمات مبسَّطة. تغطّي وثائق Cal.com الرسمية أيضًا إعداد SMTP لرسائل التأكيد وتكامل Stripe للحجوزات المدفوعة.