كيف تستضيف زملاء OpenBot بالذكاء الاصطناعي على VPS
شغّل OpenBot ذاتياً مع حاوية ومتصفح لكل زميل. تعرّف إلى دور البوابة في اعتماد كل إجراء، ولماذا قد يستهلك Chromium معظم ذاكرة VPS.
ما تحصل عليه عند الاستضافة الذاتية لزملاء OpenBot بالذكاء الاصطناعي
تستضيف زملاء OpenBot بالذكاء الاصطناعي ذاتياً عبر تشغيل خادم بوابة واحد وحاوية واحدة لكل bot على عتاد تتحكم فيه. تحتوي كل حاوية bot على متصفح Chromium ومساحة عمل volume خاصة بها، مع ملف تعريف للمتصفح يستمر بين الجلسات. يمر كل إجراء ينفذه bot على جهاز كمبيوتر أو ملف أو خادم MCP (model context protocol) أو مكوّن في واجهة المستخدم عبر تلك البوابة. تتحقق البوابة من الإجراء مقابل سياسة قبل تنفيذه، وتسجله بعد ذلك.
تنشر CopilotKit برنامج OpenBot بموجب ترخيص MIT على github.com/CopilotKit/openbot. نُشر أول إصدار موسوم، v0.0.1، في 17 August 2026، ويصف المشروع نفسه بأنه إصدار alpha وقيد التطوير النشط. تعامل معه كتصميم جاد ذي جوانب مبكرة لم تكتمل بعد.
الجزء المثير للاهتمام في هذه البنية هو أيضاً الجزء الأعلى تكلفة. يستهلك تشغيل متصفح لكل agent معظم الذاكرة التي ينسى كثيرون التخطيط لها، لذلك يسبق تحديد الحجم عملية التثبيت هنا.
كيف تحدد البوابة كل إجراء
خادم API على المنفذ 3001 هو المسار الوحيد إلى حاسوب bot. قبل تنفيذ أي إجراء في المتصفح، تحلّ البوابة الهدف من لقطة الصفحة، وتقيّم قواعد سياسة CEL (لغة التعبيرات الشائعة) وفق السياق، وتكتب صفاً في سجل التدقيق يتضمن القرار، ثم تستدعي الحاوية فقط بعد ذلك. إذا فشل التنفيذ بعد هذه الخطوة، تكتب صفاً ثانياً. توضّح الوثائق الحد الفاصل بعبارة صريحة: لا يحدد الحاسوب السياسة، بل تُعد بوابة الخادم حدّ تنفيذ الإجراء.
تعمل السياسة وفق مبدأ الرفض الافتراضي، وتُقيّم قواعد الرفض قبل قواعد السماح. ويهم اتجاه الفشل أكثر من صياغة القاعدة. لا تسمح السياسة المفقودة بأي شيء، وتؤدي القاعدة المعطلة إلى الحظر سواء كانت قاعدة رفض أم قاعدة سماح. لذلك، يتسبب الخطأ في سياستك في توقف bot بدلاً من تركه يتصرف دون قيود في حساباتك.
يوجد مسار التدقيق في PostgreSQL، لذلك يبقى بعد إعادة التشغيل. تُسجَّل عمليات تسليم التحكم بوصفها computer.help_requested وcomputer.control_taken وcomputer.control_released. يتيح لك ذلك رؤية طلب bot تدخّل بشري، ورؤية إعادة الإنسان التحكم. تُسجَّل الأسرار على شكل عدد الأحرف، وليس قيمها. وتسجّل عمليات الملفات المسار والحجم، وليس المحتوى. إذا أردت حد التحكم نفسه من دون متصفح خلفه، يشرح وضع إجراءات وكيل الذكاء الاصطناعي خلف الموافقات هذه الحالة الأضيق.
ما تكلفة Bot واحد من حيث الذاكرة والقرص
ينشر المشروع أرقاماً مقاسة لـBot واحد على arm64. وهذه هي أرقام التحجيم الوحيدة التي يوفرها OpenBot، وهي تصف Bot واحداً على بنية واحدة؛ لذلك استخدمها كنقطة بداية، لا كخطة سعة.
The data behind this chart
[
{
"label": "Measured, one Bot",
"memory_gb": 0.55,
"disk_gb": 5.3,
"vcpu": 0.06
},
{
"label": "Documented minimum",
"memory_gb": 2,
"disk_gb": 8,
"vcpu": 1
},
{
"label": "Documented recommended",
"memory_gb": 4,
"disk_gb": 10,
"vcpu": 2
}
]بلغت ذروة الذاكرة المقاسة 0.55 GB لـBot واحد، بينما الحد الأدنى الموثق هو 2 GB، والتوصية هي 4 GB. ويشير الفرق بين القياس والحد الأدنى إلى مساحة يمكن أن ينمو فيها Chromium تحت الحمل، لأن استخدام المتصفح للذاكرة يرتبط بالصفحات المفتوحة فيه، لا بالعملية وهي في حالة الخمول. يقترب استخدام CPU في حالة الخمول من الصفر، إذ يبلغ 0.06 من نواة واحدة عند الحد الأعلى للنطاق المقاس، لذلك لا يمثل CPU المورد الأساسي الذي تشتريه. القرص هو المورد الأساسي. يبلغ حجم الصورة وحدها 5.3 GB، مقارنةً بـvolume موصى به حجمه 10 GB. ويرجع هذا الحجم إلى أن الصورة تتضمن ملفات Chromium الثنائية الخاصة بـPlaywright لكل من Firefox وWebKit.
لا توضح هذه الأرقام تكلفة تشغيل عدة Bots معاً، ولا ينشر المشروع رقماً لذلك. قِس التكلفة في بيئتك. شغّل Bot واحداً، وأسند إليه مهمة فعلية مع فتح صفحة، وراقب الحاوية أثناء عملها.
docker stats --no-stream
free -mاستخدم عمود MEM USAGE لحاوية Bot باعتباره قيمة Bot الواحد، ثم أضف gateway وPostgreSQL، وبعد ذلك اضرب قيمة Bot الواحد في عدد Bots التي تتوقع وجودها في الوقت نفسه. يحتفظ Bot الخامل بعملية متصفح، لذلك ينطبق معامل الضرب على Bots الموجودة، وليس على Bots المشغولة فقط. وتستخدم هذه العملية الحسابية نفسها لتحجيم RAM وCPU لخادم VPS يشغّل coding agent، بينما يوضّح تشغيل متصفح headless للوكلاء على خادم VPS جانب المتصفح منها.
تؤثر إحدى تفاصيل Chromium في الخطط الصغيرة. يشغّل OpenBot Chromium باستخدام --disable-dev-shm-usage، لذلك يكتب المتصفح إلى /tmp بدلاً من /dev/shm. يؤدي ذلك إلى تجنب الانهيار الذي يحدث على المضيفين ذوي /dev/shm الصغير، لكنه ينقل الضغط إلى نظام الملفات الجذر، وهذا سبب إضافي يجعل القرص الموصى به أكبر من حجم الصورة.
كيف تستضيف OpenBot ذاتياً على VPS؟
تحتاج إلى Docker وBun 1.3 أو إصدار أحدث، ومشروع CopilotKit Intelligence، ومفتاح API للنموذج. تتوقع وثائق التطوير أيضاً وجود lsof وpython3 وcurl على الخادم. استنسخ إصداراً موسوماً بدلاً من main، لأنّ main في مشروع alpha يتغير دون تحذير.
git clone --branch v0.0.1 https://github.com/CopilotKit/openbot.git
cd openbot
cp .env.example .envجهّز مشروع Intelligence. تكتب هذه الأوامر الثلاثة مفتاح التشغيل ورمز الترخيص في ملف البيئة لديك.
npx --yes copilotkit@latest login
npx --yes copilotkit@latest project select
npx --yes copilotkit@latest license --writeأنشئ المفتاح الذي يشفّر بيانات الاعتماد المخزنة، ثم ضع الناتج في .env بوصفه KEY_ENCRYPTION_KEY. أضف OPENAI_API_KEY إلى الملف نفسه، أو اضبط BOT_PROVIDER على anthropic أو google مع المفتاح المطابق.
openssl rand -base64 32بعد ذلك ثبّت المكونات وشغّلها.
bun install
bash scripts/start.shيشغّل scripts/start.sh خدمات Docker، وينفّذ عمليات ترحيل قاعدة البيانات، ويبدأ الخادم والتطبيق، ويفحص حالتهما. عند اكتماله، يستجيب التطبيق على المنفذ 3010 وتستجيب واجهة API على المنفذ 3001. يبلّغ البرنامج النصي عن تعارضات المنافذ ويترك الخدمة المطابقة التي تعمل مسبقاً من دون تغيير، لذلك يمكنك تشغيله مرتين بأمان.
تحقق منه من الخادم نفسه قبل تعريض أي شيء للإنترنت.
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3010
ss -ltnp | grep -E ':(3010|3001|4100|4500|5432)'تعني 200 الناتجة عن الأمر الأول أنّ التطبيق يستجيب للطلبات. يوضح الأمر الثاني العناوين التي ترتبط بها هذه المنافذ، وهذه هي المعلومة المهمة على VPS. يكون السطر الذي يقرأ 127.0.0.1:3001 متاحاً داخل الخادم فقط. ويعني السطر الذي يقرأ 0.0.0.0:3001 أنّ أي جهة يمكنها توجيه حركة الشبكة إلى الخادم تستطيع الوصول إليه.
الصورة المفردة للحاوية
تتضمن وثائق النشر أيضاً صورة واحدة تحتوي على التطبيق وواجهة API وChromium، وتخدمها على المنفذ 3001.
docker build -t openbot .
docker run -p 127.0.0.1:3001:3001 --env-file .env \
-e EMBEDDED_POSTGRES=on -v openbot-data:/var/lib/postgresql/data openbotتشغّل EMBEDDED_POSTGRES=on PostgreSQL داخل الحاوية وتطبّق عمليات الترحيل عند بدء التشغيل. ويحافظ volume المسمّى على سجل التدقيق عند إعادة النشر، وبدونه تتخلص كل عملية إعادة إنشاء من ذلك السجل. وإذا وجّهت DATABASE_URL إلى قاعدة بيانات مُدارة بدلاً من ذلك، فيجب تفعيل الامتداد vector عليها. تدعم خدمات مُدارة مثل RDS وCloud SQL وAzure Database هذا الامتداد، ولا تفعّله أيٌّ منها نيابةً عنك، لذلك تفشل عملية الترحيل على قاعدة بيانات مُدارة جديدة لأن نوع العمود vector غير موجود بعد.
شغّل عمليات الترحيل كخطوة إصدار عندما تكون قاعدة البيانات خارجية.
docker run --rm --env-file .env openbot \
sh -c "cd /app/server && bun x drizzle-kit migrate --config=drizzle.config.ts"تترك تلك الصورة منفذ المتصفح غير منشور عمداً. كما تستبعد supervisor، لأن supervisor يحتاج إلى Docker socket، وهو غير متاح في المنصات عديمة الخوادم. ومن دون supervisor، تشترك كل bot في متصفح واحد، وبالتالي في مجموعة واحدة من بيانات تسجيل الدخول، ما يلغي العزل الذي جعل تشغيل حاويات منفصلة لكل bot أمراً مفيداً. إذا كان سبب استخدامك لهذا الحل هو توفير بيانات تسجيل دخول منفصلة لكل bot، فشغّل مكدس compose مع تعيين COMPUTER_SUPERVISOR_URL وSUPERVISOR_TOKEN، على مضيف تقبل فيه هذه المقايضة. ويمكن لعملية تتصل بـDocker socket تشغيل حاوية ذات امتيازات، ولذلك تكون عملياً root على المضيف. وهذا سبب وجيه لإبقاء OpenBot على جهاز مستقل، على غرار منح وكلاء البرمجة آلة افتراضية مؤقتة يمكن التخلص منها.
لماذا يُعدّ OPENBOT_SINGLE_USER إعداداً مناسباً للحاسوب المحمول
يأتي .env.example مع OPENBOT_SINGLE_USER=true. يسمح هذا الإعداد لكل طلب بالدخول بصفته طلباً من مسؤول واحد، ويتجاوز تسجيل الدخول بالكامل. يكون ذلك ملائماً على الحاسوب المحمول، لأن العميل الوحيد القادر على الوصول إلى المنفذ هو أنت. أما على VPS، فهذا يعني أن أول شخص يصل إلى المنفذ 3010 يصبح مسؤولاً عن نظام يخزّن بيانات اعتماد مشفّرة ويتحكم في متصفح سجّل الدخول إلى حساباتك مسبقاً.
هناك طريقتان سليمتان لتشغيله. أبقِ OPENBOT_SINGLE_USER=true، واربط كل منفذ بـ127.0.0.1، ولا تصل إلى التطبيق إلا عبر نفق SSH أو واجهة شبكة خاصة.
ssh -N -L 3010:127.0.0.1:3010 -L 3001:127.0.0.1:3001 you@your-vpsيصبح التطبيق متاحاً عند http://localhost:3010 في متصفحك، ويُعد ذلك سياقاً آمناً، ولذلك تعمل ملفات تعريف ارتباط تسجيل الدخول وميزات المتصفح التي تحتاج إليها الشاشة المباشرة. والطريقة الأخرى هي تعطيل وضع المستخدم الواحد وإعداد موفّر هوية حقيقي. تتوفر Google وMicrosoft Entra وOkta وSAML وOIDC. يحتاج أي موفّر أيضاً إلى BETTER_AUTH_SECRET بطول 32 محرفاً أو أكثر، وإلى ضبط BETTER_AUTH_URL على عنوان URL الأساسي العام لواجهة API من أجل عمليات معاودة OAuth، وإلى INITIAL_ADMIN_EMAILS وTRUSTED_ORIGINS. يجب أن تكون بيانات اعتماد الموفّر مكتملة، لأن إعداد الموفّر جزئياً يوقف الإقلاع بدلاً من الرجوع إلى الوصول المفتوح.
إذا كان التطبيق متاحاً عبر اسم عام، فضع TLS (أمان طبقة النقل) أمامه. لا تُعدّ الصفحة المقدَّمة عبر http:// في أي مكان غير localhost سياقاً آمناً، ولذلك لا تُخزَّن ملفات تعريف الارتباط المعلَّمة بـSecure، ويفشل تسجيل الدخول بطريقة تبدو كأنها خلل في OpenBot.
تأمين المنافذ ذات المستوى الأدنى
تنص ملاحظة OpenBot الأمنية على أن نقاط نهاية الخدمات ذات المستوى الأدنى محمية بواسطة tokens، وأنه يجب إبقاؤها خاصة، وألا تستخدمها لتجاوز البوابة. تمثل tokens طبقة الحماية الثانية. أما الطبقة الأولى فهي منع الوصول إلى المنفذ تماماً.
يستمع agent-computer على المنفذ 4100 ويتطلب COMPUTER_TOKEN. وتستمع نقاط نهاية bot على المنفذين 4200 و4201. ويستمع supervisor على المنفذ 4500 في المضيف، وعلى المنفذ 4300 داخل حاويته. ويستمع PostgreSQL على المنفذ 5432. لا ينبغي لأي من هذه المنافذ أن يكون متاحاً على واجهة عامة. وفي عملية نشر لمستخدم واحد، ينطبق ذلك أيضاً على app وAPI.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status verboseيوجد هنا فخ يوقع من يفترضون أن جدار الحماية كافٍ. يؤدي نشر منفذ حاوية باستخدام -p 3001:3001 إلى جعل Docker يثبت قاعدة DNAT، بحيث تُعالج حركة الشبكة في مسار FORWARD ولا تمر مطلقاً عبر السلسلة INPUT التي يطبّق عليها المنع الافتراضي في ufw. يظل المنفذ مفتوحاً بينما لا يزال ufw status يعرض Status: active. اربط المنفذ المنشور بواجهة loopback داخل عملية الربط نفسها، باستخدام -p 127.0.0.1:3001:3001، أو اضبط عنوان المضيف في ملف compose. تحقّق باستخدام ss -ltnp، وليس باستخدام ufw status.
OpenBot ليس حزمة تعمل دون اتصال
اذكر ذلك قبل أن تخطط للنشر. يعتمد OpenBot على مشروع Intelligence من CopilotKit، الذي يحتفظ بسلاسل المحادثات الدائمة وذاكرة المحادثة خارج خادمك. يتحقق الخادم من INTELLIGENCE_API_URL وINTELLIGENCE_GATEWAY_WS_URL وINTELLIGENCE_API_KEY وCOPILOTKIT_LICENSE_TOKEN عند بدء التشغيل، ويجب أن تكون القيم الأربع موجودة معاً، وإلا يفشل بدء التشغيل. تتوفر خطة مجانية اعتباراً من August 2026، كما يمكن استضافة Intelligence ذاتياً، لذلك يصبح النشر المحلي بالكامل ممكناً، لكنه يتطلب عملاً أكثر مما توضحه إرشادات البدء السريع.
النموذج هو التبعية الخارجية الثانية. لا يتضمن الصندوق أي نموذج. يقبل BOT_PROVIDER القيم openai أو anthropic أو google، بينما يوجّه OPENAI_BASE_URL مسار OpenAI إلى أي نقطة نهاية متوافقة. وهنا يندرج تشغيل Ollama على VPS لاستضافة LLM ذاتياً إذا أردت إبقاء الرموز المميزة على أجهزتك الخاصة. يتطلب التحكم في المتصفح قدرات كبيرة من النموذج، لذلك اختبر نموذجاً محلياً في مهمة فعلية قبل أن تعتمد عليه.
شغّل نسخة متماثلة واحدة، في الوقت الحالي
تخزّن البوابة لقطات الصفحات مؤقتاً في ذاكرة عملية الخادم. عند تشغيل نسختين متماثلتين، لا تكون اللقطة التي تنشئها إحدى العمليتين مرئية للعملية الأخرى، لذلك تفشل الإجراءات بشكل متقطع مع أخطاء تفيد بعدم العثور على العنصر، وتبدو هذه الأخطاء عشوائية. توضّح وثائق النشر ذلك صراحةً: شغّل نسخة متماثلة واحدة، واضبط الحد الأقصى لعدد instances في منصتك على 1. ينتهي هذا القيد عندما ينتقل تخزين اللقطات مؤقتاً إلى قاعدة البيانات. حتى ذلك الحين، يمكنك توسيع OpenBot بزيادة موارد الخادم، لا بإضافة خوادم أخرى. ويظل العزل بين bots متاحاً من خلال الحاويات المخصصة لكل bot، بالطريقة نفسها التي تحافظ بها بيئات sandbox للوكلاء المستضافة ذاتياً على أخطاء أحد الوكلاء بعيداً عن الوكلاء الآخرين.
أوضاع الفشل وما ستراه
يتوقف الإقلاع مباشرة بعد ملء .env. يتحقق الخادم من الإعدادات قبل أن يقدّم أي خدمة. تؤدي كتلة Intelligence غير المكتملة، أو فقدان KEY_ENCRYPTION_KEY، أو موفّر OAuth الذي يحتوي على معرّف عميل دون سر، إلى إيقاف الإقلاع بدلاً من الاستمرار مع تجاهل المشكلة. اقرأ الخطأ الأول، وأصلح ذلك الحقل، ثم ابدأ التشغيل مجدداً.
تفشل عمليات الترحيل على قاعدة بيانات مُدارة. لا يكون الامتداد vector مفعّلاً افتراضياً، لذلك تصل عملية الترحيل إلى نوع عمود لا يعرفه PostgreSQL. اتصل باستخدام حساب superuser، ونفّذ CREATE EXTENSION vector;، ثم أعد تنفيذ خطوة الترحيل.
يُحمّل التطبيق، لكن تسجيل الدخول لا يستمر أبداً. أنت تقدّم الخدمة عبر http:// غير مشفّر على عنوان عام، وهذا ليس سياقاً آمناً، لذلك تُهمل ملف تعريف الارتباط Secure. ضع TLS أمام التطبيق، أو استخدم نفق SSH لكي يرى المتصفح localhost.
تستخدم الروبوتات بيانات تسجيل دخول مشتركة رغم أنك توقعت فصلها. لا يعمل المشرف، لذلك لا يوجد حاسوب مخصص لكل روبوت، وتستخدم جميع الروبوتات المتصفح المشترك. تأكد من ضبط COMPUTER_SUPERVISOR_URL ومن قدرة المشرف على الوصول إلى Docker socket.
يتوقف أحد الروبوتات ويطلب المساعدة. هذا يعني أن التصميم يعمل كما هو متوقع. يسجل مسار التدقيق computer.help_requested، وتتولى التحكم من الشاشة المباشرة، ويُسجَّل التسليم من الجانبين.
FAQ
هل من الآمن إبقاء OPENBOT_SINGLE_USER مفعّلاً عند نشره على VPS؟
فقط عندما يتعذر الوصول إلى البوابة من الإنترنت. يتيح OPENBOT_SINGLE_USER=true كل طلب بصفة مسؤول واحد ومن دون تسجيل دخول، لذلك فإن أي شخص يستطيع فتح المنفذ يسيطر على النشر وبيانات الاعتماد المخزّنة والمتصفح الذي سجّلت الدخول منه. يكون ذلك مقبولاً عندما يكون كل منفذ مرتبطاً بـ127.0.0.1 وتصل إلى التطبيق عبر نفق SSH أو واجهة شبكة خاصة. أما على واجهة عامة، فعطّله واضبط Google أو Microsoft Entra أو Okta أو OIDC مع BETTER_AUTH_SECRET وBETTER_AUTH_URL وINITIAL_ADMIN_EMAILS وTRUSTED_ORIGINS.
ما مقدار RAM الذي يحتاج إليه روبوت OpenBot واحد؟
تضع الأرقام المنشورة للمشروع، بالنسبة إلى Bot واحد على arm64، ذروة استخدام الذاكرة عند 0.55 GB، مع حد أدنى موثّق قدره 2 GB، ويوصى بـ 4 GB. لا يوجد رقم منشور لعدة روبوتات في الوقت نفسه، لأن كل روبوت يشغّل Chromium خاصاً به. شغّل روبوتاً واحداً لتنفيذ مهمة فعلية، واقرأ ذاكرة ذلك الـcontainer في docker stats، ثم أضف ذاكرة البوابة وقاعدة البيانات، واضرب الناتج في عدد الروبوتات المتوقع تشغيلها في الوقت نفسه.
هل أحتاج إلى حساب CopilotKit لاستضافة OpenBot ذاتياً؟
نعم. يعتمد OpenBot على مشروع CopilotKit Intelligence للاحتفاظ بالخيوط والذاكرة، ويرفض الخادم التشغيل ما لم تُضبط جميع القيم التالية: عنوان Intelligence API، وعنوان WebSocket للبوابة، ومفتاح API، ورمز الترخيص. تتوفر خطة مجانية اعتباراً من August 2026، ويمكن استضافة Intelligence ذاتياً، لذلك يمكن إزالة الاعتماد على الخدمة المستضافة مع بذل جهد إضافي. عليك أيضاً توفير مفتاح API الخاص بك للنموذج، لأن OpenBot لا يتضمن أي نموذج.
لماذا يحصل كل روبوت على متصفح خاص به بدلاً من مشاركة متصفح واحد؟
لأن ملف تعريف المتصفح يمثل هوية. تؤدي مشاركة المتصفح إلى مشاركة ملفات تعريف الارتباط والجلسات، لذلك فإن تسجيل أحد الروبوتات الدخول إلى حساب يعني تسجيل جميع الروبوتات الدخول إلى الحساب نفسه. تمنح الـcontainers المنفصلة لكل روبوت ملف تعريف خاصاً وبيانات تسجيل دخول خاصة به. وتتمثل الكلفة في الذاكرة، لأن تشغيل Chromium لكل روبوت هو أكبر عنصر منفرد في متطلبات الموارد.
ما منافذ OpenBot التي ينبغي فتحها في جدار الحماية؟
لا تفتح أياً من المنافذ ذات المستوى الأدنى. يجب أن يبقى agent-computer على 4100، ونقطتا نهاية الروبوت على 4200 و4201، وsupervisor على 4500، وPostgreSQL على 5432 خاصة. يحميها المشروع باستخدام الرموز، ويطلب منك إبقاء الوصول إليها غير ممكن على أي حال. انشر فقط ما يحتاج المستخدم إلى فتحه، وتذكّر أن منفذ container المنشور باستخدام -p 3001:3001 يمكن الوصول إليه بصرف النظر عن قاعدة ufw الافتراضية التي ترفض الوصول، لأن قاعدة DNAT في Docker تضع تلك الحركة في مسار FORWARD بدلاً من INPUT.