SSD Nodes Learn 🎉 VPS من $4.99/شهر
الأدلة Matt Connorبقلم Matt Connor

بدائل Calendly المستضافة ذاتياً: مقارنة Cal.com وRallly

قارن Cal.com وEasy!Appointments وRallly وDayOtter على VPS: مزامنة التقويم ثنائية الاتجاه والبريد الصادر، مع خطأ المنفذ 25 المحظور عادةً.

الإجابة المختصرة

يجب أن يفعل بديل Calendly المستضاف ذاتياً شيئاً لا تفعله الأدوات الداخلية على VPS لديك: أن يستجيب للعامة. صفحة الحجز هي المنتج نفسه. تحتاج إلى اسم نطاق حقيقي وTLS (أمان طبقة النقل) منذ اليوم الأول، ويجب أن توصل البريد إلى أشخاص لم يسمعوا من قبل بخادمك.

تغطي أربعة مشاريع الخيارات الواقعية. Cal.com هو الأقرب إلى Calendly، وهو الاختيار الافتراضي للاستشاري المستقل. Easy!Appointments هو الخيار الأخف، ويعتمد على PHP وMySQL، ويعمل جيداً على VPS بسعة 1 GB. Rallly أداة لاستطلاعات المجموعة، ولا يوفّر صفحة حجز إطلاقاً. DayOtter هو المشروع الأحدث، وهو منصة جدولة بترخيص AGPLv3، يسبقها مساعد يتطلب التأكيد أولاً.

يحدد سؤالان المشروع الذي يمكنك تشغيله فعلياً. هل يزامن في الاتجاهين مع التقويم الذي تستخدمه بالفعل؟ وهل يستطيع إرسال البريد؟ السؤال الثاني هو الموضع الذي تفشل فيه معظم إعدادات الحجز المستضافة ذاتياً بصمت، لذلك نبدأ به.

البريد الإلكتروني الصادر هو الجزء الذي يتعطل

تصل رسالة تأكيد الحجز إلى صندوق وارد لشخص غريب. هذا بريد معاملات يصل إلى Gmail أو Microsoft 365، ويقيّمك هؤلاء المستلمون بناءً على عنوان IP المرسل وسجلات DNS لديك.

يكاد الإرسال مباشرة من VPS لا يعمل أبداً. يحظر معظم المزوّدين منفذ TCP الصادر 25 على الحسابات الجديدة، لذلك يظل الاتصال معلّقاً ثم تنتهي مهلته. وحتى عندما يكون المنفذ 25 مفتوحاً، لا يملك عنوان VPS جديد أي سجل إرسال، ويعتبر المستلمون الكبار عناوين نطاقات الاستضافة غير المعروفة مشبوهة. يُكتب الحجز في قاعدة البيانات، وتعرض الصفحة أنه مؤكّد، ولا تصل أي رسالة بريد إلكتروني. لا يبدو أي شيء معطلاً من جهة الخادم، ولذلك لا يُكتشف هذا الخلل عادةً إلا بعد أسابيع، عندما يتبيّن أن عميلاً لم يحضر قط.

استخدم relay. يعمل أي مزوّد لبريد المعاملات، ولا يحتاج التطبيق إلا إلى hostname ومنفذ واسم مستخدم وكلمة مرور. تحقّق من إمكانية الوصول إلى المنفذ قبل تعديل إعدادات التطبيق:

nc -vz -w 5 "$SMTP_HOST" 587

يعني سطر succeeded أن المسار مفتوح. أما التعليق أو Connection refused فيعني أن المنفذ محظور على مستوى الشبكة، ولن يصلح ذلك أي قدر من تعديل .env. تستمع relays على المنفذين 587 أو 465 تحديداً لأن المنفذ 25 يكون محظوراً كثيراً.

