[{"data":1,"prerenderedAt":258},["ShallowReactive",2],{"seo-verification":3,"blog-heberger-excalidraw-vps-2-ma-ar":6,"promo-bar-likely":249},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-heberger-excalidraw-vps-2-ma-ar",{"id":9,"slug":10,"slugs":11,"title":14,"excerpt":15,"readTime":16,"views":17,"isPinned":18,"noindex":18,"publishedAt":19,"updatedAt":20,"category":21,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":29,"intro":32,"sections":33,"ctaTitle":190,"ctaBody":191,"ctaButton":192,"ctaUrl":193,"relatedPosts":194},349,"heberger-excalidraw-vps-2",{"fr":12,"en":10,"ar":10,"es":13},"heberger-excalidraw-vps","alojar-excalidraw-en-un-vps-pizarra-colaborativa-sin-suscripcion","استضافة Excalidraw على VPS: لوح تعاوني مفتوح المصدر","انشر Excalidraw على VPS الخاص بك: لوح MIT، وقت فعلي على خادمك، وما يبقى لدى أطراف ثالثة (Firebase وروابط المشاركة).",15,10,false,"2026-09-11T00:00:00+00:00","2026-11-09T20:55:15+00:00",{"id":22,"name":23,"slug":24,"color":25,"icon":26},7,"الاستضافة الذاتية","self-hosting","bg-indigo-500\u002F10 text-indigo-400","cloud",[28],{"id":22,"name":23,"slug":24,"color":25,"icon":26},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fheberger-excalidraw-vps-poster.svg","Miro وFigJam وLucidspark: تفرض أدوات اللوح الأبيض SaaS رسوماً بالمقعد، وتخزّن نماذجك على خوادمها، وتحدّ من عدد الأعضاء وفق الخطة. Excalidraw هو البديل مفتوح المصدر (MIT): لوح تعاون في الوقت الفعلي يشبه الرسم اليدوي، مكوّن من عنصرين — واجهة React وخادم WebSocket — يمكن استضافتهما ذاتياً على VPS في حاويتَي Docker. يوضح هذا الدليل كيفية نشرهما وضبط nginx لـ WebSocket، ويقول بوضوح ما يبقى في تثبيت قياسي لدى خدمات طرف ثالث (Firebase وروابط المشاركة).",[34,38,48,51,54,62,81,84,91,131,134,137,146,150,184,187],{"type":35,"title":36,"body":37},"h2","لماذا تستضيف Excalidraw بنفسك بدلاً من النسخة العامة","تعمل النسخة العامة على ‎excalidraw.com بشكل جيد للرسم السريع الفردي. إلا أنها تُمرّر جلسات التعاون في الوقت الفعلي عبر خادم تديره شركة Excalidraw‏ s.r.o. قد يكون ذلك مقبولاً لجلسة عصف ذهني عابرة، لكنه أقل قبولاً حين تحتوي اللوحات على نماذج تدفق العملاء أو مخططات البنية الداخلية أو واجهات مشاريع مشمولة بالسرية.\n\nاستضافة Excalidraw ذاتياً تنقل حدود التحكم إلى بنيتك التحتية الخاصة. تمر حركة الوقت الفعلي عبر **خادمك** WebSocket على **نطاقك** الخاص؛ أما ما يبقى لدى طرف ثالث في تثبيت قياسي (المشهد المحفوظ وروابط المشاركة) فيُفصَّل أدناه. أنت من يقرر من يتصل — عبر قائمة IP المسموح بها أو SSO‏ OIDC أو HTTP Basic Auth أمام nginx. وبما أن المكوّنَين منشوران بموجب رخصة MIT، لا توجد قيود تجارية بصرف النظر عن عدد العملاء أو المتعاونين.",{"type":39,"title":40,"items":41},"ul","الفوائد الملموسة",[42,43,44,45,46,47],"**لا رسوم برمجية** — المكوّنان (الواجهة وخادم التعاون) برخصة MIT. تدفع مقابل VPS فقط.","**سرية النماذج** — يبقى الرسم المباشر على بنيتك التحتية. أما المشهد المحفوظ وصور الغرفة فيحتاجان إلى معالجة (Firebase افتراضياً): راجع «ما ينجح فعلاً في الاستضافة الذاتية».","**التحكم في الوصول** — قائمة IP أو SSO‏ OIDC أو HTTP Basic Auth أمام nginx حسب مستوى العزل المطلوب.","**جلسات وأعضاء غير محدودين** — لا سقف يفرضه الخطة؛ الحد الوحيد هو ذاكرة RAM للخادم، وخادم `excalidraw-room` خفيف الوزن.","**استمرارية اختيارية** — ربط وحدة تخزين Docker أو حاوية S3 متوافقة لأرشفة اللوحات المصدَّرة بصيغة JSON.","**التكامل مع مجموعة الأدوات المستضافة ذاتياً** — Excalidraw إلى جانب Penpot وMattermost وDocmost يُغلق محيط SaaS لوكالة بأكملها.",{"type":35,"title":49,"body":50},"البنية: حاويتان بأدوار مختلفة","يفصل Excalidraw ما يعتبره معظم الناس أداةً واحدةً إلى مكوّنَين مستقلَّين:\n\n- **`excalidraw\u002Fexcalidraw`** — الواجهة المُجمَّعة بـ React، تُقدَّم كموقع ثابت عبر nginx داخل الحاوية. لا تشغّل خادماً تطبيقياً. عناوين خدماتها (الغرفة وFirebase والمشاركة) متغيرات `VITE_APP_*` تُقرأ **وقت البناء** وتُدمج في حزمة JavaScript: تغييرها على حاوية قيد التشغيل لا يُحدث أي أثر.\n\n- **`excalidraw\u002Fexcalidraw-room`** — خادم ‎Node.js‏\u002FSocket.IO يُعيد توجيه أحداث الرسم في الذاكرة بين المشاركين في الجلسة ذاتها. إنه **عديم الحالة**: لا يُخزّن شيئاً وينسى كل شيء عند إعادة التشغيل. المشهد المحفوظ للغرفة لا يمر عبره (انظر أدناه). لم تُنشر صورته على Docker Hub من جديد منذ ديسمبر 2023، ويبدأ Dockerfile الأصلي من Node 12: أبقه خلف nginx على شبكة Docker دون منفذ منشور.\n\nالنتيجة العملية: بُنيت صورة Docker الرسمية بعناوين ‎excalidraw.com. لتوجيهها إلى `excalidraw-room` الخاص بك، عليك **بناء صورتك الخاصة** بعد تعديل `VITE_APP_WS_SERVER_URL` في ‎`‎.env.production`.",{"type":35,"title":52,"body":53},"المتطلبات الأساسية","يغطي VPS Solo من ServOrbit (2 نواة، 4 GB RAM) الحالة العادية: الواجهة الثابتة شبه خالية من الحمل، ويستهلك `excalidraw-room` أقل من 256 ميغابايت في الظروف العادية. مع عشرة متعاونين متزامنين ستبقى بعيداً عن نصف الذاكرة المتاحة.\n\n**ما تحتاجه قبل البدء:**",{"type":39,"title":55,"items":56},"قائمة التحقق من المتطلبات",[57,58,59,60,61],"خادم VPS بما لا يقل عن 1 نواة و512 ميغابايت RAM (يُوصى بـ 1 غيغابايت للفريق).","Docker Engine وإضافة Docker Compose مثبَّتان (للتحقق: `docker compose version`).","اسم نطاق مُوجَّه نحو IP الخادم — بدون TLS تُحجب WebSockets في المتصفحات الحديثة.","وصول SSH بصلاحيات root أو مستخدم بصلاحيات `sudo`.","شهادة TLS صالحة — يهيئ ServOrbit Let's Encrypt تلقائياً.",{"type":63,"title":64,"steps":65},"steps","نشر Excalidraw في 5 خطوات",[66,69,72,75,78],{"title":67,"body":68},"إنشاء VPS وتثبيت Docker","شغّل VPS Ubuntu 24.04 من لوحة تحكم ServOrbit. بعد الاتصال عبر SSH، إن لم يكن Docker مثبتاً بعد، شغّل:\n\n```bash\ncurl -fsSL https:\u002F\u002Fget.docker.com | sh\n```\n\nتحقق من استجابة Docker Compose Plugin قبل المتابعة:\n\n```bash\ndocker compose version\n```",{"title":70,"body":71},"بناء الصورة مع رابط التعاون الخاص بك","انسخ المستودع الرسمي ثم اضبط عنوان الغرفة **في ملف ‎`‎.env.production` من المستودع** قبل البناء. استبدل ‎`collab.yourdomain.com` بالنطاق الفرعي الذي تخصصه لـ `excalidraw-room`:\n\n‎`git clone https:\u002F\u002Fgithub.com\u002Fexcalidraw\u002Fexcalidraw.git`\n`cd excalidraw`\n‎`sed -i 's|^VITE_APP_WS_SERVER_URL=.*|VITE_APP_WS_SERVER_URL=https:\u002F\u002Fcollab.yourdomain.com|' .env.production`\n‎`docker build -t my-excalidraw:latest .`\n\nلماذا لا نستعمل `--build-arg`؟ لأن Dockerfile الأصلي لا يعلن أي `ARG` لمتغيرات `VITE_APP_*`: فالأمر `--build-arg VITE_APP_WS_SERVER_URL=…` لا يصل أبداً إلى أمر البناء، وتُبنى الصورة بشكل طبيعي وتظل موجّهة إلى خادم Excalidraw. كما أن ‎`‎.dockerignore` الأصلي لا يقبل إلا ‎`‎.env.development` و‎`‎.env.production`، فيُتجاهل ‎`‎.env.production.local`. العنوان مدمج في الحزمة، لذا يستلزم تغيير النطاق إعادة البناء.\n\nتحقق من النتيجة: يجب أن يطبع الأمر ‎`‎docker run --rm --entrypoint sh my-excalidraw:latest -c \"grep -rl oss-collab.excalidraw.com \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml || echo clean\"` الكلمة `clean`. صورة `excalidraw\u002Fexcalidraw` الرسمية مناسبة للتجارب المحلية، لكنها تستهدف خدمات Excalidraw العامة.",{"title":73,"body":74},"كتابة ملف docker-compose.yml","أنشئ مجلد عمل وضع الملف التالي. تستمع الخدمتان داخلياً؛ nginx (الخطوة التالية) هو نقطة الدخول العامة الوحيدة:\n\n```bash\nmkdir ~\u002Fexcalidraw-stack && cd ~\u002Fexcalidraw-stack\n```\n\nمحتوى `docker-compose.yml`:\n\n```bash\nservices:\n  excalidraw:\n    image: my-excalidraw:latest\n    restart: unless-stopped\n    networks:\n      - excalidraw\n\n  excalidraw-room:\n    image: excalidraw\u002Fexcalidraw-room:latest\n    environment:\n      - CORS_ORIGIN=https:\u002F\u002Fdraw.yourdomain.com\n    restart: unless-stopped\n    networks:\n      - excalidraw\n\nnetworks:\n  excalidraw:\n```\n\nشغّل المجموعة:\n\n```bash\ndocker compose up -d\n```",{"title":76,"body":77},"إعداد nginx مع ترويسات WebSocket","هذه الخطوة هي المكان الذي تفشل فيه معظم عمليات النشر بصمت: بدون ترويستَي `Upgrade` و`Connection`، يفتح المتصفح اتصالاً HTTP عادياً بدلاً من WebSocket، وتبدو ميزة التعاون كأنها لا تعمل دون أي رسالة خطأ.\n\nكتلة nginx للواجهة الأمامية لـ ‎Excalidraw (`draw.yourdomain.com`):\n\n```bash\nserver {\n    listen 443 ssl;\n    server_name draw.yourdomain.com;\n\n    location \u002F {\n        proxy_pass http:\u002F\u002Fexcalidraw:80;\n        proxy_set_header Host $host;\n    }\n}\n```\n\nكتلة nginx لخادم الغرفة (`collab.yourdomain.com`):\n\n```bash\nserver {\n    listen 443 ssl;\n    server_name collab.yourdomain.com;\n\n    location \u002F {\n        proxy_pass http:\u002F\u002Fexcalidraw-room:80;\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_read_timeout 86400s;\n    }\n}\n```\n\nأعِد تحميل nginx (`nginx -s reload`) بعد وضع الكتل.",{"title":79,"body":80},"اختبار التعاون في الوقت الفعلي","افتح `https:\u002F\u002Fdraw.yourdomain.com` في علامتَي تبويب أو متصفحَين مختلفَين. انقر على **Live collaboration** في شريط الأدوات وأنشئ جلسة. انسخ رابط الجلسة في علامة التبويب الثانية.\n\nارسم شيئاً في علامة التبويب الأولى: يجب أن تظهر اللمسة في الثانية فوراً. إن لم تظهر، تحقق أولاً من ترويسات WebSocket في nginx (تُظهر أدوات الشبكة في المتصفح إن كان الاتصال قد ارتقى إلى `101 Switching Protocols`).\n\nافتح بعد ذلك تبويب الشبكة في المتصفح: يجب أن يستهدف اتصال الوقت الفعلي ‎`collab.yourdomain.com` لا ‎oss-collab.excalidraw.com أبداً. أما ما يستقبله Firebase فتعالجه الفقرة التالية.",{"type":35,"title":82,"body":83},"ما ينجح فعلاً في الاستضافة الذاتية","لنكن دقيقين: «حاويتان وانتهى الأمر» هو الاختصار الذي تكرره هذه الأدلة أكثر من غيره. يلخص الخيط الجامع في المستودع الأصلي (excalidraw\u002Fexcalidraw، المسألة رقم 1772، مفتوحة منذ يونيو 2020 وما زالت نشطة في أكتوبر 2026) ثلاثة جدران، قابلناها بالشيفرة وبملفات ‎`‎.env` في المستودع.\n\n**الجدار الأول — العناوين مثبتة وقت البناء.** عناوين خادم التعاون وخدمة المشاركة ومشروع Firebase هي متغيرات `VITE_APP_*` يقرؤها Vite أثناء البناء. بُنيت صورة `excalidraw\u002Fexcalidraw` الرسمية بقيم ‎`‎.env.production`: لذا ما زالت تتحدث إلى خدمات ‎excalidraw.com. متغير يُمرَّر إلى `docker run` لا يغيّر شيئاً، ولا يعلن Dockerfile الأصلي أي `ARG` لنقل متغير إلى البناء.\n\n**الجدار الثاني — التعاون محلي بالنصف.** الوقت الفعلي (من يرسم ماذا مباشرةً) يمر عبر `excalidraw-room` الذي تستضيفه. لكن المشهد المحفوظ والصور الملصقة في غرفة تذهب إلى Firebase: تستدعي الشيفرة `saveToFirebase` و`saveFilesToFirebase` بإعدادات `VITE_APP_FIREBASE_CONFIG`. ما دام هذا المتغير يحتفظ بالقيمة الأصلية، تُخزَّن هذه البيانات (المشفّرة في المتصفح بمفتاح الغرفة) في مشروع Firebase التابع لـ Excalidraw لا عندك. وهذا يوفّق بين الشهادات المتناقضة في الخيط: أحدهم يلاحظ أن التعاون يفشل مع `VITE_APP_FIREBASE_CONFIG='{}'`، وآخر أن Jitsi Meet أزال جزء Firebase وأن الوقت الفعلي يعمل بالغرفة وحدها. الرسم المباشر يستغني عن Firebase؛ أما الحفظ والاستئناف فلا.\n\n**الجدار الثالث — روابط المشاركة تتطلب خادم تخزين لا ينشره المشروع.** يُنشأ رابط `#json=` بطلب إلى `VITE_APP_BACKEND_V2_POST_URL` ويُقرأ عبر `VITE_APP_BACKEND_V2_GET_URL`، والافتراضي ‎json.excalidraw.com. يذكر الخيط إعادات كتابة من المجتمع (إحداها بـ ‎Next.js على S3 وأخرى على تخزين متوافق مع S3) لكنه لا يعتبر أياً منها رسمية.",{"type":39,"title":85,"items":86},"ثلاثة تركيبات ممكنة، وما يتركه كل منها لدى طرف ثالث",[87,88,89,90],"**التركيب أ — الغرفة وحدها (تركيب هذا الدليل).** تغيّر `VITE_APP_WS_SERVER_URL` ولا شيء غيره. يمر الرسم المباشر عبر خادمك؛ أما المشهد المحفوظ وصور الغرف فتبقى مكتوبة في Firebase التابع لـ Excalidraw. مقبول للوحات قليلة الحساسية، ولا يجوز تقديمه على أنه «لا شيء لدى طرف ثالث».","**التركيب ب — الغرفة مع مشروع Firebase خاص بك.** تنشئ مشروع Firebase خاصاً بك وتضع إعداداته بصيغة JSON في `VITE_APP_FIREBASE_CONFIG`. تقرأ الشيفرة هذا المتغير وحده؛ لم ننشره من البداية إلى النهاية، ويبقى Firebase خدمة من Google لا استضافة ذاتية بالمعنى الصارم.","**التركيب ج — نسخة فردية.** تقدّم الواجهة وحدها دون غرفة ودون رابط: يرسم كل شخص ويصدّر إلى ‎`‎.excalidraw` أو إلى صورة ويؤرشف الملفات عندك. لا شيء يذهب إلى طرف ثالث بسبب التعاون، لأنه غير موجود.","**ما لا يوجد في الجانب الرسمي.** لا خادم تخزين مفتوح لروابط `#json=`، ولا خيار ينقل المحيط كله إلى نطاقك بمتغير واحد وقت التشغيل. إن كان شرطك «لا بيانات لدى طرف ثالث» مع التعاون والمشاركة، فالجواب الصادق هو عمل تكييف أو تفريع (fork) لا مجرد تثبيت.",{"type":92,"title":93,"headers":94,"rows":98},"comparison","المتغير ← الوظيفة ← ما ينكسر بدونه",[95,96,97],"المتغير","الوظيفة","ما ينكسر بدونه",[99,103,107,111,115,119,123,127],[100,101,102],"`VITE_APP_WS_SERVER_URL` (وقت البناء)","عنوان خادم الوقت الفعلي ‎Socket.IO (`excalidraw-room`).","القيمة الأصلية باقية: تمر جلساتك عبر ‎oss-collab.excalidraw.com. عنوان لا يمكن الوصول إليه: لا يبدأ التعاون.",[104,105,106],"`VITE_APP_FIREBASE_CONFIG` (وقت البناء)","إعداد JSON لمشروع Firebase: المشهد المحفوظ للغرفة والصور الملصقة.","القيمة الأصلية: تبقى تلك البيانات لدى Excalidraw. فارغ أو غير صالح (ومنه `{}`): يفشل حفظ الغرفة واستئنافها، ووفق شهادة في الخيط يفشل التعاون أيضاً. وJSON غير مقروء يسجّل `Error JSON parsing firebase config`.",[108,109,110],"`VITE_APP_BACKEND_V2_POST_URL` (وقت البناء)","إنشاء رابط مشاركة `#json=` (رفع المشهد المشفّر).","القيمة الأصلية: يُنشأ الرابط لدى ‎json.excalidraw.com. عنوان بلا خادم متوافق: يفشل إنشاء الرابط.",[112,113,114],"`VITE_APP_BACKEND_V2_GET_URL` (وقت البناء)","إعادة قراءة رابط `#json=` عند فتحه.","القيمة الأصلية: يُقرأ الرابط من Excalidraw. عنوان بلا خادم متوافق: يفشل فتح الرابط.",[116,117,118],"`VITE_APP_DISABLE_SENTRY` (وقت البناء)","يعطّل إرسال تقارير الأخطاء إلى Sentry.","لا ينكسر شيء؛ وبدونه قد يرسل التطبيق تقارير أخطاء إلى طرف ثالث. السكربت الأصلي `build:app:docker` يضبطه أصلاً على `true`.",[120,121,122],"`VITE_APP_DISABLE_PREVENT_UNLOAD` (وقت البناء)","يلغي التنبيه قبل مغادرة غرفة لم ينتهِ حفظها.","لا ينكسر شيء، لكن إغلاق التبويب لم يعد يحذّر. يُحتفظ به للتنقيح فقط.",[124,125,126],"`CORS_ORIGIN` (وقت التشغيل، `excalidraw-room`)","المصدر المسموح له بفتح اتصال بخادم الغرفة.","غائب: القيمة الافتراضية `*` وأي صفحة ويب تستطيع الاتصال. اضبط ‎`https:\u002F\u002Fdraw.yourdomain.com`.",[128,129,130],"`PORT` (وقت التشغيل، `excalidraw-room`)","منفذ استماع خادم الغرفة.","غائب: يستمع على المنفذ 80 خارج وضع التطوير، وهو ما تفترضه كتل nginx في هذا الدليل. إن غيّرته فيجب أن يتبعه `proxy_pass`.",{"type":35,"title":132,"body":133},"التحقق ممّن يستقبل ماذا","الطريقة الوحيدة لمعرفة ما يخرج من نسختك هي النظر. افتح تبويب الشبكة في المتصفح، وابدأ جلسة تعاون، وارسم، والصق صورة، ثم أنشئ رابط مشاركة. تُقرأ ثلاث فئات من الوجهات: نطاقك الفرعي للغرفة (الوقت الفعلي، متوقع)؛ ونطاقات ‎`‎googleapis.com` التابعة لـ Firebase (المشهد والصور المحفوظة، متوقعة مع الإعداد الأصلي، وتُزال إن كنت تظن العكس)؛ و‎json.excalidraw.com (المشاركة بالرابط). هذا الفحص هو اختبار قبول التركيب الذي اخترته: بدونه تبقى عبارة «على خادمي» مجرد فرضية.\n\nوتذكّر أخيراً أن خادم الغرفة لا يوثّق أحداً: `CORS_ORIGIN` يحدّ من صفحات الويب المسموح لها بالاتصال لا من الأشخاص. وتُضبط هوية المشاركين أمام الواجهة (Basic Auth أو SSO) كما يرد أدناه.",{"type":35,"title":135,"body":136},"استكشاف الأخطاء: التعاون لا يبدأ، أو لا يتذكر شيئاً","تنتج الأعراض التالية عن الشيفرة وعن الخيط الأصلي؛ ولا تُنقل أي رسالة سوى ما قُرئ في المستودع.",{"type":39,"title":138,"items":139},"الأعراض والأسباب والحلول",[140,141,142,143,144,145],"**تذهب الجلسة إلى ‎oss-collab.excalidraw.com (تبويب الشبكة) رغم أنك بنيت صورتك.** السبب: لم يُؤخذ العنوان في الحسبان وقت البناء (`--build-arg` بلا أثر، و‎`‎.env.production.local` يتجاهله ‎`‎.dockerignore`). الحل: عدّل ‎`‎.env.production` وأعد البناء وأعد فحص `grep` من الخطوة 2. وتغيير النطاق يخضع للقاعدة نفسها.","**يُرفض اتصال المتصفح بالغرفة.** سبب متكرر بعد ضبط `CORS_ORIGIN`: المصدر لا يطابق تماماً مصدر الصفحة (مخطط `http` بدل `https`، أو المنفذ، أو شرطة مائلة أخيرة). الحل: يجب أن تكون القيمة هي المصدر الدقيق للواجهة، مثل ‎`https:\u002F\u002Fdraw.yourdomain.com`.","**تظهر الخطوط مباشرةً، لكن مشاركاً ينضم لاحقاً أو بعد إعادة تشغيل الغرفة لا يجد المحتوى أو الصور.** السبب: يُحفظ المشهد والصور عبر Firebase لا عبر `excalidraw-room` الذي لا يحتفظ بشيء. إن كان `VITE_APP_FIREBASE_CONFIG` فارغاً أو لا يمكن الوصول إليه فلا يُقرأ شيء. الحل: اختر التركيب أ أو ب أعلاه.","**تحذير ‎`Error JSON parsing firebase config. Supplied value:` في وحدة تحكم المتصفح.** السبب: `VITE_APP_FIREBASE_CONFIG` ليس JSON صالحاً، وغالباً بسبب علامات اقتباس غير محمية جيداً أو سطر جديد في الملف. الحل: JSON في سطر واحد بين علامتي اقتباس مفردتين في ‎`‎.env.production` كما في الملف الأصلي.","**تفشل المشاركة بالرابط، أو يشير الرابط الناتج إلى ‎json.excalidraw.com.** السبب: لم يُغيَّر `VITE_APP_BACKEND_V2_POST_URL` و`VITE_APP_BACKEND_V2_GET_URL`، أو يشيران إلى خادم لا ينفّذ الواجهة المتوقعة. الحل: الإبقاء على الافتراضي عن علم، أو تبادل ملفات ‎`‎.excalidraw`.","**خطأ تشفير أو توليد مفتاح على شبكة محلية عبر `http:\u002F\u002F`.** السبب: واجهة التشفير في المتصفح (‎`window.crypto`) لا تُتاح إلا في سياق آمن؛ وينبّه الخيط الأصلي إلى هذا الفخ في الاستضافة الذاتية على شبكة محلية. الحل: تقديم الواجهة عبر HTTPS (أو على `localhost`) كما يشترط متطلب TLS أعلاه.",{"type":147,"title":148,"body":149},"tip","استمرارية اللوحات: ما يُحفظ فعلاً","بشكل افتراضي، يكون `excalidraw-room` عديم الحالة تماماً: إن أُعيد تشغيل الخادم يبدأ الترحيل من الصفر. المشهد المحفوظ للغرفة يعيش في مكان آخر (Firebase، انظر أعلاه)، ويحتفظ كل مشارك أيضاً برسمه في `localStorage` المتصفح.\n\n**الخيار الأول — تصدير يدوي لملفات ‎`‎.excalidraw`.** تُنتج قائمة التصدير في الواجهة ملف ‎`‎.excalidraw` (أو صورة) يمكن إعادة استيراده في أي وقت. لا يوفر Excalidraw واجهة تصدير تُستدعى من cron: إنها خطوة تتم في المتصفح، ثم تضع الملف في وحدة تخزين أو مستودع git.\n\n**الخيار الثاني — حاوية S3 متوافقة للأرشفة.** يوفر ServOrbit تخزين كائنات متوافق مع S3. انسخ إليه الملفات المصدَّرة بالأداة التي تفضلها (`rclone` أو `aws s3 cp`)؛ والاستعادة تتم بإعادة استيراد آخر ملف. Excalidraw نفسه لا يكتب في S3.",{"type":92,"title":151,"headers":152,"rows":157},"Excalidraw المستضاف ذاتياً مقابل بدائل SaaS",[153,154,155,156],"المعيار","Excalidraw (ذاتي)","Miro","FigJam",[158,162,167,171,175,179],[159,160,161,161],"التكلفة لكل مستخدم","لا شيء (VPS فقط)","مدفوع بالمقعد",[163,164,165,166],"استضافة البيانات","بنيتك التحتية (الوقت الفعلي)؛ وFirebase الخاص بـ Excalidraw افتراضياً للمشهد المحفوظ","‎Miro Inc.‎","‎Adobe \u002F Figma‎",[168,169,170,170],"الأعضاء المتزامنون","غير محدود (RAM فقط)","محدود بالخطة",[172,173,174,174],"رخصة البرنامج","MIT (مفتوح المصدر)","خاصة",[176,177,178,178],"قابل للاستضافة الذاتية","جزئياً: حاويتان، مع Firebase وروابط المشاركة التي تحتاج معالجة","لا",[180,181,182,183],"التحكم في الوصول","IP \u002F SSO \u002F Basic Auth","SSO (خطط Pro)","SSO (خطط Edu+)",{"type":35,"title":185,"body":186},"للمزيد: SSO وقوائم IP المسموح بها","بالنسبة للوكالات ذات متطلبات سرية صارمة، قد لا يكون نشر Excalidraw على نطاق فرعي عام مقبولاً دائماً. ثمة إعدادان شائعان يُحكمان الوصول دون تعديل Excalidraw نفسه.\n\n**HTTP Basic Auth عبر nginx.** أضف توجيه `auth_basic` أمام كتلة `location \u002F` للواجهة الأمامية. يجب على أي شخص يحاول فتح الواجهة المصادقة قبل تحميل تطبيق React. سهل التطبيق وكافٍ للمشاريع الداخلية.\n\n**قائمة IP المسموح بها.** إن اتصل المتعاونون من عناوين IP ثابتة أو شبكة VPN مؤسسية، تكفي كتلة `allow`\u002F`deny` في nginx لإغلاق الوصول:\n\n```bash\nallow 203.0.113.0\u002F24;\nallow 198.51.100.42;\ndeny all;\n```\n\n**SSO‏ OIDC عبر وكيل عكسي للمصادقة.** للفرق التي تمتلك بالفعل مزود هوية (Keycloak أو Authelia أو Authentik)، يُفوَّض التحقق من الهوية إلى SSO الحالي عبر وكيل كـ Oauth2-Proxy أو Authelia أمام nginx. لا يحتاج Excalidraw إلى معرفة وجود طبقة المصادقة الإضافية.",{"type":35,"title":188,"body":189},"التكامل مع مجموعة الأدوات المستضافة ذاتياً","يتكامل Excalidraw بشكل طبيعي مع مجموعة الأدوات المستضافة ذاتياً. إن نشرت Mattermost للتواصل الجماعي، يمكنك لصق رابط جلسة Excalidraw في قناة ودعوة المتعاونين للانضمام إلى اللوحة مباشرةً. وإن كان Penpot يغطي التصميم عالي الدقة، يتولى Excalidraw العمل الأولي — الواجهات السريعة ومخططات التدفق وجلسات العصف الذهني — قبل انتقال التصاميم إلى Penpot.\n\nهذا التكامل هو الحجة الحقيقية في مواجهة SaaS: تبقى كل أداة في نطاق كفاءتها دون اشتراك منصة يفوتر عن ميزات لا تحتاجها.","منصة واحدة لـ VPS والنطاق والنسخ الاحتياطية","يجمع ServOrbit.com VPS والنطاق والنسخ الاحتياطية على حسابك: انشر Excalidraw لفريقك من فضاء العميل.","اكتشف عرض الوكالات","\u002Fsolutions\u002Fagences",[195,220,239],{"id":196,"slug":197,"slugs":198,"title":202,"excerpt":203,"readTime":204,"views":205,"isPinned":18,"noindex":18,"publishedAt":206,"updatedAt":207,"category":208,"categories":214,"featuredImage":29,"bgImage":30,"posterImage":216,"relatedSolution":217},193,"استضافة-penpot-على-vps-بديل-figma-مفتوح-المصدر",{"fr":199,"en":200,"ar":197,"es":201},"self-host-penpot-vps","self-host-penpot-open-source-figma-alternative-on-your-vps","alojar-penpot-en-un-vps","استضافة Penpot على VPS: بديل Figma مفتوح المصدر","انشر Penpot على خادم ServOrbit الافتراضي واحصل على أداة تصميم تعاونية كاملة — تصميم متجهي، مكونات، تسليم للمطورين — دون اشتراك Figma أو بيانات تصميمك لدى طرف ثالث.",12,1,"2026-07-27T00:00:00+00:00","2026-11-04T16:30:26+00:00",{"id":209,"name":210,"slug":211,"color":212,"icon":213},4,"التطوير","developpement","bg-warning\u002F10 text-warning","dev",[215],{"id":209,"name":210,"slug":211,"color":212,"icon":213},"\u002Fblog\u002Fcovers\u002Fself-host-penpot-vps-poster.svg",{"categorySlug":218,"appSlug":219},"التعاون-والإنتاجية","penpot",{"id":221,"slug":222,"slugs":223,"title":227,"excerpt":228,"readTime":229,"views":230,"isPinned":18,"noindex":18,"publishedAt":231,"updatedAt":232,"category":233,"categories":234,"featuredImage":29,"bgImage":30,"posterImage":236,"relatedSolution":237},76,"استضافة-mattermost-على-خادم-vps-الخاص-بك",{"fr":224,"en":225,"ar":222,"es":226},"heberger-mattermost","host-mattermost-on-your-own-vps","alojar-mattermost-en-un-vps","استضافة ‎Mattermost‎ على خادم ‎VPS‎ الخاص بك","دليل كامل 2026: نشر ‎Mattermost v10\u002Fv11‎ على ‎VPS‎ مع ‎Docker‎ و‎PostgreSQL‎ و‎SSL‎ والتكاملات والنسخ الاحتياطية. بديل ذاتي الاستضافة عن ‎Slack‎.",9,5,"2026-04-05T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":22,"name":23,"slug":24,"color":25,"icon":26},[235],{"id":22,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fheberger-mattermost-poster.svg",{"categorySlug":24,"appSlug":238},"mattermost",{"id":240,"slug":241,"slugs":242,"title":246,"excerpt":247,"readTime":248,"views":209,"isPinned":18,"noindex":249,"publishedAt":250,"updatedAt":251,"category":252,"categories":253,"featuredImage":29,"bgImage":30,"posterImage":255,"relatedSolution":256},302,"planka-نشر-لوحة-kanban-مفتوحة-المصدر-على-vps",{"fr":243,"en":244,"ar":241,"es":245},"self-host-planka-vps","planka-self-host-an-open-source-kanban-board-on-your-vps","planka-tablero-kanban-open-source-autoalojado-en-vps","Planka: نشر لوحة Kanban مفتوحة المصدر على VPS","Planka: لوحة Kanban ذاتية الاستضافة لفرق التطوير. بديل مفتوح المصدر لـ Trello (AGPL) — انشر على VPS في دقائق.",3,true,"2026-01-13T00:00:00+00:00","2026-11-04T16:30:27+00:00",{"id":22,"name":23,"slug":24,"color":25,"icon":26},[254],{"id":22,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fself-host-planka-vps-poster.svg",{"categorySlug":218,"appSlug":257},"planka",1794270339459]