SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-26

لماذا يعرض dsh الرابط http://127.0.0.1:3080؟

يعرض dsh الخطأ الظاهري http://127.0.0.1:3080 لأن Web UI تستمع محلياً فقط. تعرّف إلى نفق 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 الاتصالات من العمليات الموجودة على الجهاز نفسه فقط، ولا تقبلها من أي مكان آخر. لذلك يوضح لك هذا السطر أمرين في الوقت نفسه: العنوان الذي تستمع عليه Web UI، والجهة المسموح لها بالوصول إليها. وهي الجهاز الذي يعمل عليه dsh فقط.

لهذا لا يفعل الرابط شيئاً عند لصقه في المتصفح على حاسوبك المحمول. عنوان 127.0.0.1 في حاسوبك المحمول هو حاسوبك المحمول نفسه. يستمع harness على 127.0.0.1 في VPS، وهو جهاز مختلف له loopback stack مختلف. لا يوجد عطل. تحتاج إلى تمرير الاتصال بين الجهازين.

يوضح README الرسمي الإعداد الافتراضي صراحةً: "يبدأ الأمر Web UI، وتُقدَّم افتراضياً على http://127.0.0.1:3080." يأتي عنوان الربط من webserver host plugin، وهو @deepseek-ai/dsh-host-webserver، وتوثَّق فيه قيمة host على النحو التالي: "مضيف الاستماع؛ القيمتان المدعومتان هما loopback وall-interfaces". تحصل على loopback ما لم تغيّر هذا الإعداد. إذا كانت المنافذ جديدة عليك، يشرح كيفية عمل المنافذ في Linux نموذج العنوان مع المنفذ الذي يعتمد عليه كل ذلك.

لماذا ترتبط واجهة الويب بـlocalhost فقط

dsh هو إطار تشغيل للوكيل، أي البرنامج المحيط بالنموذج: فهو يدير الحلقة، واستدعاءات الأدوات، والصلاحيات التي تُنفَّذ بها تلك الاستدعاءات. وتُعد علامة تبويب المتصفح واجهة تحكم لعملية تنفّذ أوامر shell، وتقرأ الملفات وتكتبها في مجلد مساحة العمل الذي اخترته، وتستهلك مفتاح API الخاص بالنموذج. ويمكن لأي شخص يستطيع تحميل تلك الصفحة تنفيذ كل ذلك بصفته المستخدم الذي يشغّل dsh. ولا تقتصر طرق الوصول إلى هذه الصلاحيات على الشبكة؛ إذ يعمل أي plugin تثبّته داخل العملية نفسها وبالصلاحيات نفسها. لذلك فإن فحص plugin 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 UI.

تتضمن الوسيطة -L ثلاثة حقول تفصل بينها نقطتان. الحقل الأول هو المنفذ الذي يجب فتحه على حاسوبك المحمول. الحقلان الثاني والثالث هما العنوان والمنفذ اللذان يجب إعادة توجيه كل اتصال إليهما. التفصيل المهم هو أن 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 UI يعمل على كل واجهة، بما فيها الواجهة العامة. أوقفه وأصلح عنوان الربط قبل تنفيذ أي إجراء آخر. إذا طبعت 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 للمستخدم، فهذه هي المشكلة نفسها التي عولجت في إبقاء coding agent قيد التشغيل على VPS. وأثناء عملك على جانب SSH، يُستحسن تنفيذ تقوية SSH على VPS أولاً، لأن النفق يجعل تسجيل دخول SSH الخاص بك الباب الوحيد للوصول إلى agent.

الوصول إليه عبر شبكة 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 الهدف نفسه على الإنترنت العام، ما يعيدك إلى runtime لوكيل غير موثّق على منفذ مفتوح. يبدو الأمران متطابقين تقريباً، لكنهما ينفذان إجراءين متعاكسين. لذلك اقرأ الفرق بين Tailscale Serve وFunnel قبل كتابة أي منهما. يشرح Tailscale كشبكة خاصة إعداد الشبكة نفسه.

الوصول إليه عبر Reverse Proxy يتحقق من كلمة مرور

هذا هو الخيار الذي ينشر منفذاً فعلياً على الإنترنت، ولذلك تكون المصادقة هي الحاجز الوحيد بين شخص غريب وتنفيذ الأوامر على خادمك. اختره عندما يحتاج عدة أشخاص إلى واجهة المستخدم ويكون إنشاء نفق لكل شخص غير عملي.

تظل أداة الاختبار على 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 الذي تختاره، بحيث يكون المسار الوحيد للدخول عبر الـproxy الذي يطلب المصادقة. يشرح أساسيات جدار الحماية ufw القواعد اللازمة. المصادقة الأساسية عبر TLS هي الحد الأدنى وليست نموذج أمان مكتملاً. من يملك كلمة المرور يملك وصولاً إلى shell على خادمك. فضّل النفق متى أمكنك ذلك.

كيف أغيّر المنفذ الذي يستمع عليه dsh web؟

ينتمي --port إلى تطبيق الويب، وليس إلى المشغّل. تعرض وثائق CLI المثال مباشرة:

dsh --profile web --port 8080

dsh web هو اسم مستعار لـ --profile web، ولذلك فإن dsh web --port 8080 هو الأمر نفسه. يحلّل المشغّل أعلامه فقط، ويمرّر كل ما يليها إلى ملف التعريف الذي شغّله. لذلك تأتي أعلام المشغّل أولاً، وتبدأ وسيطات التطبيق عند أول رمز لا يتعرّف عليه المشغّل. ضع --port بعد ملف التعريف، وليس قبله.

