OpenCodeサーバーのセキュリティ:opencode serveとopencode webを安全に動かす方法
opencode serveはファイルの読み取りやシェルコマンドの実行ができるHTTP APIを公開します。localhostに留める、パスワードを設定する、TLSを追加する、リモートから安全に接続する方法。
- CLI
- 0.2.17
- プレビュー ref
- a2c45c8
要点
opencode serve と opencode web はHTTPサーバーを起動し、そのAPIはファイルの読み取り、シェルコマンドの実行、設定の変更、プロバイダーの認証情報の設定ができます。このサーバーへのアクセスは、そのマシンへのシェルアクセスと同じものとして扱ってください。
安全な構成を重要度順に:
- デフォルトのホスト名
127.0.0.1のままにする。0.0.0.0へのバインドや--mdnsは、自分で管理しているネットワークでだけ使います。 - 自分のマシン以外から到達できる場合は、必ず
OPENCODE_SERVER_PASSWORDを設定する。 OpenCodeのドキュメントによると、これがないとサーバーは保護されていません。 - 通信がネットワークをまたぐならTLSを前段に置く。 平文HTTP上のBasic認証では、経路上の誰でも読める形でパスワードが送られます。
- 公開ポートではなく、プライベートネットワークやトンネル経由で接続する。 SSHやTailscaleなどです。
--corsは最小限に。 自分で運用しているオリジンだけを追加します。
問題
OpenCodeのクライアント・サーバー構成は強みの1つです。TUIはローカルのサーバーと通信するので、ブラウザ、IDEプラグイン、スクリプト、別のコンピューターからも操作できます。ドキュメントでは、それをフラグ1つで行う方法が紹介されています。
opencode web --port 4096 --hostname 0.0.0.0自宅のノートPCならこの1行で問題ありません。しかしカフェのネットワーク、共有オフィスのLAN、セキュリティグループが開いたクラウドVMでは、コーディングエージェントの制御APIを、そのポートに到達できる全員に公開することになります。対策はいくつかの設定だけですが、スマートフォンをつなぐことだけが目的だと見落としがちです。
OpenCodeサーバーが公開するもの
OpenCodeのサーバーのドキュメント(2026年10月26日時点)によると、APIには次のものが含まれます。
| エンドポイント | 内容 |
|---|---|
POST /session/:id/shell | シェルコマンドを実行 |
POST /session/:id/message | エージェントにプロンプトを送信 |
GET /file/content?path= | ファイルを読み取り |
GET /find?pattern= | ファイルの内容を検索 |
PATCH /config | 設定を更新 |
PUT /auth/:id | プロバイダーの認証情報を設定 |
POST /mcp | MCPサーバーを追加 |
POST /session/:id/permissions/:permissionID | 権限リクエストに回答 |
GET /doc | OpenAPI 3.1の仕様 |
これらを呼び出せる人は、そのマシンのターミナルであなたができることを何でもでき、エージェントの権限確認にあなたとして回答できます。以下のすべてはこの脅威モデルを前提にしています。
OpenCodeサーバーのデフォルト
サーバーのドキュメントより:
| フラグ | デフォルト | 備考 |
|---|---|---|
--port | 4096 | |
--hostname | 127.0.0.1 | ループバックのみ |
--mdns | false | 有効にするとホスト名が 0.0.0.0 になり、opencode.local をアドバタイズする |
--cors | なし | 許可する追加のブラウザオリジン |
デフォルトのままなら安全です。引数なしで opencode を実行すると、TUIと、ランダムなポートとホスト名のサーバーが起動し、TUIはそれをバックエンドとして使います。リスクはホスト名を変えたりmDNSを有効にしたりしたときに生じます。
ステップ1:必要がなければOpenCodeをlocalhostに留める
クライアントが同じマシンにしかないなら、--hostname は指定しません。
opencode serve待ち受けを確認します。
# Linux
ss -ltnp | grep 4096
# macOS
lsof -nP -iTCP:4096 -sTCP:LISTEN0.0.0.0:4096 や *:4096 ではなく、127.0.0.1:4096 になっているべきです。
ステップ2:OpenCodeサーバーにパスワードを設定する
サーバーは環境変数によるHTTP Basic認証に対応しています。opencode serve と opencode web の両方に適用されます。
export OPENCODE_SERVER_PASSWORD="$(openssl rand -base64 32)"
opencode serveユーザー名のデフォルトは opencode です。変えるには OPENCODE_SERVER_USERNAME を設定します。Webのドキュメントには注意書きがあり、OPENCODE_SERVER_PASSWORD が設定されていないとサーバーは保護されず、ローカルで使うなら問題ないが、ネットワークからアクセスするなら設定すべきだとしています。
パスワード保護されたサーバーにTUIをアタッチするには:
opencode attach http://10.20.30.40:4096 --password "$OPENCODE_SERVER_PASSWORD"--password のデフォルトは OPENCODE_SERVER_PASSWORD なので、そのシェルで変数が設定されていればフラグは省略できます。
パスワードはシェルの履歴や、共有リポジトリのdotfilesに残さないでください。パスワードマネージャーや、自分だけが読めるファイルを起動時に読み込む方法が使えます。
ステップ3:OpenCodeサーバーの前段にTLSを追加する
Basic認証はリクエストのたびに認証情報を送ります。エンコードされていても暗号化はされていません。完全には信頼できないネットワーク上の平文HTTPでは、パスワードがないのと同じです。選択肢:
-
リバースプロキシ。 CaddyやnginxでHTTPSを終端し、
127.0.0.1:4096に転送します。OpenCodeサーバーはループバックのままです。 -
SSHトンネル。 新しいポートを開けずに接続を暗号化します。
ssh -N -L 4096:127.0.0.1:4096 you@serverその後、自分のマシンでクライアントを
http://127.0.0.1:4096に向けます。 -
プライベートネットワーク。 TailscaleやWireGuardはデバイス間の通信を暗号化します。そのネットワーク上の他の機器もポートに到達できるので、パスワードとも組み合わせてください。
トンネルの選択肢はCloudflare Tunnel vs Tailscale Funnel vs ngrokで比較しています。ポートを公開インターネットに出すものには注意してください。公開URLとBasic認証の組み合わせは、パスワードだけで守られたシェルです。
ステップ4:OpenCodeのポートに到達できる相手を絞る
- クラウドVMでは、 セキュリティグループで4096を開けないでください。SSHやプライベートネットワーク経由で接続します。
- 自宅サーバーでは、 ルーターのポートフォワーディングに含めないでください。
- mDNSを使う場合は、
--mdnsが0.0.0.0にバインドすることを忘れないでください。自宅のネットワークでは便利ですが、共有Wi-Fiには向きません。 - ホストのファイアウォールでは、 必要なアドレスからだけポートを許可します。
ステップ5:CORSを最小限に保つ
--cors はサーバーの呼び出しを許可するブラウザオリジンを追加します。追加したオリジンはそれぞれ、サーバーに到達できるブラウザからエージェントと通信できるスクリプトを持つWebサイトです。自分で運用しているフロントエンドだけを、正確なオリジンで追加してください。
opencode serve --cors https://app.example.comステップ6:マシン上での被害範囲を小さくする
アクセス制御が適切でも、サーバーはあなたの権限で動きます。ミスの影響を抑える習慣:
- 共有サーバーでは、必要なリポジトリにだけアクセスでき、本番の認証情報を持たない別ユーザーでOpenCodeを動かします。
- シェルコマンドの権限ルールは厳しく保ちます。リモートのクライアントが「許可」と答えても、許可しているのはあなたです。
- 使い終わったらサーバーを止めます。何週間も動き続ける
opencode serveは、常に開いている入口です。
ポートを開けずにスマートフォンからOpenCodeを使う
0.0.0.0 にバインドするよくある理由は、別のデバイスからOpenCodeを使うことです。これはOpenCodeサーバーをループバック以外で待ち受けさせなくても実現できます。
サーバーを公開せずにスマートフォンからOpenCodeを操作したいなら、HappierはClaude Code、Codex、OpenCodeなどのエージェントをスマートフォン、デスクトップ、Webからクロスデバイスで実行・オーケストレーションできるオープンソースアプリです。
Happierが管理するOpenCodeサーバーの扱い:
- ループバックのみ。 Happierは管理下のOpenCodeサーバーを
--hostname=127.0.0.1と空いているローカルポートで起動し、アドレスがループバックの管理サーバーだけを再利用します。 - 管理サーバーごとにパスワード。
OPENCODE_PASSWORDかOPENCODE_SERVER_PASSWORDを設定していればそれを使います。そうでなければサーバーごとに生成し、~/.happier/opencode/managed-servers/の下にある所有者だけが読める状態ファイルに保存します。 - パスワードはマシンの外に出ません。 Happierのドキュメントによると、パスワードは環境変数経由でサーバーに渡され、HappierのOpenCodeサーバーログには書かれず、リモートのエンドポイントにも送られません。
- リモートアクセスはOpenCodeのポートではなくHappierを経由します。 スマートフォン、デスクトップ、WebのアプリはリレーをはさんでコンピューターのHappierデーモンと通信します。セッションの内容はデフォルトでエンドツーエンド暗号化されます。セッションIDやタイムスタンプなどのメタデータは暗号化されません。リレーをセルフホストすることもできます。
OpenCodeの権限確認はスマートフォンに届き、そこで回答します。happier attach <session-id> で、同じマシン上でそのセッションのOpenCode TUIを開き直せます。セットアップはスマートフォンからHappierを使う方法にあります。HappierはGitHubで公開されており、こちらからダウンロードでき、Discordもあります。
トラブルシューティング
すべてのリクエストが401になる
クライアントがサーバーの期待するパスワードを送っていません。クライアントの OPENCODE_SERVER_PASSWORD がサーバーと一致しているか、OPENCODE_SERVER_USERNAME を変えた場合はユーザー名も一致しているか確認します。新しいOpenCodeのリリースには別の変数名を読むものもあるので、opencode --version を確認し、そのリリースのドキュメントと照らし合わせてください。
他のマシンからサーバーに到達できてしまう
ss -ltnp か lsof で待ち受けアドレスを確認します。0.0.0.0 や * なら、コマンドやサービスファイルに --hostname 0.0.0.0 か --mdns がないか探します。
カスタムのフロントエンドからのリクエストをブラウザがブロックする
フロントエンドの正確なオリジンを --cors で追加します。ワイルドカードは使わないでください。
SSH経由で opencode attach が接続できない
トンネルが張られていて、リモート側の 127.0.0.1:4096 を指しているか確認します。リモートのIPではなく、ローカルの http://127.0.0.1:4096 にアタッチします。
よくある質問
opencode serveはデフォルトで安全?
127.0.0.1 で待ち受けるので、他のマシンからは到達できません。同じマシンのプロセスなら到達できます。OPENCODE_SERVER_PASSWORD がなければ認証はありません。
opencode webも同じパスワードを使う?
はい。OpenCodeのドキュメントによると、OPENCODE_SERVER_PASSWORD は opencode serve と opencode web の両方に適用されます。
OpenCodeをインターネットに公開できる?
できますが、APIはシェルコマンドを実行します。どうしても必要なら、TLS、強いパスワード、できればVPNやID認識型プロキシなどのアクセス層を前段に置いてください。
OpenAPI仕様のエンドポイントはリスクになる?
/doc はAPIを説明するものです。それ自体がアクセスを与えるわけではありませんが、攻撃対象を調べやすくします。他と同じパスワードで保護されます。