ما معنى dsh web: http://127.0.0.1:3080؟
يظهر الخطأ dsh web: http://127.0.0.1:3080 لأن الواجهة مرتبطة بـlocalhost فقط. تعرّف إلى نفق SSH الآمن ولماذا يُعد نشر المنفذ 3080 خطراً.
ما الذي يعنيه dsh web: http://127.0.0.1:3080
عند بدء ملف تعريف DeepSeek Harness للويب على VPS، يطبع سطرين ثم ينتظر:
dsh web: http://127.0.0.1:3080
Ready.127.0.0.1 هو عنوان loopback. وهو العنوان الذي يستخدمه الجهاز للاتصال بنفسه. تقبل socket المرتبطة بـ127.0.0.1 الاتصالات من العمليات الموجودة على الجهاز نفسه فقط، ولا تقبلها من أي مكان آخر. لذلك يوضح لك هذا السطر أمرين في الوقت نفسه: العنوان الذي تستمع عليه واجهة الويب، والجهة المسموح لها بالوصول إليها. الجهاز dsh فقط هو الذي يشغّلها.
لهذا السبب لا يفعل عنوان URL شيئاً عند لصقه في المتصفح على جهازك المحمول. عنوان 127.0.0.1 على جهازك المحمول يعود إلى جهازك المحمول نفسه. أما Harness فيستمع على 127.0.0.1 الخاص بـVPS، وهو جهاز مختلف يملك مكدس loopback مختلفاً. لا يوجد عطل. تحتاج إلى تمرير الاتصال عبر الشبكة.
يوضح README الرسمي الإعداد الافتراضي مباشرة: "يبدأ الأمر واجهة الويب، وتُقدَّم افتراضياً على http://127.0.0.1:3080." يأتي عنوان الربط من إضافة مضيف خادم الويب، @deepseek-ai/dsh-host-webserver، حيث يوثَّق مفتاح host على النحو التالي: "مضيف الاستماع؛ القيمتان المدعومتان هما loopback وall-interfaces". تحصل على loopback ما لم تغيّره يدوياً. إذا كانت المنافذ جديدة عليك، يشرح كيفية عمل المنافذ في Linux نموذج العنوان والمنفذ الذي يعتمد عليه كل ذلك.
سبب ربط واجهة الويب بـ localhost فقط
dsh هو إطار تشغيل لوكيل. تمثل علامة تبويب المتصفح سطح تحكم لعملية تنفّذ أوامر shell، وتقرأ الملفات وتكتبها في دليل مساحة العمل الذي اخترته، وتستهلك مفتاح API الخاص بالنموذج. يمكن لأي شخص يستطيع تحميل تلك الصفحة تنفيذ كل ذلك بامتيازات المستخدم الذي يشغّل dsh.
لذلك، فإن المنفذ 3080 ليس لوحة معلومات للقراءة فقط. يمنح تحميل تلك الصفحة إمكانية تنفيذ الأوامر على الخادم.
عند فتح واجهة الويب، تنتقل مباشرة إلى قائمة الجلسات. لا تظهر مطالبة بتسجيل الدخول، لأن الإصدار التجريبي للمطورين لا يتضمن حسابات مستخدمين ولا مصادقة عن بُعد. يكون ذلك متسقاً عند الربط بـ loopback: يتولى نظام التشغيل التحكم في الوصول، ولا تمر إلا العمليات المحلية. إذا ربطت الخادم نفسه بـ 0.0.0.0 على VPS ذي عنوان IP عام، فستستجيب الصفحة نفسها للإنترنت بأكمله، من دون وجود أي طبقة حماية أمامها. تفحص الماسحات الآلية المنافذ غير الشائعة باستمرار، لذلك تعامل مع المنفذ 3080 المنشور على أنه سيُكتشف.
لا تفتح المنفذ 3080 في جدار الحماية، ولا تضبطhostالخاص بخادم الويب على0.0.0.0في VPS عام. فهذا الجمع يمنح تنفيذ الأوامر على خادمك لأول من يتصل به.
ينطبق المنطق نفسه على كل بيئة تشغيل لوكيل تضعها على خادم. لذلك يبدأ تشغيل وكيل برمجي بأمان على VPS من القاعدة نفسها: يبقى منفذ تحكم الوكيل خاصاً، وتتولى جهة تثق بها نقلك إليه.
كيف أفتح واجهة Web الخاصة بـ dsh من حاسوبي المحمول؟
هناك 3 طرق سليمة، وتُبقي كل واحدة منها الـharness مرتبطاً بـloopback.
- نفق SSH. لا توجد خدمة جديدة تستمع على الواجهة العامة، ولديك بيانات الاعتماد مسبقاً. استخدم هذه الطريقة.
- شبكة overlay خاصة، بحيث يمكن الوصول إلى الواجهة من أجهزتك أنت، ولا يراها أي شخص آخر.
- Reverse Proxy ينهي TLS (أمان طبقة النقل) ويطلب كلمة مرور قبل أن يمرر أي شيء.
يكمن الاختلاف بينها في الوسيلة التي تنقل متصفحك إلى loopback. لا ينبغي أن تتضمن أي منها نقل الـharness خارج loopback.
الوصول إليه عبر نفق SSH
نفّذ هذا على حاسوبك المحمول، وليس على VPS:
ssh -N -L 3080:127.0.0.1:3080 you@your-vpsاتركه قيد التشغيل، ثم افتح http://127.0.0.1:3080 في المتصفح المحلي لديك. ستُحمَّل واجهة Web.
يحتوي الوسيط -L على 3 حقول تفصل بينها نقطتان. الحقل الأول هو المنفذ الذي سيفتح على حاسوبك المحمول. الحقلان الثاني والثالث هما العنوان والمنفذ اللذان ستُحوَّل إليهما كل اتصالاتك. التفاصيل المهمة هي أن 127.0.0.1 في الحقل الأوسط يُحلِّه خادم SSH على VPS، بعد وصول حركة الشبكة إليه. وهو يشير إلى loopback الخاص بـVPS، وليس إلى loopback الخاص بك. وهذا هو العنوان نفسه الذي طبعه dsh، ولذلك يعمل النفق عندما لا يعمل اتصال المتصفح المباشر.
يشير -N إلى SSH بعدم تشغيل أمر بعيد، ولذلك تحصل على مُعيد توجيه من دون shell. لإنشاء نفق في الخلفية مع إظهار الفشل بدلاً من تجاهله:
ssh -N -f -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -L 3080:127.0.0.1:3080 you@your-vpsيضعه -f في الخلفية بعد المصادقة. وتكمن أهمية ExitOnForwardFailure=yes في أنه من دونها ينجح SSH في الاتصال حتى عندما يتعذر إعداد إعادة التوجيه، فتحصل على جلسة عاملة ونفق متوقف من دون تحذير. يرسل ServerAliveInterval=30 رسالة keepalive كل 30 ثانية، حتى يبقى النفق فعالاً عند انتهاء مهلات NAT (ترجمة عناوين الشبكة) في أجهزة التوجيه في المقاهي والفنادق.
ما يجب أن تراه
على VPS، تحقّق مما يستمع فعلياً:
ss -ltnp | grep 3080تُظهر النتيجة السليمة عنوان loopback:
LISTEN 0 511 127.0.0.1:3080 0.0.0.0:* users:(("node",pid=1042,fd=21))إذا قرأ عمود العنوان المحلي 0.0.0.0:3080 بدلاً من ذلك، فهذا يعني أن واجهة Web متاحة على كل واجهة، بما فيها الواجهة العامة. أوقفها وأصلح عنوان bind قبل تنفيذ أي شيء آخر. إذا طبع ss المقبس لكنه ترك الحقل users: فارغاً، فشغّله مع sudo، لأن اسم العملية الخاصة بمقبس يملكه مستخدم آخر يكون مخفياً خلاف ذلك.
عندما يرفض النفق البدء
يطبع SSH الرسالة التالية ثم يخرج:
bind [127.0.0.1]:3080: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 3080يتعلق هذا بحاسوبك المحمول، وليس بالخادم. هناك شيء محلي يستخدم المنفذ 3080 بالفعل، وغالباً يكون نفقاً سابقاً نسيته. اختر منفذاً محلياً متاحاً بدلاً منه:
ssh -N -L 3081:127.0.0.1:3080 you@your-vpsتغيّر الحقل الأول فقط، ولذلك ستتصفح الآن إلى http://127.0.0.1:3081 بينما يواصل harness الاستماع على 3080. لا يلزم أن يتطابق الرقمان.
إذا بدأ النفق لكن أبلغ المتصفح عن رفض الاتصال أو عن رد فارغ، فهذا يعني أن حركة الشبكة عبرت إلى VPS ولم تجد شيئاً في الطرف البعيد. إما أن dsh خرج، أو أنه ربط منفذاً مختلفاً. تحقّق باستخدام ss -ltnp | grep 3080 على الخادم.
هناك أمر آخر يسبب المشكلات هنا. يتوقف npx @deepseek-ai/dsh web الذي يعمل في الواجهة الأمامية عند إغلاق shell، ولذلك يوقف harness عمله فور تسجيل الخروج. ابدأه داخل tmux أو باستخدام خدمة systemd خاصة بالمستخدم، وهي تعالج المشكلة نفسها الموضحة في إبقاء وكيل برمجي قيد التشغيل على VPS. وأثناء عملك على جانب SSH، من المفيد تنفيذ تعزيز أمان SSH على VPS أولاً، لأن النفق يجعل تسجيل دخولك عبر SSH الباب الوحيد للوصول إلى الوكيل.
الوصول عبر شبكة overlay خاصة
تمنحك شبكة overlay أنت وخادم VPS المحمول عناوين على شبكة خاصة لا تنضم إليها إلا أجهزتك. يُعد Tailscale الخيار الشائع، ويتوافق الأمر serve معه تماماً في هذه الحالة: يُشغَّل tailscaled على خادم VPS ويتصل بـ localhost:3080 نفسه، لذلك يبقى harness على loopback ولا تغيّر شيئاً في طريقة إعداد dsh.
tailscale serve --bg localhost:3080
tailscale serve statusيمكنك بعد ذلك الوصول إلى واجهة المستخدم عبر اسم جهازك داخل tailnet، باستخدام HTTPS، من دون فتح أي منفذ على الواجهة العامة. يتطلب ذلك تفعيل شهادات HTTPS لـtailnet، وإلا فلن يمتلك serve شهادة يقدّمها. لإيقافه، كرر الأمر باستخدام off:
tailscale serve --https=443 offاستخدم serve، وليس funnel. ينشر Funnel الهدف نفسه على الإنترنت العام، ما يعيدك إلى بيئة تشغيل agent غير موثّقة على منفذ مفتوح. يبدو الأمران متطابقين تقريباً، لكنهما ينفّذان إجراءين متعاكسين، لذلك اقرأ الفرق بين Tailscale Serve وFunnel قبل كتابة أيٍّ منهما. يشرح Tailscale كشبكة خاصة إعداد الشبكة نفسه.
الوصول إليه عبر Reverse Proxy يتحقق من كلمة مرور
هذا هو الخيار الذي ينشر منفذاً فعلياً على الإنترنت، لذلك تكون المصادقة هي الحاجز الوحيد بين شخص غريب وتنفيذ الأوامر على خادمك. اختره عندما يحتاج عدة أشخاص إلى واجهة المستخدم ويكون إنشاء نفق لكل شخص غير عملي.
يبقى harness على 127.0.0.1:3080. يعمل nginx على الخادم نفسه، لذلك يمكنه الوصول إلى loopback، ويستمع على المنفذ 443 باستخدام شهادة وملف كلمات مرور.
server {
listen 443 ssl;
server_name dsh.example.com;
ssl_certificate /etc/letsencrypt/live/dsh.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dsh.example.com/privkey.pem;
auth_basic "dsh";
auth_basic_user_file /etc/nginx/dsh.htpasswd;
location / {
proxy_pass http://127.0.0.1:3080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
proxy_buffering off;
}
}أنشئ ملف كلمات المرور ثم أعد التحميل:
sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/dsh.htpasswd you
sudo nginx -t && sudo systemctl reload nginxيجب أن يطبع nginx -t القيمة syntax is ok متبوعةً بالقيمة test is successful. تفشل إعادة التحميل عند وجود ملف تالف، وتُبقي الإعداد قيد التشغيل كما هو. لذلك اقرأ رسالة الخطأ بدلاً من إعادة التشغيل عشوائياً.
ثلاثة من أسطر Proxy هذه ضرورية وليست شكلية. تسمح ترويساتا Upgrade وConnection بمرور مصافحة WebSocket. من دونهما تُحمّل الصفحة، لكنها لا تتحدث مطلقاً. تستبدل proxy_read_timeout 3600s القيمة الافتراضية البالغة 60 ثانية. وإلا يُقطع تشغيل agent الطويل أثناء الاستجابة، وتبدو واجهة المستخدم متوقفة. ترسل proxy_buffering off مخرجات النموذج إلى المتصفح فور وصولها بدلاً من احتجازها حتى تكتمل الاستجابة. يشرح إعداد Reverse Proxy في nginx، سطراً بسطر بقية التفاصيل، ويتناول الاختيار بين nginx وCaddy وTraefik تنفيذ الشيء نفسه باستخدام شهادات تلقائية.
أبقِ المنفذ 3080 مغلقاً في جدار الحماية، أياً كان Proxy الذي تختاره، بحيث يمر المسار الوحيد إلى الداخل عبر نقطة الوصول التي تتطلب المصادقة. يشرح أساسيات جدار الحماية ufw القواعد. المصادقة الأساسية عبر TLS هي الحد الأدنى وليست نموذج أمان مكتملًا: من يملك كلمة المرور يملك shell على خادمك. استخدم النفق متى أمكنك ذلك.
كيف أغيّر المنفذ الذي تستمع عليه واجهة dsh على الويب؟
--port يخص تطبيق الويب، وليس المشغّل. تعرض وثائق CLI المثال مباشرة:
dsh --profile web --port 8080dsh web هو اسم مستعار لـ --profile web، لذلك فإن dsh web --port 8080 هو الأمر نفسه. يحلّل المشغّل أعلامه فقط، ويمرّر كل ما يليها إلى profile الذي شغّله. لذلك تأتي أعلام المشغّل أولاً، ويبدأَـت وسائط التطبيق عند أول token لا يتعرّف إليه المشغّل. ضع --port بعد profile، وليس قبله.
اقرأ URL الذي يطبعه الأمر بدلاً من افتراضه، لأن هذا السطر يعرض العنوان الذي ربط به الخادم فعلياً. ثم حدّث الحقل الأخير في tunnel ليطابقه:
ssh -N -L 3080:127.0.0.1:8080 you@your-vpsلإجراء تغيير دائم، يوجد المنفذ في إعدادات profile بدلاً من سطر الأوامر. يهيّئ profile web وheadless نفسه تلقائياً عند أول استخدام من القوالب المضمّنة، ضمن ~/.dsh. لعرض الإعداد الفعلي بعد دمج جميع الطبقات:
dsh --dump-configيكشف plugin الخاص بـ webserver عن مفتاحين فقط، هما host وport. يؤدي ضبط port على 0 إلى طلب منفذ متاح من نظام التشغيل، كما توضّح الوثائق: «يطلب الصفر منفذاً يعيّنه نظام التشغيل». يضمن ذلك عدم حدوث تعارض، لكنه غير مناسب لـ tunnel، لأن الرقم يتغير عند كل إعادة تشغيل.
لماذا يفشل dsh بسبب استخدام العنوان بالفعل؟
لأن عملية أخرى تشغل العنوان والمنفذ بالفعل، ولذلك ترفض النواة عملية الربط الثانية. يعرض Node الخطأ بهذا الشكل:
Error: listen EADDRINUSE: address already in use 127.0.0.1:3080حدّد العملية التي تشغل العنوان قبل تغيير أي شيء:
sudo ss -ltnp | grep 3080يحدّد الحقل users:(("node",pid=1042,fd=21)) العملية ورقم PID الخاص بها. غالباً ما تكون العملية نسخة سابقة من dsh ظننت أنها توقفت، لكنها ما تزال تعمل داخل نافذة tmux منفصلة. أوقفها باستخدام kill 1042، أو شغّل النسخة الجديدة على منفذ مختلف. لاحظ أن 127.0.0.1:3080 و0.0.0.0:3080 يتعارضان أيضاً، لأن الربط بجميع الواجهات يشمل loopback بالفعل.
ثبّت الإصدار لأن هذه معاينة للمطورين
يوضح ملف README ذلك صراحةً: ما يزال DeepSeek Harness في مرحلة معاينة للمطورين ويتغير بسرعة، وستطرأ تغييرات تكسر التوافق.
يحل npx @deepseek-ai/dsh web إلى أحدث إصدار منشور في كل مرة تشغّله فيها. قد يبدأ خادم لم تلمسه منذ أسبوع تشغيل CLI مختلف في المرة التالية، مع flags مختلفة. ثبّت الإصدار حتى لا تتحول إعادة التشغيل إلى ترقية:
npx @deepseek-ai/dsh@0.1.0-rc.7 webاعتباراً من August 2026، الإصدار المنشور من الحزمة هو 0.1.0-rc.7. تحقّق مما سيجلبه npx من دون إصدار محدد قبل قبوله:
npm view @deepseek-ai/dsh versionتنتقل flags بين المشغّل وتطبيق الويب في إصدارات المعاينة. إذا توقف --port عن العمل بالطريقة الموضحة في هذا الدليل، فاطلب من التطبيق نفسه قائمة flags بدلاً من التخمين:
dsh --profile web --helpلإعداد التثبيت نفسه، وإعداد مساحة العمل، ومفتاح النموذج، راجع تثبيت DeepSeek Harness على VPS. ولشرح أقصر لخطوة الوصول وحدها، يشرح الوصول إلى واجهة Web UI لـ dsh على VPS النفق من دون التعليل.
FAQ
لماذا لا يمكنني فتح http://127.0.0.1:3080 في متصفح الكمبيوتر المحمول؟
لأن 127.0.0.1 يشير إلى الجهاز الذي تكتب عليه. ترتبط واجهة DeepSeek Harness Web بــloopback الخاص بـVPS، لذلك لا يمكن الاتصال بها إلا من عمليات تعمل على VPS. لدى الكمبيوتر المحمول loopback منفصل خاص به، ولا توجد خدمة تستمع على المنفذ 3080 فيه. نفّذ إعادة توجيه للمنفذ عبر SSH باستخدام ssh -N -L 3080:127.0.0.1:3080 you@your-vps، ثم افتح http://127.0.0.1:3080 محلياً. يُحل الحقل الأوسط من وسيطة -L على جانب الخادم، ولذلك يشير إلى harness.
هل من الآمن ربط واجهة dsh Web بـ0.0.0.0 على VPS عام؟
لا. واجهة Web هي سطح التحكم في agent الذي ينفذ أوامر shell ويعدّل الملفات بامتيازات المستخدم الذي يشغّل dsh، كما أن المعاينة التطويرية لا تعرض شاشة تسجيل دخول إطلاقاً. يعني الربط بجميع الواجهات على عنوان IP عام أن أي شخص يصل إلى المنفذ 3080 يمكنه تنفيذ الأوامر على خادمك. أبقِ الربط على 127.0.0.1، وأبقِ المنفذ 3080 مغلقاً في جدار الحماية، واستخدم نفق SSH أو شبكة overlay خاصة أو reverse proxy يتطلب كلمة مرور.
كيف أبقي واجهة dsh Web قيد التشغيل بعد إغلاق جلسة SSH؟
يكون npx @deepseek-ai/dsh web الذي يعمل في المقدمة ابناً لـlogin shell، لذلك يُنهى عند خروج تلك shell. شغّله داخل جلسة tmux وافصل الجلسة باستخدام Ctrl-b d، أو شغّله كخدمة systemd للمستخدم مع تفعيل lingering. النفق وharness مستقلان: يمكنك إسقاط نفق SSH وإعادة إنشائه كلما شئت دون التأثير في harness قيد التشغيل، ما دام لـharness نفسه parent يستمر بعد انتهاء جلسة الدخول.
لماذا تتجمد واجهة dsh Web في منتصف تشغيل agent طويل خلف nginx؟
لأن proxy_read_timeout الافتراضي في nginx هو 60 ثانية، ولذلك يغلق اتصالاً لا ينتج أي بيانات لمدة دقيقة، وهو أمر يحدث بسهولة أثناء خطوة agent طويلة. اضبط proxy_read_timeout 3600s; في كتلة location. أضف proxy_buffering off; حتى تُرسل المخرجات إلى المتصفح فور وصولها، ومرّر الرأسيْن Upgrade وConnection باستخدام proxy_http_version 1.1; حتى تنجح مصافحة WebSocket. من دون هذين الرأسين، تُحمّل الصفحة لكنها لا تتلقى أي تحديث.