يتعامل كل مشروع مع relay بطريقته الخاصة. يقرأ Cal.com القيم EMAIL_FROM وEMAIL_SERVER_HOST وEMAIL_SERVER_PORT وEMAIL_SERVER_USER وEMAIL_SERVER_PASSWORD، ويقبل أيضاً قيمة RESEND_API_KEY بدلاً منها. انتبه إلى هذه القيمة: يشير .env.example المضمّن مع التطبيق إلى EMAIL_SERVER_HOST على localhost عبر المنفذ 1025، وهو صندوق بريد محلي مخصّص للتطوير. إذا أبقيت القيمة الافتراضية، فسيرسل التطبيق الرسائل إلى لا شيء من دون إظهار خطأ. يستخدم Rallly القيم SMTP_HOST وSMTP_PORT وSMTP_USER وSMTP_PWD. يستخدم DayOtter إعدادات SMTP أو مفتاح Resend. أما Easy!Appointments فيرسل إشعاراته من التطبيق، لذلك وجّهه إلى relay نفسه من صفحة الإعدادات قبل قبول حجز حقيقي.

بعد ذلك، انشر سجلات DNS التي يزوّدك بها relay. يحدّد سجل SPF (إطار سياسة المرسل) الخوادم التي يُسمح لها بالإرسال نيابةً عن نطاقك، وتوقّع مفتاح DKIM (بريد النطاقات المعرّفة) كل رسالة حتى يتمكن المستلم من إثبات أنها لم تُعدّل. أضف سياسة DMARC (مصادقة الرسائل المعتمدة على النطاق والإبلاغ والمطابقة) بعد نجاح الاختبارين. أرسل حجزاً تجريبياً إلى عنوان حقيقي لدى مزوّد كبير، وافتح ترويسات الرسالة، وتأكد من أن أسطر المصادقة تعرض pass. صفحة الحجز التي لا تستطيع الإرسال أسوأ من عدم وجود صفحة حجز، لأنها تفشل بصمت.

ما هي خدمات التقويم التي تدعم المزامنة في الاتجاهين فعلاً

للمزامنة اتجاهان، وقد يفشل كل منهما بشكل مستقل. اتجاه القراءة هو التحقق من التوافر: يجب أن يرى التطبيق الفترات المشغولة الموجودة لديك، وإلا فقد يمنح موعداً أنت مشغول فيه مسبقاً. أما اتجاه الكتابة فهو إنشاء الحجز نفسه: يجب أن يظهر الحدث المؤكد في التقويم الذي تراجعه فعلياً، لا داخل أداة الحجز فقط.

يدعم Google Calendar وMicrosoft 365 كلا الاتجاهين، بشرط واحد في التثبيت الذاتي الاستضافة. يجب أن تنشئ عميل OAuth (التفويض المفتوح) بنفسك، لأن معرّف العميل الخاص بالمنتج المستضاف غير موجود في الشيفرة المصدرية. في Cal.com يوجد ذلك في GOOGLE_API_CREDENTIALS داخل .env، حيث تضع ملف JSON الذي تنزّله من وحدة تحكم Google Cloud. ويستخدم DayOtter بيانات اعتماد OAuth الخاصة بـGoogle وMicrosoft بالطريقة نفسها.

هناك مشكلتان تؤديان إلى تعطل ذلك، ومن المفيد معرفتهما قبل البدء. أولاً، يجب أن يطابق redirect URI الذي تسجله عنوان URL العام لديك تماماً، بما في ذلك المخطط وأي مسار لاحق، وإلا يوقف Google الاتصال عند شاشة الموافقة مع redirect_uri_mismatch. ثانياً، يصدر مشروع Google الذي تظل حالة نشره Testing رموز تحديث تنتهي بعد سبعة أيام. تعمل المزامنة طوال الأسبوع ثم تتوقف، وتعرض سجلات التطبيق invalid_grant عند محاولة التحديث التالية. انقل شاشة الموافقة إلى In production، أو اقبل إعادة الاتصال يدوياً كل يوم اثنين.

يُعد CalDAV (امتدادات التقويم لـWebDAV) الخيار المفتوح، لكن دعمه أضيق. يوفّر Cal.com تطبيق CalDAV مصنفاً حالياً كإصدار تجريبي، وقد تم التحقق منه مع خوادم تشمل Baikal وRadicale وNextcloud وKerio Connect. يعمل Apple iCloud عبر التطبيق نفسه، لكنه يحتاج إلى كلمة مرور خاصة بالتطبيق بدلاً من كلمة مرور Apple ID. يدرج DayOtter Apple عبر CalDAV إلى جانب Google وMicrosoft 365.

