Jitsi ذاتي الاستضافة مقارنةً بـZoom: ما الذي يتغيّر فعلًا
تفرض خدمات مؤتمرات الفيديو الموجَّهة للجمهور العام (Zoom وGoogle Meet وTeams) حدودًا زمنية في الخطط المجانية، وحصصًا للمشاركين، وتحتفظ بتسجيلاتك على خوادمها. يزيل Jitsi Meet، عند استضافته ذاتيًا، هذه القيود: غرف غير محدودة، ومدة غير محدودة، ولا حساب مطلوب للانضمام إلى اجتماع، وتدفّقات الفيديو تبقى على بنيتك التحتية. وهذا وجيه بوجه خاص لمؤسسة تحرص على سرّية اجتماعاتها، أو مكتب يتعامل مع بيانات حساسة، أو لمن يريد دمج الفيديو في تطبيق خارجي (يوفّر Jitsi واجهة iframe API مستقرة). تُختصر تكاليف التشغيل في فاتورة خادم VPS — لا اشتراك بالمقعد، ولا رسوم إضافية للبرمجيات.
فوائد ملموسة لـJitsi ذاتي الاستضافة
- اجتماعات دون حدّ زمني ودون سقف لعدد الغرف — لا عدّاد يقطع الاتصال.
- لا حساب مطلوب للمشاركين: رابط بسيط يكفي للانضمام.
- واجهة iframe API لدمج الفيديو مباشرةً في تطبيقك أو موقعك.
- تشفير النقل (DTLS-SRTP) والتحكم الكامل في أي تسجيلات.
- تخصيص كامل: الشعار والألوان واسم نطاق الغرف.
- لا قياس عن بُعد يُرسَل إلى طرف ثالث — تدفّقات الفيديو لا تغادر خادم VPS الخاص بك.
متطلبات مُحدَّدة بالأرقام قبل البدء
Jitsi يُحجَّم بـعرض النطاق الترددي، لا بوحدة المعالجة (CPU). توصي وثائق Jitsi بـ8 غيغابايت RAM (تكفي 4 غيغابايت للاجتماعات الصغيرة)، ونحو 4 أنوية مخصّصة لخادم أساسي، وقبل كل شيء رابط شبكة موثوق: يستهلك تدفّق 720p نحو 2.5 Mbit/s، ورابط بسرعة 100 Mbit/s لا يحتمل عشرين مشاركًا بدقة عالية. راقِب حِمل شبكة JVB. ثلاثة منافذ يجب أن تكون قابلة للوصول من الإنترنت: TCP 443 (HTTPS)، وTCP 80 (تحدّي Let's Encrypt وإعادة التوجيه إلى HTTPS)، وUDP 10000 (وسائط JVB). المنفذ TCP 4443 الذي تذكره أدلة قديمة لم يعد في القائمة الرسمية. إن كان coturn يعمل على خادم VPS نفسه، أضِف منافذه: 3478 عبر UDP وTCP، و5349 عبر TLS (المنفذ 443 تشغله حاوية web). تحتاج Docker مع Compose V2 (الأمر docker compose)، واسم نطاق meet.yourdomain.com مع سجل A يشير إلى IP عام لخادم VPS، وعنوان IP عام مخصّص وثابت — عنوان IP مشترك يُعقِّد إعداد coturn تعقيدًا كبيرًا.
النشر خطوة بخطوة: Docker و.env وcoturn وأول اختبار
جلب docker-jitsi-meet
نزّل أحدث إصدار من صفحة الإصدارات في
github.com/jitsi/docker-jitsi-meetوفُكّ ضغطه: الدليل الرسمي لا ينصح باستنساخ المستودع، إذ يسحب فرعه الرئيسي صورunstable. أنشئ مجلدات الإعداد التي يذكرها الدليل (~/.jitsi-meet-cfg/…، ومنهاstorageوtmp، قابلة للكتابة من المستخدم uid 1000): تعمل الحاويات دون صلاحيات root وترفض الإقلاع بدون ذلك. انسخenv.exampleإلى.env، ثم نفّذ./gen-passwords.sh— يولّد هذا السكربت جميع الأسرار الداخلية (Prosody وJicofo وJVB). لا تتجاوز هذه الخطوة: القيم الافتراضية ليست أسرارًا. الإصدارstable-11248-3(نوفمبر 2026) هو آخر إصدار مستقر؛ تجنّبmasterوصورunstableفي الإنتاج — المكوّنات الداخلية تتغيّر دون إشعار مسبق.ضبط PUBLIC_URL والمنافذ وJVB_ADVERTISE_IPS
في
.env، اضبط أولًاHTTP_PORT=80وHTTPS_PORT=443(القيمتان الافتراضيتان 8000 و8443). ثم متغيّران حاسمان:PUBLIC_URL=https://meet.yourdomain.com(يستخدمه العميل الويب لبناء عناوين URL للغرف)، وJVB_ADVERTISE_IPS=<IP_عامة_لـVPS>(العنوان الذي يُعلنه JVB للعملاء لإنشاء اتصال الوسائط المباشر؛ وهو يحلّ محلّ المتغيّر القديمDOCKER_HOST_ADDRESS). بدونJVB_ADVERTISE_IPSيحاول JVB اكتشاف عنوانه العام عبر STUN؛ وإن كان العنوان المُعلَن خاطئًا تفشل المكالمات بمجرد انضمام أكثر من مشاركَين.تفعيل Let's Encrypt في .env
أضِف إلى
.env:ENABLE_LETSENCRYPT=1، وLETSENCRYPT_DOMAIN=meet.yourdomain.com، و[email protected]. تحقّق من أن المنفذ 80 مفتوح قبل التشغيل — يستخدم Let's Encrypt تحدي HTTP-01 الذي يستلزم ردًّا على هذا المنفذ. تحصل حاوية web على الشهادة وتجدّدها بأداة acme.sh (خدمة تجديد داخلية) وتحفظها في ~/.jitsi-meet-cfg/storage/web: احتفِظ بهذا المجلد عبر إعادة التشغيل. أضِف أيضًاLETSENCRYPT_ACME_SERVER=letsencrypt: بدونه تتوجّه acme.sh افتراضيًا إلى ZeroSSL.إعداد coturn (خادم TURN)
هذه الخطوة التي يتجاوزها معظم الأدلة وتتسبّب في فشل التثبيت. لا يتضمّن docker-jitsi-meet خادم coturn: ثبّته على حدة (حزمة أو حاوية)، ثم صرّح به في
.envكي يسلّم Prosody العملاءَ بيانات اعتماد مؤقتة:TURNS_HOST=turn.yourdomain.comوTURNS_PORTلـTLS، إضافةً إلىTURN_HOST=turn.yourdomain.comوTURN_PORT=3478وTURN_TRANSPORT=udp,tcp. المنفذ 443 عبر TLS يخترق أشد الجدران تقييدًا التي تحجب المنافذ غير المعيارية لكنها تسمح بما يشبه HTTPS؛ لكنه يتطلّب عنوان IP لا تشغله حاوية web، وإلا فاحتفِظ بالمنفذ 5349.ثم ولّد سرًّا مشتركًا (
openssl rand -hex 32) وضعه فيTURN_CREDENTIALSداخل.envوفي coturn (use-auth-secretوstatic-auth-secret=<السرّ نفسه>)؛ ولا تستخدمno-authأبدًا، فهو يجعل خادمك مُرحِّلًا مفتوحًا للجميع. تُعلَن شهادة TLS في إعداد coturn (cert=وpkey=)، لا في.env. إن كان coturn يعمل في حاوية منفصلة، ارفع هذه الملفات كأحجام volume.تفصيل كثيرًا ما يُنسى: لا يحجب coturn افتراضيًا نطاقات RFC1918 (192.168.x.x و10.x.x.x و172.16.x.x): يرفض عنوان loopback فقط. لذا يستطيع عميل مُصادَق ترحيل حركة نحو شبكتك الداخلية. أضِف
no-multicast-peersوأسطرdenied-peer-ipلهذه النطاقات، ثم، إن كان لـJVB عنوان داخلي، اسمح به وحده عبرallowed-peer-ip.تشغيل الحزمة والتحقق من JVB
نفّذ
docker compose up -d. انتظر 30 ثانية، ثم:docker compose logs jvb 2>&1 | grep -E 'register|connected|error'. يجب أن ترى سطرًا يُظهر أن JVB سُجِّل لدى Jicofo. إن ظهرFailed to registerأوConnection refused، فـProsody لم يستعدّ بعد — أعِد المحاولة بعد دقيقة. ثم تحقّق من أن المنافذ تستجيب:nc -zv meet.yourdomain.com 443(web، TCP) وnc -zv turn.yourdomain.com 3478(coturn، TCP) وnc -zvu meet.yourdomain.com 10000(JVB، UDP؛ نجاح اختبار UDP مؤشّر فقط).أول اختبار فيديو من شبكتين مختلفتين
افتح
https://meet.yourdomain.comمن جهازك المعتاد ومن جهاز ثانٍ على شبكة مختلفة (هاتف بالاتصال عبر شبكة الجوّال مثلًا). إن رأى المشاركان بعضهما وسمعا بعضهما، فـTURN يعمل. الاختبار بين جهازين على الشبكة المحلية ذاتها لا يُثبت صحة coturn — ينجح باتصال نظير-لنظير دون أن يستدعي المُرحِّل قطّ.
الإعداد المتقدّم: التسجيل والمصادقة والحدود
تسجيل الاجتماعات. يتضمّن Jitsi أداة Jibri للتسجيل المحلي أو البثّ عبر RTMP. يلتقط Jibri عرض متصفح في الوقت الفعلي: النسخة الواحدة لا تسجّل إلا اجتماعًا واحدًا في كل مرة، وتطلب وثائق Jitsi ما لا يقل عن 8 غيغابايت RAM لكل نسخة بدقة 720p، ويُفضَّل تشغيلها على خادم منفصل. فعّل ENABLE_RECORDING=1 في .env وشغّل حاوية Jibri المرفقة: docker compose -f docker-compose.yml -f jibri.yml up -d. مصادقة المنظِّمين. افتراضيًا يمكن لأي شخص إنشاء غرفة: النسخة العامة المتروكة هكذا تصبح خدمة فيديو مجانية للغرباء على حساب عرض النطاق الخاص بك. فعّل ENABLE_AUTH=1 وAUTH_TYPE=internal وENABLE_GUESTS=1 لاشتراط حساب من جهة المنظِّم مع ترك الضيوف ينضمّون بحرية. أنشئ حسابات المضيفين بـ: docker compose exec prosody prosodyctl --config /run/prosody/config/prosody.cfg.lua register admin meet.jitsi <كلمة_مرور>: النطاق meet.jitsi هو نطاق XMPP الداخلي لا اسمك العام، وتُولَّد كلمة المرور (openssl rand -base64 18) بدل إعادة استخدام كلمة قديمة. تقييد المشاركين المجهولين. يجعل ENABLE_LOBBY=1 غرفة الانتظار متاحة: بعد أن يفعّلها المشرف، يجب الموافقة على كل دخول قبل الوصول إلى الغرفة. مجتمعًا مع ENABLE_AUTH=1، يمنحك ذلك تحكمًا كاملًا فيمن يصل إلى ماذا.
التصليب الأمني: fail2ban على خدمة TURN
يكشف coturn خدمةً قابلة للوصول من الإنترنت. ثبّت fail2ban وأنشئ مرشّحًا على محاولات مصادقة TURN الفاشلة: تظهر حالات الفشل في سجل coturn مع الرمز 401؛ تحقّق من الصيغة الدقيقة في نسختك قبل كتابة التعبير النمطي للمرشّح. سجن fail2ban بـmaxretry=10 وbantime=600 يكفي لردع المسح الآلي دون التأثير على مستخدميك الشرعيين. ثبّت مسار السجل بـlog-file=/var/log/turnserver.log في إعداد coturn (بدون هذا الخيار يختار coturn ملفًا بنفسه في /var/log أو /var/tmp أو /tmp)، واجعل fail2ban يراقب هذا المسار، أو ارفع هذا الملف من الحاوية.
استكشاف الأخطاء: الأخطاء الأربعة الأكثر شيوعًا
غياب الصوت أو الفيديو العالق على «connecting» — coturn ومنفذ UDP 10000. هذا العطل الأكثر تكرارًا. افحص بهذا الترتيب: (1) ufw status — هل المنفذان TCP 443 وUDP 10000 مفتوحان؟ (2) سجلات coturn (journalctl -u coturn عند التشغيل الأصلي، وdocker logs <حاوية-coturn> خلاف ذلك) — هل يبدأ coturn بلا أخطاء في الشهادة؟ (3) من جهاز خارجي: curl -v telnet://meet.yourdomain.com:3478 — هل يستجيب coturn؟ (4) في سجلات المتصفح (F12 ← Console): هل ترى ICE failed أو failed to gather candidates؟ إن كان كذلك، coturn لا يمكن الوصول إليه من الخارج. تحقّق من أن TURN_HOST وTURNS_HOST في .env يُحَلّان فعلًا إلى عنوان IP خادم coturn. رفض الاتصال على TCP 443. إن لم يتمكّن Let's Encrypt من إصدار شهادة (المنفذ 80 كان مغلقًا عند الإطلاق الأول)، تتوقف حاوية web بعد الرسالة Failed to obtain a certificate from the Let's Encrypt CA ولا يعود شيء يستجيب على المنفذ 443. الحلّ: افتح المنفذ 80، وتحقّق من HTTP_PORT=80، وأعِد تشغيل docker compose up -d؛ لا داعي لحذف الإعداد، وكل محاولة جديدة تُحتسب ضمن حدود Let's Encrypt. رفض مشاركة الشاشة من المتصفح. تستلزم مشاركة الشاشة سياقًا آمنًا (HTTPS صالح). إن رأيت getUserMedia is not supported، الشهادة غير صالحة أو النطاق ليس على HTTPS. راجِع PUBLIC_URL — يجب أن تبدأ بـhttps:// مع نطاق شهادته صالحة، لا بعنوان IP خام. خطأ «ICE failed» مستمر رغم عمل coturn. افحص المتغيّر JVB_ADVERTISE_IPS (سابقًا DOCKER_HOST_ADDRESS): يجب أن يحتوي على IP العام لـVPS، لا على IP الداخلي لحاوية Docker (172.17.x.x). إن كان VPS الخاص بك خلف NAT سحابيًا (نادر لكن ممكن)، فأنت بحاجة إلى IP NAT الخارجي، لا IP واجهة الشبكة.
المراقبة: رصد عرض النطاق الترددي وعدد المشاركين
يكشف جسر الفيديو JVB واجهة إحصاءات في الوقت الفعلي على http://localhost:8080/colibri/stats. تُبلَّغ هذه النقطة بصيغة JSON عن عدد المؤتمرات النشطة والمشاركين وعرض النطاق الترددي الوارد والصادر بالكيلوبت/الثانية ومتوسط زمن الذهاب والإياب (rtt_aggregate). لا يُنشَر المنفذ 8080 إلا على 127.0.0.1: أبقِه كذلك. للمراقبة المستمرة، يكشف JVB مقاييسه أصلًا بصيغة Prometheus على /metrics (المنفذ الخاص نفسه)؛ ومن جهة Prosody، فعّل PROSODY_ENABLE_METRICS=1 في .env. ثم صِل مجموعة Prometheus + Grafana: يوفّر المستودع الملفين prometheus.yml وgrafana.yml، وهما ينشران المنفذين 9090 و3000 على كل الواجهات. قيّدهما بـ127.0.0.1 أو بشبكة VPN، لأن المنافذ التي ينشرها Docker تتجاوز قواعد ufw.
بدون Prometheus، تتحقّق رقابة دنيا بمهمة cron تستعلم /colibri/stats وتنبّه حين يتجاوز الإنتاجية حدًّا معيّنًا: curl -s http://127.0.0.1:8080/colibri/stats | python3 -c "import json,sys; s=json.load(sys.stdin); print(s.get('bit_rate_download',0), s.get('bit_rate_upload',0))".
لتقدير الطاقة الاستيعابية قبل الإشباع: تعتمد طاقة JVB أولًا على رابط الشبكة والدقّات المُرسَلة؛ قِسها على حِملك الفعلي بدل الاعتماد على رقم عام. وحين يقترب الحدّ يرتفع مقياس rtt_aggregate وتنخفض الجودة المُدرَكة قبل أن تنشغل وحدة المعالجة — هذه هي الإشارة لإضافة نسخة JVB أخرى.
خادم Jitsi جاهز — أدِر عرض النطاق الترددي
يعمل Jitsi في وضع SFU: يعيد جسر الفيديو (JVB) ترحيل كل تدفّق إلى كل مشارِك، فيتناسب عرض النطاق الترددي الصادر مع عدد المشاركين مضروبًا في عدد التدفّقات. يزن تدفّق 720p نحو 2.5 Mbit/s وفق وثائق Jitsi: اضربه في عدد التدفّقات المُرسَلة فعلًا إلى كل مشارك لتقدير المعدّل الصادر. اضبط channelLastN: 5 في custom-config.js (مجلد web في الإعداد) لاستقبال آخر N فيديوهات نشطة فقط للحدّ من التدفّقات من جانب العميل في الاجتماعات الكبيرة، وراقِب docker stats jvb لاستباق الإشباع. ما فوق عشرين مشاركًا متزامنًا بصورة منتظمة، انشُر عدة نُسخ من JVB على خوادم VPS منفصلة خلف Jicofo واحد: هذه بنية التوسّع الأفقي الأصيلة في Jitsi. وللنشر متعدّد المؤسسات أو متعدّد النطاقات، تذكّر أن تثبيت docker-jitsi-meet له PUBLIC_URL واحد فقط: إن احتاجت كل مؤسسة حساباتها الخاصة وفضاء غرف معزولًا، فخصّص نسخة لكل مؤسسة على نطاقها الفرعي الخاص.