dshのhttp://127.0.0.1:3080に接続する方法
dshがhttp://127.0.0.1:3080と表示する理由はWeb UIがlocalhost限定で待ち受けるためです。SSHトンネルで安全に接続する方法と、3080の公開が危険な理由を解説します。
dsh web: http://127.0.0.1:3080 の意味
VPS で DeepSeek Harness の Web プロファイルを起動すると、2 行を出力した後に待機します。
dsh web: http://127.0.0.1:3080
Ready.127.0.0.1 はループバックアドレスです。これは、マシンが自分自身と通信するために使用するアドレスです。127.0.0.1 にバインドされたソケットは、同じマシン上のプロセスからの接続だけを受け付けます。それ以外の接続は受け付けません。この行から、Web UI が待ち受けている場所と、接続できる対象の両方が分かります。接続できるのは、dsh が実行されているマシンだけです。
そのため、この URL をラップトップのブラウザーに貼り付けても何も起こりません。ラップトップの 127.0.0.1 は、ラップトップ自身を指します。Harness は、別のマシンである VPS の 127.0.0.1 で待ち受けています。両者のループバックスタックは異なります。何も壊れているわけではありません。接続を転送する必要があります。
公式 README には、デフォルト設定が明記されています。「このコマンドは Web UI を起動し、デフォルトでは http://127.0.0.1:3080 で提供します」。バインドアドレスは Webserver host plugin の @deepseek-ai/dsh-host-webserver から取得されます。このプラグインの host キーには、「待ち受けるホスト。指定できる値は loopback と all-interfaces の 2 つ」と記載されています。変更しない限り、loopback が使用されます。ポートに不慣れな場合は、Linux でのポートの仕組みで、この仕組みの基礎となるアドレスとポートの関係を確認できます。
Web UI が localhost のみにバインドする理由
dsh はエージェントハーネスです。モデルを包むプログラムであり、ループ、ツール呼び出し、それらの呼び出しに適用される権限を管理します。ブラウザーのタブは、シェルコマンドを実行し、選択した workspace directory のファイルを読み書きし、モデル API key を消費するプロセスの操作画面です。そのページを読み込めるユーザーは、dsh を実行しているユーザーとして、これらすべてを実行できます。この経路はネットワークだけではありません。インストールした plugin は同じプロセス内で同じ権限を使って実行されます。そのため、インストール前に dsh plugin を検証することは、サーバーの待ち受け先を決める場合と同じように慎重に行う必要があります。
したがって、port 3080 は読み取り専用の dashboard ではありません。そのページを読み込むと、サーバー上でコマンドを実行できます。
Web UI を開くと、すぐに session list が表示されます。login prompt がないのは、developer preview にユーザーアカウントとリモート認証が用意されていないためです。loopback では、この動作に問題はありません。アクセス制御をオペレーティングシステムが担い、ローカルプロセスだけが接続できるためです。同じ server を、public IP を持つ VPS 上で 0.0.0.0 にバインドすると、前段に何もない状態で、そのページがインターネット全体から利用可能になります。自動スキャナーは一般的でない port も継続的に探索するため、公開した 3080 は発見されるものとして扱ってください。
firewall で port 3080 を開放しないでください。また、public VPS で webserver のhostを0.0.0.0に設定しないでください。この組み合わせでは、最初に接続したユーザーにサーバー上のコマンド実行権限を渡すことになります。
同じ考え方は、サーバー上で動かすすべての agent runtime に当てはまります。そのため、VPS 上で coding agent を安全に実行する方法も、同じ原則から始まります。agent の control port は非公開にし、信頼できる仕組みを経由して接続します。
ノートパソコンから dsh Web UI を開くにはどうすればよいですか?
正攻法は 3 つあります。いずれの場合も、ハーネスは loopback にバインドしたままにします。
- SSH トンネルを使用する方法です。public interface で新たに待ち受けるものはなく、すでに認証情報もあります。使用すべき方法はこれです。
- private overlay network を使用する方法です。自分のデバイスからのみ UI に到達でき、他のユーザーからは見えません。
- TLS (transport layer security) を終端する reverse proxy を使用する方法です。reverse proxy は、転送する前にパスワードを要求します。
違いは、ブラウザーから loopback までの通信を何が運ぶかです。いずれの方法でも、ハーネスを loopback から移動させてはいけません。
SSH トンネルで接続する
VPS ではなく、ノート PC で次のコマンドを実行します。
ssh -N -L 3080:127.0.0.1:3080 you@your-vps実行したままにして、ローカルブラウザーで http://127.0.0.1:3080 を開きます。Web UI が読み込まれます。
-L 引数には、コロンで区切られた 3 つのフィールドがあります。1 番目はノート PC で開くポートです。2 番目と 3 番目は、各接続の転送先となるアドレスとポートです。重要なのは、中央のフィールドにある 127.0.0.1 が、トラフィックがすでに到着した後に、VPS 上の SSH サーバーによって解決されることです。これはノート PC ではなく、VPS のループバックアドレスを指します。まさに dsh が表示したアドレスです。そのため、ブラウザーから直接接続できない場合でもトンネルは機能します。
-N は SSH にリモートコマンドを実行させない指定です。そのため、シェルではなく転送専用になります。警告を出さずに失敗することを避け、バックグラウンドでトンネルを実行するには、次のようにします。
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 は 30 秒ごとに keepalive を送信します。これにより、カフェやホテルのルーターで発生する NAT(ネットワークアドレス変換)のタイムアウト後も、アイドル状態のトンネルを維持できます。
確認する内容
VPS 上で、実際に待ち受けているアドレスを確認します。
ss -ltnp | grep 3080正常な結果では、ループバックアドレスが表示されます。
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これはサーバーではなく、ノート PC 側の問題です。ローカルのポート 3080 は、以前のトンネルを終了し忘れた場合などに、すでに別のプロセスが使用している可能性があります。空いているローカルポートを選びます。
ssh -N -L 3081:127.0.0.1:3080 you@your-vps変更したのは 1 番目のフィールドだけです。そのため、ハーネスは 3080 で待ち受けたまま、ブラウザーでは http://127.0.0.1:3081 にアクセスします。2 つの番号を一致させる必要はありません。
トンネルは起動するものの、ブラウザーに接続拒否または空の応答が表示される場合、トラフィックは VPS まで到達していますが、転送先で待ち受けているものがありません。dsh が終了したか、別のポートにバインドしています。サーバー上で ss -ltnp | grep 3080 を実行して確認してください。
ここでは、もう 1 つ注意点があります。フォアグラウンドで実行した npx @deepseek-ai/dsh web は、シェルを閉じると終了します。そのため、ログアウトした時点でハーネスも停止します。tmux 内部、または systemd のユーザーサービスとして起動してください。これは、VPS 上で coding agent を実行し続ける場合と同じ問題への対処です。SSH 側の作業中に、VPS の SSH を強化することも先に行う価値があります。トンネルによって、SSH ログインが agent への唯一の入口になるためです。
プライベートなオーバーレイネットワーク経由でアクセスする
オーバーレイネットワークを使用すると、VPS と laptop に、自分のデバイスだけが参加するプライベートネットワーク上のアドレスを割り当てられます。一般的な選択肢は Tailscale です。この用途には、その serve command が適しています。tailscaled は VPS 上で実行し、localhost:3080 自体に接続します。そのため、harness は loopback 上で動作し、dsh の設定方法を変更する必要はありません。
tailscale serve --bg localhost:3080
tailscale serve statusこれで UI には、tailnet 内のマシン名を使用して HTTPS 経由でアクセスできます。public interface でポートを開く必要もありません。これには tailnet 用の HTTPS 証明書を有効にする必要があります。有効にしないと、serve は提示する証明書を持てません。停止する場合は、off を指定して同じ command をもう一度実行します。
tailscale serve --https=443 offserve を使用し、funnel は使用しないでください。Funnel は同じ target を public internet に公開するため、認証されていない agent runtime が公開ポート上で動作する状態に戻ります。この 2 つの command はほとんど同じに見えますが、動作は正反対です。どちらかを入力する前に、Tailscale Serve と Funnel の違いを確認してください。プライベートネットワークとしての Tailscaleでは、セットアップ自体を説明しています。
パスワードを確認するリバースプロキシ経由でアクセスする
この方法では、実際にポートをインターネットへ公開します。そのため、認証だけが第三者によるサーバー上でのコマンド実行を防ぎます。複数人が UI を使う必要があり、それぞれにトンネルを用意するのが現実的でない場合に選択します。
harness は 127.0.0.1:3080 上で動作します。nginx は同じホストで動作するため loopback に接続でき、証明書と password file を使用して 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;
}
}password file を作成して reload します。
sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/dsh.htpasswd you
sudo nginx -t && sudo systemctl reload nginxnginx -t の出力には、syntax is ok に続いて test is successful が表示されます。壊れたファイルで reload すると失敗し、実行中の設定はそのまま維持されます。そのため、無条件に restart せず、エラーを確認してください。
これらの proxy 設定のうち 3 行は装飾ではありません。Upgrade ヘッダーと Connection ヘッダーにより WebSocket の handshake が通過します。これらがないとページは読み込まれますが、更新されません。proxy_read_timeout 3600s はデフォルトの 60 秒を置き換えます。設定しない場合、長時間の agent 実行が応答の途中で切断され、UI が停止したように見えます。proxy_buffering off は、応答が完了するまで保持せず、到着した model output をそのまま browser に送信します。nginx reverse proxy の設定を行ごとに確認するでは残りの内容を説明し、nginx、Caddy、Traefik から選択するでは automatic certificate を使って同じ構成を実現する方法を説明します。
どの proxy を選択しても、firewall では 3080 を閉じたままにしてください。外部からの経路を、認証済みの proxy 経由だけにするためです。ufw firewall の基本でルールを説明しています。TLS 上の Basic authentication は最低限の対策であり、完成した security model ではありません。その password を持つ人は、サーバー上の shell を操作できます。可能であれば tunnel を優先してください。
dsh web が待ち受けるポートを変更する方法
--port はランチャーではなく、Web アプリケーションに属します。CLI のドキュメントには、次の例が直接示されています。
dsh --profile web --port 8080dsh 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 key と model endpoint の設定も保存されます。そのため、これらのファイルを編集する場合は、dsh の key、model、endpoint の設定も併せて確認してください。すべての設定レイヤーを統合した後、実際に有効な設定を確認するには、次を実行します。
dsh --dump-configwebserver plugin が公開するキーは host と port の2つだけです。port を 0 に設定すると、オペレーティングシステムに空きポートを要求します。ドキュメントでは「zero requests an OS-assigned port」と説明されています。これによりポート競合は確実に回避できますが、再起動のたびに番号が変わるため、トンネルには適していません。
dsh が「address already in use」で失敗するのはなぜですか?
別のプロセスがそのアドレスとポートをすでに使用しているため、カーネルが 2 つ目の bind を拒否します。Node では次のように表示されます。
Error: listen EADDRINUSE: address already in use 127.0.0.1:3080変更を加える前に、使用中のプロセスを確認します。
sudo ss -ltnp | grep 3080users:(("node",pid=1042,fd=21)) フィールドにプロセスとその PID が表示されます。通常は、停止したと思っていた以前の dsh が原因です。切断された tmux ウィンドウ内で、まだ動作していることもよくあります。kill 1042 でそのプロセスを停止するか、新しいインスタンスを別のポートで起動します。127.0.0.1:3080 と 0.0.0.0:3080 も互いに競合する点に注意してください。すべてのインターフェースに bind すると、loopback もすでに対象になるためです。
開発者向けプレビューのため、バージョンを固定します
README には明記されています。DeepSeek Harness は開発者向けプレビューで、現在も急速に更新されており、互換性を壊す変更が予定されています。この更新速度が導入をためらう理由であれば、dsh と Claude Code、Omnigent の比較で、同じ開発段階の異なる位置にある2つの harness と比較しています。
npx @deepseek-ai/dsh web は、実行するたびに公開済みの最新バージョンへ解決されます。1週間触れていなかったサーバーでも、次回の起動時には異なるフラグを持つ別の CLI が起動する可能性があります。再起動がアップグレードにならないよう、バージョンを固定します。
npx @deepseek-ai/dsh@0.1.0-rc.7 web2026年8月時点で、公開されているパッケージのバージョンは 0.1.0-rc.7 です。受け入れる前に、単独の npx が何を取得するかを確認してください。
npm view @deepseek-ai/dsh version固定したバージョンをインストールできない場合や、新しいバージョンを固定した後も npx が古いビルドを起動し続ける場合は、発生する install と version のエラーで、npx キャッシュの削除方法と、Node に含まれる npm の確認方法を説明しています。
プレビュー版では、リリースごとにランチャーと Web アプリケーションの間でフラグの配置が変わります。--port がこのガイドの説明どおりに動作しなくなった場合は、推測で対応せず、アプリケーション自体にフラグの一覧を表示させてください。
dsh --profile web --helpインストール本体、workspace の設定、model key については、VPS への DeepSeek Harness のインストールを参照してください。アクセス手順だけを簡潔に確認する場合は、VPS 上の dsh Web UI への接続で、理由の説明を省いたトンネルの手順を確認できます。
FAQ
ノート PC のブラウザーで http://127.0.0.1:3080 を開けないのはなぜですか?
127.0.0.1 は、コマンドを入力しているマシンを指すためです。DeepSeek Harness Web UI は VPS のループバックアドレスにバインドされているため、VPS 上のプロセスだけが接続できます。ノート PC には独立したループバックアドレスがあり、そこで port 3080 を待ち受けているプロセスはありません。ssh -N -L 3080:127.0.0.1:3080 you@your-vps で SSH 経由のポート転送を設定し、その後、ローカルで http://127.0.0.1:3080 を読み込みます。-L 引数の中央のフィールドはサーバー側で解決されるため、harness を指すことができます。
公開 VPS で dsh Web UI を 0.0.0.0 にバインドしても安全ですか?
いいえ。Web UI は、dsh を実行するユーザーの権限でシェルコマンドを実行し、ファイルを編集する agent の制御画面です。さらに、developer preview にはログイン画面がありません。パブリック IP のすべてのインターフェースにバインドすると、port 3080 に到達できる誰もがサーバー上でコマンドを実行できます。バインド先は 127.0.0.1 のままにし、ファイアウォールで 3080 を閉じ、パスワードを要求する SSH トンネル、プライベートなオーバーレイネットワーク、またはリバースプロキシを使用してください。
SSH セッションを閉じた後も dsh Web UI を実行し続けるにはどうすればよいですか?
フォアグラウンドの npx @deepseek-ai/dsh web はログインシェルの子プロセスであるため、そのシェルが終了すると停止します。tmux セッション内で起動し、Ctrl-b d でデタッチしてください。または、lingering を有効にした systemd user service として実行します。トンネルと harness は独立しています。harness 自体にログインより長く存続する親プロセスがある限り、実行中の harness に影響を与えず、SSH トンネルを何度でも切断して再構築できます。
nginx の背後で長時間の agent 実行を行うと、dsh Web UI が途中で停止するのはなぜですか?
nginx のデフォルトの proxy_read_timeout は 60 秒です。そのため、1 分間データを生成しない接続を nginx が閉じます。長時間の agent の処理では、この状態が容易に発生します。location ブロックに proxy_read_timeout 3600s; を設定してください。出力が到着した時点でブラウザーへストリームされるように proxy_buffering off; を追加し、WebSocket handshake が成功するように proxy_http_version 1.1; で Upgrade ヘッダーと Connection ヘッダーを渡します。これらのヘッダーがないとページは読み込まれますが、更新を受信できません。