[{"data":1,"prerenderedAt":192},["ShallowReactive",2],{"seo-verification":3,"blog-استضافة-centrifugo-على-vps-خادم-زمن-حقيقي-ar":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-استضافة-centrifugo-على-vps-خادم-زمن-حقيقي-ar",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":20,"publishedAt":21,"updatedAt":22,"category":23,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":33,"intro":36,"sections":37,"ctaTitle":120,"ctaBody":121,"ctaButton":122,"ctaUrl":123,"relatedPosts":124},569,"استضافة-centrifugo-على-vps-خادم-زمن-حقيقي",{"fr":12,"en":13,"ar":10,"es":14},"self-host-centrifugo-vps","self-host-centrifugo-vps-real-time-server","autoalojar-centrifugo-vps-servidor-tiempo-real","Centrifugo على VPS: خادم زمن حقيقي مستضاف ذاتيًا","ثبّت Centrifugo على خادم افتراضي: خادم زمن حقيقي مفتوح المصدر لدفع رسائل WebSocket من الخادم الخلفي لتطبيقك، مع رموز JWT وواجهة نشر.",7,0,false,true,"2026-11-07T00:00:00+00:00","2026-11-08T01:13:02+00:00",{"id":17,"name":24,"slug":25,"color":26,"icon":27},"الاستضافة الذاتية","self-hosting","bg-indigo-500\u002F10 text-indigo-400","cloud",[29],{"id":17,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fself-host-centrifugo-vps-poster.svg",{"categorySlug":34,"appSlug":35},"التطوير","centrifugo","عرض إشعار لحظة دفع الطلب، أو تشغيل دردشة، أو تحديث لوحة متابعة دون إعادة تحميل الصفحة: كل ذلك يتطلب اتصالًا مفتوحًا باستمرار بين الخادم والمتصفح. تؤدي خدمات مثل Pusher أو Ably هذا العمل جيدًا، لكنها تفوتر كل اتصال وكل رسالة، وتمر بياناتك عبرها. ‏Centrifugo خادم مراسلة فورية مفتوح المصدر (رخصة Apache-2.0) مكتوب بلغة Go، يؤدي العمل نفسه على خادمك الافتراضي. يثبّته هذا الدليل باستخدام Docker Compose، ويضعه خلف nginx عبر HTTPS، ثم يشرح كيف تنشر من الخادم الخلفي وتربط متصفحًا برمز JWT.",[38,42,52,79,82,95,99,102,105,108,111,114,117],{"type":39,"title":40,"body":41},"h2","كيف يعمل Centrifugo","يقع Centrifugo بين تطبيقك ومستخدميه. لا يُبقي خادمك الخلفي — Laravel أو Django أو Express أو Rails أو غيرها — أي اتصال مفتوحًا: يوقّع رمزًا لكل مستخدم، ثم ينشر الرسائل بطلب HTTP بسيط. أما Centrifugo فيحافظ على اتصالات WebSocket للمتصفحات وتطبيقات الجوال، ويوصل كل رسالة إلى مشتركي القناة المعنية.\n\nلهذا الفصل فائدة ملموسة: يبقى تطبيقك بلا حالة وسهل النشر، ويتسع جزء الزمن الحقيقي في ملف Go تنفيذي واحد يستهلك بضع عشرات من الميغابايت من الذاكرة في وضع الخمول.",{"type":43,"title":44,"items":45},"ul","ما يقدّمه Centrifugo",[46,47,48,49,50,51],"**اتصالات WebSocket** — مع حزم رسمية للعملاء بلغات JavaScript وDart\u002FFlutter وSwift وJava\u002FAndroid وGo وPython.","**واجهة نشر** — طلب HTTP POST مع الترويسة `X-API-Key`، من أي لغة.","**رموز JWT** — يقرر خادمك الخلفي من يتصل وبأي قنوات، ويتحقق Centrifugo من التوقيع.","**اشتراكات من جهة الخادم** — تنتقل قائمة قنوات المستخدم داخل رمزه.","**لوحة إدارة** — حالة العقدة والعملاء المتصلون وأوامر الواجهة من المتصفح.","**إعدادات افتراضية حذرة** — لا اتصال مجهول، ولا نشر من المتصفح دون إذن صريح.",{"type":53,"title":54,"headers":55,"rows":58},"comparison","Centrifugo مقارنة بخدمة مستضافة",[5,56,57],"Centrifugo على VPS","Pusher وAbly",[59,63,67,71,75],[60,61,62],"الفوترة","سعر الخادم دون حد للرسائل","حسب الاتصالات والرسائل",[64,65,66],"مسار البيانات","على خادمك","عبر المزوّد",[68,69,70],"بروتوكول العميل","WebSocket وحزم رسمية","WebSocket وحزم مملوكة",[72,73,74],"المصادقة","JWT يوقّعه خادمك الخلفي","توقيع خاص بالخدمة",[76,77,78],"التشغيل","على عاتقك","يتولاه المزوّد",{"type":39,"title":80,"body":81},"المتطلبات","خادم افتراضي بنظام Ubuntu 24.04 بذاكرة 1 غيغابايت ومساحة 10 غيغابايت، مع Docker وإضافة Compose، ونطاق فرعي يشير إلى الخادم، مثل `rt.example.com`. ‏HTTPS ليس اختياريًا: لا يستطيع موقع يُقدَّم عبر HTTPS فتح اتصالات غير `wss:\u002F\u002F`، ويجب ألا يمر مفتاح الواجهة بنص واضح أبدًا.",{"type":83,"title":84,"steps":85},"steps","تثبيت Centrifugo باستخدام Docker Compose",[86,89,92],{"title":87,"body":88},"توليد الأسرار","أنشئ مجلد التطبيق وملف `.env` يحمل أربعة أسرار مختلفة: كلمة مرور اللوحة، والمفتاح الذي يوقّع جلساتها، ومفتاح واجهة الخادم، ومفتاح HMAC لرموز العملاء.\n```bash\nmkdir -p \u002Fopt\u002Fcentrifugo && cd \u002Fopt\u002Fcentrifugo\n{\n  echo \"ADMIN_PASSWORD=$(openssl rand -hex 12)\"\n  echo \"SECRET_KEY=$(openssl rand -hex 24)\"\n  echo \"ENCRYPTION_KEY=$(openssl rand -hex 16)\"\n  echo \"ENCRYPTION_KEY_HEX64=$(openssl rand -hex 32)\"\n} > .env\nchmod 600 .env\n```",{"title":90,"body":91},"كتابة ملف docker-compose.yml","يُنشر المنفذ على الواجهة المحلية فقط: لا يصل إليه إلا nginx. استبدل `https:\u002F\u002Fapp.example.com` بعنوان موقعك.\n```yaml\nservices:\n  centrifugo:\n    image: centrifugo\u002Fcentrifugo:v6.10.2\n    restart: unless-stopped\n    command: [\"centrifugo\"]\n    ports:\n      - \"127.0.0.1:8000:8000\"\n    environment:\n      CENTRIFUGO_ADMIN_ENABLED: \"true\"\n      CENTRIFUGO_ADMIN_PASSWORD: \"${ADMIN_PASSWORD}\"\n      CENTRIFUGO_ADMIN_SECRET: \"${SECRET_KEY}\"\n      CENTRIFUGO_HTTP_API_KEY: \"${ENCRYPTION_KEY}\"\n      CENTRIFUGO_CLIENT_TOKEN_HMAC_SECRET_KEY: \"${ENCRYPTION_KEY_HEX64}\"\n      CENTRIFUGO_CLIENT_ALLOWED_ORIGINS: \"https:\u002F\u002Fapp.example.com\"\n      CENTRIFUGO_HEALTH_ENABLED: \"true\"\n    ulimits:\n      nofile:\n        soft: 65535\n        hard: 65535\n```",{"title":93,"body":94},"التشغيل والتحقق","شغّل الحاوية واستعلم نقطة الصحة؛ يجب أن تجيب بـ `{}`.\n```bash\ndocker compose up -d\ncurl -fsS http:\u002F\u002F127.0.0.1:8000\u002Fhealth\n```",{"type":96,"title":97,"body":98},"tip","لا تنشر المنفذ 8000 على العنوان العام أبدًا","يخدم المنفذ نفسه اتصالات العملاء وواجهة الخادم ولوحة الإدارة. أبقه على `127.0.0.1` ومرّ دائمًا عبر الوكيل العكسي HTTPS. ولا تضع أبدًا `ENCRYPTION_KEY` أو `ENCRYPTION_KEY_HEX64` في شيفرة تُرسل إلى المتصفح: الأول يسمح بالنشر على أي قناة، والثاني بصنع رموز لأي مستخدم.",{"type":39,"title":100,"body":101},"وضع Centrifugo خلف nginx","يبدأ اتصال WebSocket بطلب HTTP يطلب تبديل البروتوكول. يجب أن يمرر nginx هذا الطلب، وألا يقطع اتصالًا يبقى صامتًا بضع دقائق. في كتلة `server` الخاصة بنطاقك الفرعي، مع شهادة Let's Encrypt:\n```nginx\nlocation \u002F {\n    proxy_pass http:\u002F\u002F127.0.0.1:8000;\n    proxy_http_version 1.1;\n    proxy_set_header Upgrade $http_upgrade;\n    proxy_set_header Connection \"upgrade\";\n    proxy_set_header Host $host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_read_timeout 3600s;\n}\n```\nبعد `nginx -t` وإعادة التحميل، يعرض `https:\u002F\u002Frt.example.com` شاشة الدخول إلى اللوحة.",{"type":39,"title":103,"body":104},"النشر من الخادم الخلفي","النشر هو إرسال كائن JSON إلى قناة. تصلح لذلك أي لغة قادرة على إرسال طلب HTTP:\n```bash\ncurl -X POST https:\u002F\u002Frt.example.com\u002Fapi\u002Fpublish \\\n  -H \"X-API-Key: $ENCRYPTION_KEY\" \\\n  -d '{\"channel\": \"commandes\", \"data\": {\"id\": 1042, \"statut\": \"payee\"}}'\n```\nيؤكد الرد `{\"result\":{}}` قبول الرسالة. دون الترويسة `X-API-Key`، أو بمفتاح خاطئ، يجيب Centrifugo بـ `401`.",{"type":39,"title":106,"body":107},"توقيع رموز الاتصال","لا يتصل المتصفح إلا برمز JWT يوقّعه خادمك الخلفي بـ `ENCRYPTION_KEY_HEX64`. تحمل المطالبة `sub` معرّف المستخدم، و`exp` تاريخ الانتهاء، و`channels` قائمة القنوات التي يُشترك فيها تلقائيًا. مثال بلغة Python:\n```python\nimport time, jwt  # pip install pyjwt\n\ndef centrifugo_token(user_id: str) -> str:\n    claims = {\"sub\": user_id, \"exp\": int(time.time()) + 3600, \"channels\": [\"commandes\"]}\n    return jwt.encode(claims, ENCRYPTION_KEY_HEX64, algorithm=\"HS256\")\n```\nضع هذه الدالة خلف مسار موثّق في تطبيقك: لا ينبغي أن يحصل على رمز إلا مستخدم مسجّل الدخول لديك.",{"type":39,"title":109,"body":110},"ما المسموح به للعميل","إعدادات هذا التثبيت مغلقة عن قصد. لا يستطيع المتصفح الاشتراك في قناة من تلقاء نفسه ولا النشر فيها: لا يتلقى إلا القنوات المذكورة في المطالبة `channels` داخل رمزه. يقرر خادمك الخلفي، عند كل إصدار للرمز، من يستمع إلى ماذا — لا يرى العميل إلا طلباته، ولا يرى موظف الدعم إلا طابور فريقه.\n\nفي الدردشة إذن، يمر النشر أيضًا عبر خادمك الخلفي: يرسل المتصفح الرسالة إلى تطبيقك، فيتحقق منها ويحفظها في قاعدة البيانات ثم ينشرها عبر الواجهة. يكلّف هذا الالتفاف بضع أجزاء من الثانية ويُبقي بيدك الإشراف والسجل.\n\nوأخيرًا، اجعل مدة صلاحية الرموز قصيرة، ساعة مثلًا. بدل تمرير رمز ثابت، دع الحزمة تطلب رمزًا جديدًا من تطبيقك عند انتهاء صلاحيته:\n```javascript\nconst client = new Centrifuge('wss:\u002F\u002Frt.example.com\u002Fconnection\u002Fwebsocket', {\n  getToken: async () => {\n    const res = await fetch('\u002Frealtime\u002Ftoken', { credentials: 'include' });\n    return (await res.json()).token;\n  },\n});\n```\nالمسار `\u002Frealtime\u002Ftoken` خاص بتطبيقك، ويتحقق من جلسة المستخدم قبل توقيع أي شيء.",{"type":39,"title":112,"body":113},"ربط متصفح","من جهة العميل، تفتح الحزمة الرسمية `centrifuge` ‏(npm) الاتصال وتسلّم الرسائل:\n```javascript\nimport { Centrifuge } from 'centrifuge';\n\nconst client = new Centrifuge('wss:\u002F\u002Frt.example.com\u002Fconnection\u002Fwebsocket', {\n  token: tokenFromYourBackend,\n});\nclient.on('publication', (ctx) => console.log(ctx.channel, ctx.data));\nclient.connect();\n```\nإذا فشل الاتصال، فابدأ بالسجلات (`docker compose logs centrifugo`). تعني الرسالة «request Origin is not authorized» أن أصل موقعك غائب عن `CENTRIFUGO_CLIENT_ALLOWED_ORIGINS`، وتشير «invalid token» إلى رمز موقّع بشكل خاطئ أو منتهي الصلاحية.",{"type":39,"title":115,"body":116},"لوحة الإدارة","افتح `https:\u002F\u002Frt.example.com` وأدخل `ADMIN_PASSWORD`: لا تطلب اللوحة اسم مستخدم. تعرض إصدار العقدة وعدد العملاء والمستخدمين المتصلين، وتتيح إرسال أوامر الواجهة — نشر رسالة تجريبية أو سرد القنوات النشطة — دون كتابة شيفرة. إنها أسرع وسيلة للتحقق من خروج الرسالة قبل البحث عن الخلل في المتصفح.",{"type":39,"title":118,"body":119},"التوسّع والتحديثات","يستخدم هذا الدليل محرك الذاكرة: عقدة واحدة دون أي اعتماد. يناسب معظم التطبيقات، ويتحمل خادم متواضع عددًا كبيرًا من الاتصالات المتزامنة، ولذلك رُفع حد الملفات المفتوحة في `docker-compose.yml`. وحين لا تكفي عقدة واحدة، يستطيع Centrifugo توزيع الحمل على عدة عقد مرتبطة عبر Redis. للتحديث، غيّر وسم الصورة بعد قراءة ملاحظات الإصدار، ثم شغّل `docker compose pull && docker compose up -d`؛ تعود الاتصالات تلقائيًا لأن حزم العملاء تعيد الاتصال من تلقاء نفسها.","خادم الزمن الحقيقي على خادمك","يكفي خادم ServOrbit بنظام Ubuntu 24.04 وذاكرة 1 غيغابايت لتشغيل Centrifugo. تثبيت بنقرة واحدة من المتجر، وHTTPS وWebSocket على نطاقك أو على النطاق الفرعي المجاني للخادم، مع توليد كلمة المرور والمفاتيح لك.","ثبّت Centrifugo","\u002Fapplications\u002Fالتطوير\u002Fcentrifugo",[125,150,174],{"id":126,"slug":127,"slugs":128,"title":132,"excerpt":133,"readTime":134,"views":135,"isPinned":19,"noindex":19,"publishedAt":136,"updatedAt":137,"category":138,"categories":144,"featuredImage":30,"bgImage":31,"posterImage":146,"relatedSolution":147},194,"استضافة-ntfy-على-vps-إشعارات-فورية-من-سكريبتاتك-وcicd",{"fr":129,"en":130,"ar":127,"es":131},"self-host-ntfy-vps","self-host-ntfy-on-a-vps-push-notifications-for-scripts-and-cicd","autoalojar-ntfy-en-un-vps","استضافة ntfy على VPS: إشعارات فورية من سكريبتاتك وCI\u002FCD","انشر ntfy على VPS الخاص بك وأرسل إشعارات push من أي سكريبت أو مهمة cron أو خط CI\u002FCD بأمر curl بسيط — بدون SaaS أو API key أو اشتراك.",16,2,"2026-07-28T00:00:00+00:00","2026-11-04T16:30:26+00:00",{"id":139,"name":140,"slug":141,"color":142,"icon":143},8,"الأمان والمراقبة","securite-monitoring","bg-rose-500\u002F10 text-rose-400","security",[145],{"id":139,"name":140,"slug":141,"color":142,"icon":143},"\u002Fblog\u002Fcovers\u002Fself-host-ntfy-vps-poster.svg",{"categorySlug":148,"appSlug":149},"المراقبة-وقابلية-الرصد","ntfy",{"id":151,"slug":152,"slugs":153,"title":157,"excerpt":158,"readTime":159,"views":18,"isPinned":19,"noindex":19,"publishedAt":160,"updatedAt":161,"category":162,"categories":168,"featuredImage":30,"bgImage":31,"posterImage":170,"relatedSolution":171},58,"استضافة-redis-على-خادم-vps",{"fr":154,"en":155,"ar":152,"es":156},"heberger-redis-vps","hosting-redis-on-a-vps","alojar-redis-en-un-vps","استضافة ‎Redis‎ على خادم ‎VPS‎: الدليل الشامل","انشر ‎Redis‎ على خادم ‎VPS‎ السحابي: متطلبات ‎RAM‎ و‎CPU‎، الأمان (‎ACL‎ و‎TLS‎)، استمرارية ‎RDB\u002FAOF‎، استكشاف الأخطاء والتوافر العالي.",10,"2026-04-23T00:00:00+00:00","2026-09-08T21:59:59+00:00",{"id":163,"name":164,"slug":165,"color":166,"icon":167},6,"قواعد البيانات","bases-de-donnees","bg-teal-500\u002F10 text-teal-400","database",[169],{"id":163,"name":164,"slug":165,"color":166,"icon":167},"\u002Fblog\u002Fcovers\u002Fheberger-redis-vps-poster.svg",{"categorySlug":172,"appSlug":173},"قواعد-البيانات","redis-stack",{"id":175,"slug":176,"slugs":177,"title":181,"excerpt":182,"readTime":183,"views":18,"isPinned":19,"noindex":19,"publishedAt":184,"updatedAt":185,"category":186,"categories":187,"featuredImage":30,"bgImage":31,"posterImage":189,"relatedSolution":190},60,"استضافة-supabase-على-خادم-vps",{"fr":178,"en":179,"ar":176,"es":180},"heberger-supabase-vps","hosting-supabase-on-a-vps","alojar-supabase-en-un-vps","استضافة Supabase على VPS في 2026","‏استضف Supabase ذاتيًا على VPS: Postgres والمصادقة والتخزين وREST API خلف Envoy. هجرة PG 15→17 وKong→Envoy وثغرة GoTrue.",15,"2026-04-21T00:00:00+00:00","2026-11-08T01:13:14+00:00",{"id":163,"name":164,"slug":165,"color":166,"icon":167},[188],{"id":163,"name":164,"slug":165,"color":166,"icon":167},"\u002Fblog\u002Fcovers\u002Fheberger-supabase-vps-poster.svg",{"categorySlug":172,"appSlug":191},"supabase",1794100721988]