تغذية ICS ليست مزامنة. يكون عنوان URL المشترك .ics للقراءة فقط حسب التصميم، لذلك يمكنه حجب الوقت في صفحة الحجز لديك، لكنه لا يستطيع استقبال الحجز مطلقاً. إذا كانت الأداة توفّر ICS فقط لتقويمك، فلديك نصف البنية المطلوبة فقط، وستظل تنسخ الأحداث يدوياً.

يدعم Easy!Appointments مزامنة Google Calendar ولا يدعم غيره. أما Rallly فلا يقرأ التوافر أصلاً، بل يجمع الأصوات على مجموعة من التواريخ المقترحة. إنه الأداة المناسبة لسؤال «متى يمكننا نحن الستة أن نلتقي؟»، وليس لسؤال «احجز معي 30 دقيقة».

صفحة الحجز عامة، لذلك يأتي TLS أولاً

معظم ما يستضيفه الناس ذاتياً يكون خاصاً. يمكن أن تعمل الويكي ولوحة العمل ولوحة المعلومات خلف VPN أو تسجيل دخول SSO، وألا تصل إلى الإنترنت المفتوح مطلقاً. أما رابط الحجز فلا يمكنه ذلك. يجب على أي شخص ترسله إليه أن يفتحه، وهذا يغيّر الإعداد بثلاثة أمور عملية.

تحتاج إلى اسم نطاق يتجه سجل A فيه إلى VPS، قبل تثبيت أي شيء. وتحتاج إلى شهادة منذ اليوم الأول، لأن المتصفحات تعرض نموذج HTTP العادي على أنه غير آمن، ولأن عميلك سيكتب اسمه وبريده الإلكتروني فيه. كما يجب ضبط عنوان URL العام للتطبيق بشكل صحيح في إعداداته، لأن هذه القيمة تُضمَّن في الروابط الموجودة داخل رسائل البريد الإلكتروني الصادرة وفي عناوين URI لإعادة توجيه OAuth. اضبط NEXT_PUBLIC_WEBAPP_URL في Cal.com، أو DOMAIN في Rallly، أو BASE_URL في Easy!Appointments، أو DAYOTTER_DOMAIN أثناء التثبيت، واجعله عنوان https:// الذي ستستخدمه فعلياً.

يتولى Rallly وDayOtter إعداد TLS نيابةً عنك. تتضمن حزمة Rallly المضمّنة Traefik، وتصدر شهادات Let's Encrypt باستخدام العنوان الموجود في ACME_EMAIL. ويشغّل مثبت DayOtter ‏Caddy مع HTTPS تلقائي. أما Cal.com وEasy!Appointments فلا يفعلان ذلك، لذلك تضع nginx أمام التطبيق وتصدر الشهادة بنفسك، بالطريقة نفسها التي تتبعها مع شهادة Let's Encrypt على nginx باستخدام Certbot. اربط حاوية التطبيق بالعنوان 127.0.0.1، بحيث يكون المرور الوحيد إليها عبر الـproxy الذي تتحكم فيه. وإذا كان الخادم نفسه يشغّل بالفعل بديلاً مستضافاً ذاتياً لـTrello للوحاتك الداخلية، فأبقِه خلف المصادقة الحالية، وامنح مضيف الحجز وحده كتلة خادم عامة.

Cal.com على VPS

يوجد إعداد Docker في مستودع مستقل، والصور مبنية مسبقاً على Docker Hub، لذلك اسحب الصورة بدلاً من بنائها.

git clone --recursive https://github.com/calcom/cal.diy.git
cd cal.diy
cp .env.example .env
openssl rand -base64 32
openssl rand -base64 24
docker compose pull
docker compose up -d

ضع القيمة العشوائية الأولى في NEXTAUTH_SECRET والثانية في CALENDSO_ENCRYPTION_KEY. كلتاهما مطلوبة. عيّن DATABASE_URL، واجعل NEXT_PUBLIC_WEBAPP_URL يشير إلى عنوانك العام. تتضمن الحزمة المرفقة تطبيق الويب وPostgreSQL وPrisma Studio. وتوفر الوثائق docker compose up -d calcom لتشغيل التطبيق وحده مع قاعدة بيانات تستضيفها في مكان آخر. وهذا هو الخيار المناسب بعد استقرار التثبيت.