اقرأ عنوان URL الذي يطبعه الأمر بدلاً من افتراضه، لأن هذا السطر يعرض العنوان الذي ربط الخادم نفسه به فعلياً. ثم حدّث الحقل الأخير في نفقك ليتطابق معه:

ssh -N -L 3080:127.0.0.1:8080 you@your-vps

لتغيير المنفذ بشكل دائم، يجب ضبطه في إعدادات ملف التعريف بدلاً من سطر الأوامر. تتم تهيئة ملفي التعريف web وheadless تلقائياً عند الاستخدام الأول من القوالب المضمّنة في ~/.dsh. ويحتوي الدليل نفسه على إعدادات مفتاح API ونقطة نهاية النموذج، لذلك فإن إعداد مفاتيح dsh ونماذجه ونقاط نهايته هو المرجع المكمّل الذي ينبغي قراءته عند تحرير هذه الملفات. لعرض الإعداد الفعلي بعد دمج جميع الطبقات:

dsh --dump-config

تكشف إضافة webserver مفتاحين فقط، هما host وport. يؤدي ضبط port على 0 إلى طلب منفذ متاح من نظام التشغيل، كما توضّح الوثائق: «يطلب الصفر منفذاً يعيّنه نظام التشغيل». يضمن ذلك عدم حدوث تعارض، لكنه لا يناسب النفق، لأن الرقم يتغير عند كل إعادة تشغيل.

لماذا يفشل 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 في مرحلة معاينة للمطورين، ويتغير بسرعة، وستطرأ تغييرات تكسر التوافق. إذا كان هذا الإيقاع هو سبب ترددك، فالمقالة مقارنة dsh مع Claude Code وOmnigent تضعه في مقابل أداتين تمر كل منهما بمرحلة مختلفة على المنحنى نفسه.

يحل 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

إذا رفض التثبيت الإصدار المثبّت، أو استمر npx في تشغيل الإصدار القديم بعد تثبيت إصدار أحدث، فتشرح أخطاء التثبيت والإصدار التي يطرحها هذا الأمر كيفية مسح ذاكرة التخزين المؤقت لـnpx والتحقق من إصدار npm المضمّن مع Node.

تنتقل flags بين المشغّل وتطبيق الويب في إصدارات المعاينة. إذا توقف --port عن العمل بالطريقة التي يصفها هذا الدليل، فاطلب من التطبيق قائمة flags الخاصة به بدلاً من التخمين:

dsh --profile web --help

للتثبيت نفسه، وإعداد مساحة العمل، ومفتاح النموذج، راجع تثبيت DeepSeek Harness على VPS. ولشرح أقصر لخطوة الوصول وحدها، يشرح الوصول إلى واجهة dsh Web UI على VPS إعداد النفق من دون التفاصيل المنطقية.

FAQ

لماذا لا أستطيع فتح http://127.0.0.1:3080 في متصفح الحاسوب المحمول؟

لأن 127.0.0.1 يشير إلى الجهاز الذي تكتب عليه الأمر. ترتبط واجهة DeepSeek Harness Web UI بعنوان 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 UI بالعنوان 0.0.0.0 على خادم VPS عام؟

لا. واجهة Web UI هي سطح التحكم في وكيل ينفّذ أوامر shell ويعدّل الملفات بصفة المستخدم الذي يشغّل dsh، كما أن المعاينة التطويرية لا تعرض شاشة تسجيل دخول إطلاقاً. يعني الربط بجميع الواجهات على عنوان IP عام أن أي شخص يصل إلى المنفذ 3080 يستطيع تنفيذ الأوامر على خادمك. أبقِ الربط على 127.0.0.1، وأبقِ المنفذ 3080 مغلقاً في جدار الحماية، واستخدم نفق SSH أو شبكة overlay خاصة أو reverse proxy يطلب كلمة مرور.

كيف أبقي واجهة dsh Web UI قيد التشغيل بعد إغلاق جلسة SSH؟

يكون npx @deepseek-ai/dsh web الذي يعمل في الواجهة الأمامية تابعاً لـshell تسجيل الدخول، لذلك يُنهى عند خروج ذلك الـshell. شغّله داخل جلسة tmux وافصل الجلسة باستخدام Ctrl-b d، أو شغّله كخدمة systemd للمستخدم مع تفعيل lingering. النفق وharness مستقلان: يمكنك إسقاط نفق SSH وإعادة إنشائه كلما شئت من دون التأثير في harness قيد التشغيل، ما دام لـharness نفسه تابع أبقى من جلسة تسجيل الدخول.

لماذا تتجمّد واجهة dsh Web UI في منتصف تشغيل وكيل طويل خلف nginx؟

لأن قيمة proxy_read_timeout الافتراضية في nginx هي 60 ثانية، ولذلك يغلق اتصالاً لا ينتج أي بيانات لمدة دقيقة، وهو أمر يحدث بسهولة أثناء خطوة طويلة للوكيل. اضبط proxy_read_timeout 3600s; في كتلة location. أضف proxy_buffering off; حتى تُرسل المخرجات إلى المتصفح فور وصولها، ومرّر رأسي Upgrade وConnection باستخدام proxy_http_version 1.1; حتى تنجح مصافحة WebSocket. من دون هذين الرأسين، تُحمّل الصفحة لكنها لا تتلقى أي تحديث.