DeepSeek HarnessをVPSで安全に使う方法
Linux VPSにDeepSeek Harnessを導入し、npmのバージョンを固定する方法を解説します。プラグインの役割と、3080番ポートのWeb UIへSSHトンネルで接続する手順も紹介します。
DeepSeek Harness とは
DeepSeek Harness(dsh)は、VPS(仮想プライベートサーバー)上で実行できる Node.js エージェントランタイムです。安全に運用するには、127.0.0.1 にバインドし、ブラウザーから SSH(セキュアシェル)トンネル経由で接続します。ターミナル上で動作するのではなく、3080 番ポートで Web UI(ユーザーインターフェース)を提供します。この Web サーバーには独自のパスワード認証がないため、3080 番ポートを公開すると、見つけた人なら誰でも、Linux ユーザーの権限でファイルを読み取り、コマンドを実行できるエージェントにアクセスできてしまいます。
DeepSeek はこれを 2026 年 8 月 13 日に MIT ライセンスでリリースし、npm パッケージ @deepseek-ai/dsh として公開しました。プロジェクトでは開発者向けプレビューと位置付けられており、互換性を破る変更が予想されると説明されています。以下に示すバージョン番号はすべて 2026 年 8 月時点のスナップショットです。そのため、重要なサーバーにコピーして導入する前に、リポジトリを確認してください。
この設計全体を貫く考え方は、すべてがプラグインであることです。モデルアダプター、ツールレジストリ、セッションログ、サンドボックス、スケジューラー、エージェントループ自体が、1 つの共有コンテキストに読み込まれるプラグインであり、どれも置き換えられます。プラグインが機能を追加するだけの特権的なコアは存在しません。これが Harness を試す価値のある理由であり、同時に、唯一の本質的なリスクが存在する箇所でもあります。
ハーネスはモデルではありません
ハーネスはエージェントのループを実行します。推論は別の場所にあるモデルで行われるため、API(application programming interface)キーか、自分でホストするモデルエンドポイントのアドレスを指定するまで何も動作しません。
UI の Settings、次に Models で設定します。カタログには、大手 API プロバイダー(DeepSeek、OpenAI、Anthropic)向けのカードが用意されており、キーを貼り付けて使えます。「Add a custom provider」は重要な選択肢です。プロバイダー ID、表示名、ベース URL、API プロトコル、認証情報を指定します。OpenAI-compatible プロトコルを使用するため、このプロトコルを実装するゲートウェイやローカルサーバーであれば利用できます。カスタムプロバイダーは OpenAI-compatible GET /models エンドポイントにも問い合わせて、モデル一覧を自動入力できます。
これで、同じ VPS 上のモデルをハーネスから利用できます。Ollama は http://127.0.0.1:11434/v1/ で OpenAI-compatible API を公開します。API key フィールドには任意の文字列を入力します。フィールドが必須で、その後は無視されるため、慣例として ollama を使用します。VPS に収まる小さなモデルでエージェントを十分に動かせるかどうかは、より難しい問題です。ローカルモデルサーバーとしての Ollama と vLLM の違いによって、その答えに必要な RAM の量が決まります。
UI に入力したキーは書き込み専用です。ハーネスはキーを $DSH_HOME/.credentials.yaml に保存し、settings.yaml には認証情報への参照だけを保持します。$DSH_HOME のデフォルト値は ~/.dsh です。このファイルはパスワードファイルとして扱ってください。実際にパスワードファイルだからです。読み取り権限を持つ人は、あなたの API 利用予算を消費できます。
インストール前に必要なもの
- SSH 接続が可能な Ubuntu 24.04 または別の現行 Linux が動作する VPS
- 22.x 系列の Node.js 22.19 以降、または Node.js 24 以降。これはプロジェクトがビルドとテストの対象としているバージョンです
rootではない通常のユーザーアカウント。エージェントはプロセスを起動したユーザーとしてシェルコマンドを実行するためです- プラグインをインストールする場合は PATH 上に
pnpm。プラグインコマンドは内部でこれを呼び出すためです - ファイアウォールとプロバイダーが別途提供するネットワークファイアウォールの両方で閉じた port 3080
Ubuntu 標準の nodejs パッケージはこの harness に必要なバージョンより古いため、apt install nodejs を使うのではなく、NodeSource または nvm から Node をインストールしてください。VPS が新規の場合は、何より先に SSH を強化することをお勧めします。これから使用するトンネルの安全性は、その背後にある SSH server の安全性に依存するためです。
VPS に DeepSeek Harness を 1 つのバージョンに固定してインストールする
node --version
npx @deepseek-ai/dsh@0.1.0-rc.6 webnpx はパッケージをダウンロードし、dsh バイナリを実行します。web は --profile web のエイリアスです。--profile web はブラウザーアプリケーションを起動し、プロセスは待ち受けているアドレスを出力します。デフォルトは http://127.0.0.1:3080 です。
バージョンを固定します。npx @deepseek-ai/dsh web は、実行した時点で latest タグが指しているバージョンを解決します。プロジェクトではすでに複数のリリース候補が公開されており、破壊的変更も予定されています。0.1.0-rc.6 は、13 August 2026 に latest が指していたバージョンです。バージョンを固定すると、今日セットアップしたサーバーが来月も同じように動作します。そのため、アップグレードを意図せず発生させるのではなく、判断して実施できます。
日常的に使用する場合は、起動のたびに再解決するのではなく、1 回だけインストールします。
npm install -g @deepseek-ai/dsh@0.1.0-rc.6
dsh --profile web --help2 行目も実行してください。ランチャーと Web アプリケーションでは、使用するフラグが異なるためです。dsh --help はランチャー独自のオプションを表示します。dsh --profile web --help は Web アプリケーションが受け付けるフラグを表示します。--port、--host、および繰り返し指定できる --trusted-host は、ここで確認できます。
次に、待ち受けているアドレスを確認します。
ss -tlnp | grep 3080ローカルアドレスの列が 127.0.0.1:3080 になっていることを確認します。0.0.0.0:3080 になっている場合、UI はインターネットから到達可能です。ほかの作業を行う前に、プロセスを停止してください。
ポート 3080 を決して公開してはいけない理由
Web サーバーには認証層がありません。設定で指定できるのは待ち受けホストと待ち受けポートだけであり、それがすべての公開面です。ループバック以外へのデプロイに対するアクセス制御は、別途指定する信頼済みホスト設定です。これはログイン画面ではありません。
次に、そのポートの背後にあるものを考えてください。エージェントはワークスペース内のファイルを編集し、shell コマンドを実行します。また、プロバイダーの認証情報はエージェントの隣のディスク上に保存されています。つまり、開放されたポート 3080 は、チャットインターフェースを備えたリモート shell です。起動したユーザーの権限で動作し、API key も付与されています。これを悪用するために、攻撃者が exploit を必要とするわけではありません。必要なのはポート番号だけです。ホストがオンラインになってから数時間以内に、スキャナーがポート番号を見つけます。
CLI(command line interface)もこの方針に従っています。0.1.0-rc.6 時点で、CLI は意図的に --host 0.0.0.0 をサポートしていません。起動せず、usage error で終了します。この拒否はセキュリティ機能です。これを削除する patch を探してはいけません。
トンネルが適さない場合でも、妥当な構成は他に 2 つあります。1 つ目は、ホストをプライベートなオーバーレイネットワークに接続する方法です。自分のデバイスだけがルーティングできるアドレスをホストに割り当てます。これは 自ホスト型 Headscale control server で実現できます。2 つ目は、ポート 3080 に到達する前にリクエストを認証する reverse proxy を前段に置く方法です。たとえば、Authentik single sign-on server で forward auth を実行します。前段に認証なしの reverse proxy を置いても、セキュリティ対策にはなりません。URL が長くなるだけです。
SSH トンネル経由で Web UI にアクセスする
これはサーバーではなく、ラップトップで実行します。
ssh -N -L 3080:127.0.0.1:3080 you@your-server-L はラップトップで 3080 番ポートを開き、そこへの接続を暗号化された SSH セッション経由で転送します。127.0.0.1:3080 の部分はサーバー上で解決されるため、接続はループバックからハーネスに到達します。これは、サーバー上で直接操作している場合と同じです。-N はリモートシェルを起動しないことを指定します。必要なのはポート転送だけだからです。
次に、ローカルのブラウザーで http://127.0.0.1:3080 を開きます。ラップトップですでに 3080 番ポートが使用中の場合は、左側の番号を変更します。ssh -N -L 3180:127.0.0.1:3080 you@your-server としてから、http://127.0.0.1:3180 にアクセスします。左側の番号はローカル側、右側の番号はサーバー側に対応するため、変更するのは左側だけです。
~/.ssh/config に保存し、以後は入力しないでください。
Host dsh
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519
LocalForward 3080 127.0.0.1:3080その後、ssh -N dsh でトンネルを開始します。ブラウザーに接続拒否が表示される場合、通常はトンネルは確立されていますが、接続先で待ち受けているサービスがありません。SSH はハーネスが実行中かどうかに関係なくポートを転送するためです。上記の ss コマンドでサーバーを確認してください。
ログアウト後もハーネスを実行し続ける
npxコマンドはシェルとともに終了します。systemd のユーザーサービスなら実行を継続でき、クラッシュや再起動の後もハーネスを再起動します。
loginctl enable-linger $USER
mkdir -p ~/.config/systemd/user
command -v dshenable-lingerが必要なのは、ユーザーサービスが通常、最後のセッション終了時に停止するためです。これがないと、トンネルを閉じた瞬間にハーネスも終了します。command -v dshが出力する絶対パスを unit に指定してください。systemd は、ログインシェルが構成する PATH を検索しないためです。
[Unit]
Description=DeepSeek Harness web UI
After=network-online.target
[Service]
Type=simple
WorkingDirectory=%h/projects/site
ExecStart=/usr/local/bin/dsh web
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.targetWorkingDirectoryは単なる装飾ではありません。dshプロセスは、起動元のディレクトリをデフォルトのファイルシステム上の場所として使用します。そのため、サービスを誤った場所で起動すると、エージェントのデフォルトのワークスペースも誤ったものになります。ワークスペースは UI で選択することもできます。
systemctl --user daemon-reload
systemctl --user enable --now dsh
systemctl --user status dsh起動を拒否する unit の原因は、ほぼ必ず誤った ExecStartパス、またはバイナリが拒否する Node バージョンです。journalctl --user -u dsh -n 50で原因を特定できます。同じパターンで、VPS 上で任意のコーディングエージェントを実行し続ける方法にも対応できます。発生する問題も同じです。
プラグインに許可される操作
プラグインは、共有コンテキストにサービス、型付きイベント、取り消し可能な作用を追加するモジュールです。特に、次の拡張ポイントを確認してください。
ctx.llmにモデルプロバイダーを登録するctx.toolsにモデル向けツールを追加するctx.shellの背後で動作する shell バックエンドを提供するctx.fsの背後でファイルシステムアクセスまたはポリシーを提供するctx.commandsに人間向けコマンドを登録するctx.jobsを通じてバックグラウンド処理を実行するctx.sandboxバックエンドで起動したプロセスをラップするagent/*およびtools/*イベントを通じてリクエストとツール呼び出しを傍受する- 永続的なセッション状態を拡張する
ctx.agentsを通じて UI を操作する
この一覧を攻撃者の視点で読んでください。プラグインはファイルシステム層と shell 層を提供でき、モデルが行うすべてのツール呼び出しの中間に入ることもできます。プラグインとこれらの接点の間に権限確認ダイアログはありません。プラグインは、ほかのすべてのコードと同じプロセスに読み込まれる通常の Node コードだからです。プラグインのインストールとは、エージェントの権限で第三者のコードを実行することです。エージェントの権限は、Unix ユーザーの権限そのものです。
これは、VPS 上のエージェントに MCP サーバーを接続するときに行う信頼判断と同じです。MCP は model context protocol を指します。また、VPS 上で coding agent を安全に実行する際に、モデルではなく実行アカウントから考え始める理由もここにあります。さらに、npm のサプライチェーン攻撃がサーバーに深刻な影響を与える理由も同じです。インストール手順そのものが侵害につながり、確認を求める仕組みはありません。
プラグインの入手元
プラグインはプロファイルに格納されます。プロファイルは $DSH_HOME 配下に保存される名前付きの構成で、デフォルトは ~/.dsh です。各プロファイルディレクトリには、そのプロファイルがインストールする out-of-tree プラグインが格納されます。CLI はプロファイルディレクトリを作業ディレクトリとして、引数をそのまま pnpm に渡してプラグインを管理します。
dsh plugin --profile web add github:deepseek-harness/turtle-ui
dsh plugin --profile web remove turtle-ui引数は変更されずに pnpm へ渡されるため、add、remove、update、why は通常の pnpm プロジェクトと同じように動作します。プラグインには npm パッケージまたは GitHub リファレンスを指定できます。最初に pnpm が PATH 上に存在している必要があります。Node 22 以降では、corepack enable pnpm がそれを PATH に配置します。
プラグインの探索には GitHub の topic を使用します。プラグイン作成者はリポジトリに dsh-plugin topic を追加します。この topic を参照すると、利用できるプラグインを見つけられます。topic は作成者が自分のリポジトリに付けるラベルです。第三者による審査や署名はありません。topic ページは stars の数で順位付けされますが、stars が示すのは安全性ではなく人気です。
次の4つの習慣で管理しやすくなります。多くのプラグインは10分で読める程度の規模なので、インストール前にソースを確認します。ブランチを追跡せず、正確なバージョンまたは commit を固定します。再構築しても問題ない VPS 上で、他の資産を所有していないユーザーとして harness を実行します。agent には専用の API key と利用上限を設定し、本番サービスで使用する key とは分離します。
1つの設計に決める前に比較したい場合は、Omnigent の multi-agent harness でも同じ問題に別の構成で対応できます。プラグインを使うと、両者のトレードオフが明確になります。
最初に発生する問題
Node が古すぎる。 プロジェクトは Node 22.19 と、22.x 系列のそれ以降のバージョン、または Node 24 以降を対象としており、CI でもこれらをテストしています。古いランタイムでは、対応していない構文や API をコードが使用しているため、起動時に失敗します。最初に node --version を実行してください。
ポート 3080 がすでに使用されている。 2 つ目の harness、停止し忘れたプロセス、または 3080 を使用する別のアプリケーションが原因です。ss -tlnp | grep 3080 で使用中のプロセスを特定し、停止するか、dsh web --port 3180 で harness を別の場所で起動してください。--port は Web アプリケーション用なので、web の後に実行します。
ブラウザーがトンネル経由で接続できない。 サーバーの公開アドレスではなく、127.0.0.1 にアクセスしたことを確認してください。転送されたポートはラップトップ上にのみ存在するためです。次に、サーバー上で harness が待ち受けていることを確認してください。SSH は接続先で応答するプロセスがあるかどうかに関係なく、ポート転送を設定します。
dsh plugin が直ちに失敗する。 このコマンドは pnpm のラッパーなので、pnpm バイナリがないと、プラグイン処理が始まる前に停止します。
agent がプロジェクトを認識できない。 workspace の既定値はプロセスの起動元ディレクトリです。そのため、WorkingDirectory がホームディレクトリになっている unit では、agent にホームディレクトリが渡されます。UI で workspace を選択するか、unit を修正して再読み込みしてください。
FAQ
DeepSeek Harness の Web UI を port 3080 で公開しても安全ですか?
いいえ。Web サーバーには独自のログイン機能がありません。また、その背後のエージェントはプロセスを起動したユーザーとしてファイルを編集し、shell コマンドを実行します。プロバイダーの API key も同じディスクに保存されます。リスナーは 127.0.0.1 に限定し、SSH トンネル経由でアクセスしてください。プライベートなオーバーレイネットワークを使用する方法もあります。各リクエストを port に到達する前に認証する reverse proxy も利用できます。version 0.1.0-rc.6 以降、CLI は --host 0.0.0.0 を拒否し、usage error で終了します。これは、この方法に対する作者の見解を示しています。
DeepSeek API key は必要ですか。それともローカルモデルを使用できますか?
どちらも使用できます。harness はモデルではなく runtime だからです。Settings、Models の順に開き、catalog provider のカードに key を貼り付けます。または、"Add a custom provider" を選択し、OpenAI-compatible protocol に対応する base URL を指定します。ローカルの Ollama サーバーは http://127.0.0.1:11434/v1/ で応答し、API key フィールドには任意の文字列を入力できます。key は $DSH_HOME/.credentials.yaml に保存されます。デフォルト値は ~/.dsh/.credentials.yaml です。
DeepSeek Harness の plugin をインストールすると、その plugin に何が与えられますか?
harness を実行している account の権限です。plugin は同じプロセスに読み込まれる Node code です。拡張ポイントには、shell backend、filesystem layer、tool registry、すべての tool call をラップする events が含まれます。plugin が独自に sandbox を提供しない限り、これらの接続点から plugin を隔離する仕組みはありません。インストールする前に source を読み、失って困るものを所有していないユーザーとして harness を実行してください。
どの version をインストールすべきですか。継続して動作しますか?
正確な version をインストールしてください。たとえば npx @deepseek-ai/dsh@0.1.0-rc.6 web です。これは、13 August 2026 時点で latest tag が指していた version です。プロジェクトは自らを developer preview と位置付け、互換性を壊す変更が予想されると説明しています。そのため、version を固定しない command は日によって異なる動作をする可能性があります。upgrade 前に repository を確認してください。version が 0 で始まる間は、config key と plugin interface が変更されることを想定してください。