اسحب الصورة ولا تبنها على VPS. توصي تعليمات المشروع نفسها بتصدير NODE_OPTIONS="--max-old-space-size=16384" عند البناء من المصدر. وتخصص هذه القيمة ذاكرة heap بحجم 16 GB لـNode وحده. على الأجهزة التي تستخدم ARM، أضف اللاحقة -arm إلى وسم الصورة. لا يحدد المشروع حداً أدنى لتشغيل الصورة المبنية مسبقاً. لذلك اعتبر 2 GB للتطبيق وPostgreSQL تقديراً عملياً مني، وليس قيمة موثقة. راقب الذاكرة خلال الأسبوع الأول.

تحقق من بدء التشغيل:

docker compose ps
docker compose logs -f calcom
curl -sI https://cal.example.com | head -n 1

يجب أن يطبع أمر curl القيمة HTTP/2 200. تعني استجابة 502 Bad Gateway من nginx، بينما تظهر الحاوية بحالة التشغيل، عادةً أن الإقلاع الأول ما زال يطبّق عمليات ترحيل قاعدة البيانات. انتظر بضع دقائق واقرأ السجلات قبل أن تستنتج وجود عطل. تُشغّل خطافات Cal.com على الويب عند كل حجز مؤكد، لذلك يمكن للحجز تشغيل أي أتمتة تستخدمها بالفعل، مثل مثيل n8n يمكن الوصول إليه عبر HTTPS على VPS.

يخضع المكوّن الأساسي لترخيص AGPLv3، بينما تتوفر بعض الميزات في مجلد enterprise بموجب ترخيص تجاري منفصل. اقرأ ذلك الترخيص قبل إنشاء عملية تجارية مدفوعة تعتمد على ميزات الفرق.

Easy!Appointments على خادم بذاكرة 1 GB

المتطلبات هي Apache أو Nginx، وPHP 8.2 أو أحدث، وMySQL. توجد صورة رسمية في alextselegidis/easyappointments.

تحذير أولاً. إنّ docker-compose.yml في المستودع بيئة تطوير. وتتوقع منك فتح shell داخل الحاوية وتشغيل npm install && composer install && npm start. هذه ليست عملية نشر. استخدم الصورة المنشورة بدلاً منها:

services:
  easyappointments:
    image: alextselegidis/easyappointments  # pin the current tag from Docker Hub
    environment:
      - BASE_URL=https://book.example.com
      - DB_HOST=mysql
      - DB_NAME=easyappointments
      - DB_USERNAME=easyapp
      - DB_PASSWORD=change-me
    ports:
      - '127.0.0.1:8080:80'
    depends_on:
      - mysql
  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=change-me-too
      - MYSQL_DATABASE=easyappointments
      - MYSQL_USER=easyapp
      - MYSQL_PASSWORD=change-me
    volumes:
      - ./mysql:/var/lib/mysql

يجب أن يكون BASE_URL هو عنوان HTTPS العام. إذا أدخلته خطأ، فستشير روابط الحجز داخل رسائل التأكيد بالبريد الإلكتروني إلى مضيف لا يستطيع عميلك الوصول إليه. تعرض الصورة HTTP عاديًا على المنفذ 80 من دون شهادة خاصة بها، ولذلك يُربط المنفذ بـ127.0.0.1، بينما ينهي nginx اتصال TLS أمامها. إذا كانت صياغة Compose جديدة عليك، فابدأ بـأساسيات Docker Compose على VPS ثم عد إلى هنا.

هذا هو الخيار الأخف بفارق كبير. تعمل حاويتان، واحدة لتطبيق PHP وأخرى لـMySQL، بسهولة على VPS بذاكرة 1 GB. لكن ذلك يحد من الخيارات: Google Calendar هو الواجهة الخلفية الوحيدة للتقويم، والواجهة عبارة عن لوحة إدارة تقليدية وليست مسار حجز حديثًا. إذا كان تقويمك هو Microsoft 365 أو Fastmail أو Nextcloud، فهذا الخيار غير مناسب لك من البداية.

Rallly لاستطلاعات المجموعة

يجيب Rallly عن سؤال مختلف. فهو لا ينشر أوقات توفرك. بل يعرض مجموعة من الأوقات المقترحة على مجموعة ويجمع الأصوات، وهذا ما تحتاج إليه لاجتماع مجلس الإدارة، لكنه لا يفيد في رابط حجز للعميل.

curl -fsSL https://get.rallly.co | bash

اقرأ أي برنامج نصي قبل تمريره إلى shell. استبدل bash بـ less، واقرأ ما يفعله، ثم شغّله. ينفّذ المسار اليدوي العمل نفسه ضمن خطوات يمكنك رؤيتها:

git clone https://github.com/lukevella/rallly-selfhosted.git
cd rallly-selfhosted
./rallly.sh setup
./rallly.sh start

المتطلبات الموثقة هي 2 GB على الأقل من RAM، وDocker 19.03 أو إصدار أحدث مع Compose v2، وتوفّر المنفذين 80 و443، وتوجيه نطاق إلى الخادم. تتضمن الحزمة المضمّنة Traefik لتوفير HTTPS، وتطبيق الويب، وPostgreSQL، وGarage لتوفير تخزين كائنات متوافق مع S3. اضبط DOMAIN، وSECRET_PASSWORD بطول لا يقل عن 32 محرفاً، وSUPPORT_EMAIL وINITIAL_ADMIN_EMAIL. إذا كنت تشغّل reverse proxy مسبقاً، فاضبط PROXY_MODE=external وWEB_PORT، وسيبقى Traefik خارج المسار. وإذا كنت تشغّل مسبقاً مخزناً ذاتي الاستضافة ومتوافقاً مع S3 باستخدام MinIO، فوجّه متغيرات S3_* إليه وأزل حاوية Garage.

لا يُعد SMTP اختيارياً هنا، لأن تسجيل الدخول يتم عبر رابط سحري. من دون relay يعمل، لن يتمكن أحد من تسجيل الدخول، بما في ذلك حساب المسؤول الذي أنشأته للتو. هذه هي الحالة الجيدة لفشل البريد الإلكتروني: فهو يوقفك عند نقطة الدخول بدلاً من أن يؤدي إلى فقدان حجز عميل بعد 3 أسابيع.

DayOtter، الوافد الأحدث

DayOtter منصة جدولة مرخّصة بموجب AGPLv3، ومرفق بها مساعد. يتطلب تثبيت الإنتاج أمراً واحداً:

curl -fsSL https://raw.githubusercontent.com/Dayotter/dayotter/main/deploy/install.sh \
  | sudo DAYOTTER_DOMAIN=cal.example.com bash

اقرأه قبل تشغيله، كما سبق. يثبّت برنامج التثبيت Docker، وينشئ الأسرار، ويشغّل الحزمة الكاملة: تطبيق الويب Next.js، وعاملاً في الخلفية يتولى التذكيرات ومزامنة التقويم وwebhooks، وPostgreSQL، وRedis، وCaddy مع HTTPS تلقائي.

دعم التقويم هو الأوسع بين المنصات الأربع. يشمل Google وMicrosoft 365 وApple عبر CalDAV وخلاصات ICS، مع التحفظ المتعلق بـICS المذكور أعلاه. جميع عمليات التكامل الأخرى اختيارية عبر متغيرات البيئة، بما في ذلك SMTP أو Resend للبريد، وANTHROPIC_API_KEY للمساعد، وTwilio للرسائل النصية، وStripe للمدفوعات. يعمل المساعد وفق مبدأ التأكيد أولاً: يقترح، ثم توافق أنت، ولا يُضاف شيء إلى تقويمك من دون موافقة صريحة. إذا تركت مفتاح API فارغاً، فلن يعمل هذا الجزء من المنتج ببساطة.

الترخيص واضح لمشغّلي الاستضافة الذاتية. النواة مرخّصة بموجب AGPLv3، ويحتوي دليل ee/ على ترخيص تجاري مخصص للسحابة فقط، ويظل غير نشط ما لم يتم تعيين DAYOTTER_CLOUD=1. وهذا يعني أن ميزات الفريق التي تفرض الخطة المستضافة رسوماً عليها بقيمة $9 لكل مقعد شهرياً، اعتباراً من August 2026، متاحة على خادمك الخاص.

هذه أيضاً أثقل حزمة هنا وأحدث مشروع. شغّلها إلى جانب رابط الحجز الحالي لمدة أسبوعين، واستقبل حجوزات فعلية عبر النظامين، واقرأ سجلات العامل قبل نقل عملائك إليه.

ما الذي تكلّفك به كل حزمة فعلياً

يمثل عدد الحاويات مؤشراً صادقاً إلى حجم الموارد التي ستطلبها الحزمة من VPS صغير، لأن كل خدمة تفرض حداً أدنى خاصاً بها من الذاكرة. هذه هي الأعداد الواردة في Docker stack المنشورة من كل مشروع، بعد الاطلاع عليها في أغسطس 2026.

ChartServices in each project's documented Docker stack
The data behind this chart
[
  {
    "tool": "Easy!Appointments",
    "containers": 2,
    "database": "MySQL"
  },
  {
    "tool": "Cal.com",
    "containers": 3,
    "database": "PostgreSQL"
  },
  {
    "tool": "Rallly",
    "containers": 4,
    "database": "PostgreSQL"
  },
  {
    "tool": "DayOtter",
    "containers": 5,
    "database": "PostgreSQL and Redis"
  }
]

الأمر سهل! يحتاج Easy!Appointments إلى 2 حاويات، ويعمل ضمن 1 GB. أما الحزمة المضمّنة في Rallly فتتكون من 4، وتطلب وثائقها 2 GB. ويشغّل مثبّت DayOtter 5، ولذلك يحتاج إلى أكبر خادم ضمن 4 المعروض هنا. لا ينشر Cal.com وDayOtter أي رقم للحد الأدنى من الذاكرة، لذلك أبدأ بـ2 GB لكليهما، لا باعتباره رقماً مدعوماً رسمياً.

ينخفض رقمان من هذه الأعداد إذا كنت تشغّل البنية التحتية مسبقاً. يمكنك إزالة حاويتي Traefik وGarage من Rallly عند توجيهه إلى الـproxy الخاص بك وتخزين الكائنات الخاص بك. أما Prisma Studio في Cal.com فهي أداة تطوير، ولا ينبغي أن تتركها قيد التشغيل على خادم عام.

ما بديل Calendly المستضاف ذاتياً الذي ينبغي اختياره

ينبغي للاستشاري المستقل تشغيل Cal.com. فهو المشروع الوحيد هنا الذي يجمع بين صفحة حجز مألوفة للناس، وصور جاهزة تغنيك عن إجراء عملية بناء لـNode على VPS، ومسار CalDAV لمن لا يحتفظون بتقويم على Google أو Microsoft. تمثل قاعدة بيانات PostgreSQL واحدة وحاوية تطبيق واحدة عبء صيانة يمكنك تحمّله لسنوات. خصص فترة بعد الظهر لإعداد عميل OAuth ومرحل البريد، وانتبه إلى أن تطبيق CalDAV لا يزال في المرحلة التجريبية، لذلك اختبر حجزاً حقيقياً واحداً من البداية إلى النهاية قبل نشر الرابط.

ينبغي للفريق الصغير إلقاء نظرة على DayOtter. توجد آلية التناوب الموزون والحجز الجماعي ضمن النواة المرخّصة بموجب AGPLv3، لذا يمنحك التشغيل المستضاف ذاتياً الميزات التي تُفرض رسوم عليها لكل مقعد في الخدمة المستضافة. كما أن عملية worker مصممة للتذكيرات وwebhooks التي يعتمد عليها الفريق فعلياً. المقابل هو حداثة المشروع: فهو أحدث مشروع في هذه القائمة، لذلك شغّله بالتوازي أولاً، وأبقِ الرابط القديم فعالاً إلى أن تراقب حجوزات شهر كامل.

هناك حالتان أضيق نطاقاً. إذا كان كل ما تحتاج إليه هو استطلاع للعثور على وقت مناسب لاجتماع المجموعة، فثبّت Rallly واكتفِ بذلك. وإذا كان لديك VPS بسعة 1 GB، وتعتمد على Google Calendar، وتريد أصغر حل يستقبل حجزاً، فسيستمر Easy!Appointments في العمل مدة أطول من أي خيار أكثر تعقيداً يمكنك وضعه على ذلك الخادم. ولمعرفة ما الذي يستحق مساحة على الخادم نفسه في الحالات الأوسع، راجع ما الذي يستحق الاستضافة الذاتية في 2026.

FAQ

هل يمكنني تشغيل صفحة حجز مستضافة ذاتياً من دون اسم نطاق؟

لا. تكتب كل هذه التطبيقات عنوان URL العام في الروابط داخل رسائل تأكيد البريد الإلكتروني، ويطابق كل من Google وMicrosoft عنوان إعادة توجيه OAuth مع القيمة نفسها، لذلك يعرض استخدام عنوان IP مجرد redirect_uri_mismatch في شاشة الموافقة. كما أن Let's Encrypt لا تصدر شهادة لعنوان IP، ولذلك تُحمَّل الصفحة عبر HTTP العادي ويضع المتصفح علامة على أن النموذج غير آمن. اشترِ اسم النطاق أولاً، ووجّه سجل A إلى VPS، ثم ثبّت التطبيق.

لماذا لا تصل رسائل تأكيد الحجز عبر البريد الإلكتروني؟

السبب في الغالب هو أن الخادم يحاول تسليم البريد بنفسه. يحظر معظم موفري VPS المنفذ الصادر 25 في الحسابات الجديدة، لذلك يتوقف الاتصال، وحتى عندما يكون المنفذ مفتوحاً لا يملك العنوان الجديد سمعة إرسال، فترفضه خوادم الاستلام الكبيرة. وجّه التطبيق إلى مرحّل بريد للرسائل المعاملاتية عبر المنفذ 587، وتأكد من إمكانية الوصول إلى المنفذ باستخدام nc -vz -w 5 "$SMTP_HOST" 587، ثم انشر سجلي SPF وDKIM اللذين يقدمهما المرحّل. إذا كنت تشغّل Cal.com، فتحقق من استبدال الإعدادين الافتراضيين EMAIL_SERVER_HOST=localhost وEMAIL_SERVER_PORT=1025 اللذين يأتي بهما التطبيق، إذ إنهما يشيران إلى صندوق بريد تطوير محلي.

هل يتزامن Cal.com المستضاف ذاتياً مع CalDAV، أم مع Google فقط؟

كلاهما، مع اختلاف مستوى النضج. تطبيق CalDAV مصنّف كإصدار تجريبي، وقد جرى التحقق منه مع خوادم تشمل Baikal وRadicale وNextcloud وKerio Connect، كما يعمل Apple iCloud من خلاله باستخدام كلمة مرور خاصة بالتطبيق. يتزامن كل من Google Calendar وMicrosoft 365 في الاتجاهين، لكن يجب عليك في التثبيت المستضاف ذاتياً إنشاء عميل OAuth الخاص بك وتقديمه عبر GOOGLE_API_CREDENTIALS، لأن بيانات اعتماد الخدمة المستضافة غير موجودة في المصدر.

لماذا يتوقف تزامن Google Calendar عن العمل بعد أسبوع؟

لأن حالة نشر مشروع Google Cloud ما زالت Testing. تصدر Google رموز تحديث للتطبيقات في هذه الحالة وتنتهي صلاحيتها بعد 7 أيام، لذلك يعمل الاتصال ثم يتوقف عند محاولة تحديث الرمز التالية، ويعرض سجل التطبيق invalid_grant. انقل شاشة موافقة OAuth إلى In production، ثم أعد ربط التقويم مرة واحدة. إن أعدت الربط دون تغيير الحالة، فستحصل على 7 أيام إضافية فقط.

أيّ من هذه التطبيقات سيعمل على VPS بسعة 1 GB؟

سيعمل Easy!Appointments، لأنه تطبيق PHP مع MySQL. يذكر Rallly أن الحد الأدنى هو 2 GB، وتُشغّل حزمته المضمنة أربع خدمات. لا يحدد Cal.com وDayOtter حداً أدنى، لكن تطبيق Next.js مع PostgreSQL، ومع Redis وعملية worker أيضاً في حالة DayOtter، يعني أنه ينبغي التخطيط لسعة 2 GB أو أكثر. لا تبنِ Cal.com من المصدر على خادم صغير. تطلب تعليمات البناء الخاصة بالمشروع heap لـNode بسعة 16 GB، لذا استخدم الصورة المبنية مسبقاً بدلاً من ذلك.

#scheduling#calendly#cal-com#self-hosted#booking