OpenBot AI coworkersをVPSでセルフホストする方法
OpenBotをVPSでセルフホストする方法を解説します。botごとのコンテナとChromium、ゲートウェイのポリシー判定、監査ログ、必要なRAM容量を確認できます。
OpenBot AI coworkers をセルフホストすると得られるもの
自分で管理するハードウェア上で、1 台のゲートウェイサーバーと bot ごとに 1 つのコンテナを実行すると、OpenBot AI coworkers をセルフホストできます。各 bot コンテナには専用の Chromium ブラウザーと専用のワークスペースボリュームがあり、セッション間で保持されるブラウザープロファイルも備わっています。bot がコンピューター、ファイル、MCP (model context protocol) サーバー、または UI コンポーネントに対して行うすべての操作はゲートウェイを通過します。ゲートウェイは操作の実行前にポリシーと照合し、実行後に記録します。
OpenBot は CopilotKit が MIT ライセンスで github.com/CopilotKit/openbot に公開しています。最初のタグ付きリリース v0.0.1 は 17 August 2026 に公開されました。プロジェクトは自らを alpha で開発中と説明しています。完成度が初期段階にある設計として、慎重に扱ってください。
このアーキテクチャーの興味深い点は、同時にコストの大きい点でもあります。各 agent に 1 つずつブラウザーを割り当てるために必要なメモリ量は、多くの人が計画時に見落とします。そのため、ここではインストールの前にサイジングを行います。
ゲートウェイがすべてのアクションを決定する仕組み
3001 番ポートの API サーバーだけが、bot のコンピューターへの経路です。ブラウザー操作を実行する前に、ゲートウェイはページスナップショットから対象を解決し、コンテキストに対して CEL(Common Expression Language)のポリシールールを評価し、判定を保持する監査行を書き込みます。その後にのみ、コンテナを呼び出します。この処理の後に実行が失敗した場合は、2 行目を書き込みます。ドキュメントでは、この境界を明確に示しています。ポリシーを決定するのはコンピューターではなく、サーバーゲートウェイがアクションの境界です。
ポリシーはデフォルト拒否で、拒否ルールは許可ルールより先に評価されます。ルールの構文よりも、失敗時の方向が重要です。ポリシーがない場合は何も許可されません。ルールが壊れている場合も、それが拒否ルールか許可ルールかにかかわらず、ブロックする方向に失敗します。そのため、ポリシーのミスによって生じるのは、アカウント上で無制限に動作する bot ではなく、停止した bot です。
監査証跡は PostgreSQL に保存されるため、再起動後も維持されます。制御の引き渡しは computer.help_requested、computer.control_taken、computer.control_released として記録されます。これにより、bot が人間に操作を求めたことと、人間が操作を返したことを確認できます。Secret は値ではなく文字数として記録されます。ファイル操作では、内容ではなくパスとサイズが記録されます。ブラウザーを介さずに同じ制御境界を設けたい場合は、AI エージェントのアクションを承認の後に実行させるで、この限定的なケースを説明しています。
1 Bot あたりに必要な RAM とディスク
このプロジェクトが公開しているのは、arm64 上で 1 Bot を実行した場合の実測値です。OpenBot が提供するサイジング情報はこれだけです。1 つのアーキテクチャ上で 1 Bot を動かした結果なので、容量計画ではなく開始点として扱ってください。
The data behind this chart
[
{
"label": "Measured, one Bot",
"memory_gb": 0.55,
"disk_gb": 5.3,
"vcpu": 0.06
},
{
"label": "Documented minimum",
"memory_gb": 2,
"disk_gb": 8,
"vcpu": 1
},
{
"label": "Documented recommended",
"memory_gb": 4,
"disk_gb": 10,
"vcpu": 2
}
]1 Bot のピークメモリ使用量は 0.55 GB でした。文書化されている最小値は 2 GB、推奨値は 4 GB です。実測値と最小値の差は、負荷時に Chromium が使用する余裕です。ブラウザーのメモリ使用量は、プロセスが待機中かどうかではなく、開いているページ数に応じて変わるためです。アイドル時の CPU 使用量はほぼゼロで、実測範囲の上限でもコアの 0.06 に近い値です。購入時に重視すべきなのは CPU ではありません。ディスクです。イメージだけで 5.3 GB あり、推奨ボリュームは 10 GB です。Chromium に加えて、Playwright の Firefox と WebKit のバイナリも含まれるため、このサイズになります。
複数の Bot を同時に動かした場合のコストは、これらの数値だけでは分かりません。プロジェクトもその数値を公開していません。実環境で測定してください。最初に 1 Bot を起動し、ページを開いた実際のタスクを与え、動作中のコンテナを監視します。
docker stats --no-stream
free -mBot のコンテナについて MEM USAGE 列の値を 1 Bot あたりの数値として使用します。そこに gateway と PostgreSQL の使用量を加え、同時に存在させる Bot 数を 1 Bot あたりの数値に掛けます。アイドル状態の Bot もブラウザープロセスを保持するため、掛ける対象は動作中の Bot だけではなく、存在するすべての Bot です。この計算方法は、coding agent 用 VPS の RAM と CPU をサイジングする方法と同じです。ブラウザー部分については、VPS でエージェント用のヘッドレスブラウザーを実行する方法で説明しています。
小規模なプランでは、Chromium の設定も影響します。OpenBot は --disable-dev-shm-usage を付けて Chromium を起動するため、ブラウザーは /dev/shm ではなく /tmp に書き込みます。これにより、/dev/shm が小さいホストで発生するクラッシュを回避できます。その分、負荷は root ファイルシステムに移ります。イメージより推奨ディスク容量が大きい理由の 1 つもこれです。
VPS で OpenBot をセルフホストする方法
Docker、Bun 1.3 以降、CopilotKit Intelligence プロジェクト、モデル API キーが必要です。開発ドキュメントでは、サーバー上に lsof、python3、curl も用意されていることを前提としています。main ではなくタグ付きリリースを clone してください。アルファ版プロジェクトの main は予告なく変更されるためです。
git clone --branch v0.0.1 https://github.com/CopilotKit/openbot.git
cd openbot
cp .env.example .envIntelligence プロジェクトをプロビジョニングします。この 3 つのコマンドにより、ランタイムキーとライセンストークンが環境ファイルに書き込まれます。
npx --yes copilotkit@latest login
npx --yes copilotkit@latest project select
npx --yes copilotkit@latest license --write保存された認証情報を暗号化するキーを生成し、出力を .env に KEY_ENCRYPTION_KEY として設定します。同じファイルに OPENAI_API_KEY を追加するか、BOT_PROVIDER に anthropic または google を設定し、対応するキーを指定します。
openssl rand -base64 32続いてインストールして起動します。
bun install
bash scripts/start.shscripts/start.sh は Docker サービスを起動し、データベースマイグレーションを実行して、サーバーとアプリを起動し、それらのヘルスチェックを行います。完了すると、アプリはポート 3010、API はポート 3001 で応答します。このスクリプトはポート競合を報告し、すでに稼働している同じサービスはそのままにします。そのため、2 回実行しても安全です。
外部公開する前に、サーバー自体から確認してください。
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3010
ss -ltnp | grep -E ':(3010|3001|4100|4500|5432)'最初のコマンドで 200 と表示されれば、アプリは応答しています。2 つ目のコマンドでは、これらのポートがどのアドレスに bind されているかを確認できます。VPS では、この結果が重要です。127.0.0.1:3001 と表示される行は、そのサーバー内からのみアクセスできます。0.0.0.0:3001 と表示される行は、そのサーバーへルーティングできるすべてのホストからアクセスできます。
単一コンテナイメージ
デプロイメントドキュメントには、アプリ、API、Chromium を含み、3001 番ポートで提供する単一イメージも用意されています。
docker build -t openbot .
docker run -p 127.0.0.1:3001:3001 --env-file .env \
-e EMBEDDED_POSTGRES=on -v openbot-data:/var/lib/postgresql/data openbotEMBEDDED_POSTGRES=on はコンテナ内で PostgreSQL を実行し、起動時にマイグレーションを適用します。名前付きボリュームにより再デプロイ後も監査履歴が保持されます。これがないと、再ビルドのたびにその履歴が破棄されます。DATABASE_URL の接続先をマネージドデータベースに変更する場合は、そこでも vector 拡張機能を有効にする必要があります。RDS、Cloud SQL、Azure Database などのマネージドサービスはこの拡張機能をサポートしていますが、いずれも自動では有効化しません。そのため、新しいマネージドデータベースに対するマイグレーションは、vector のカラム型がまだ存在しないため失敗します。
データベースが外部にある場合は、リリース手順の一部としてマイグレーションを実行します。
docker run --rm --env-file .env openbot \
sh -c "cd /app/server && bun x drizzle-kit migrate --config=drizzle.config.ts"このイメージでは、ブラウザのポートを意図的に公開していません。また、supervisor も含めていません。supervisor には Docker socket が必要ですが、サーバーレスプラットフォームでは Docker socket を利用できないためです。supervisor がない場合、すべての bot が 1 つのブラウザと 1 セットのログイン情報を共有します。そのため、bot ごとのコンテナ運用に意味があった分離が失われます。bot ごとに別のログイン情報が必要であれば、COMPUTER_SUPERVISOR_URL と SUPERVISOR_TOKEN を設定して compose stack を実行し、そのトレードオフを受け入れられるホストで運用してください。Docker socket と通信できるプロセスは特権コンテナを起動できるため、実質的にホスト上の root になります。これは、コーディングエージェントに使い捨ての VM を割り当てるのと同じ考え方で、OpenBot 専用のマシンに置くべき理由になります。
OPENBOT_SINGLE_USER がラップトップ向けの設定である理由
.env.example には OPENBOT_SINGLE_USER=true が付属しています。この設定では、すべてのリクエストを 1 人の administrator として受け付け、サインインを完全に省略します。ラップトップでは、ポートに接続できるクライアントが自分だけなので便利です。VPS では、ポート 3010 に最初に接続した人が、暗号化された認証情報を保存し、アカウントにサインイン済みのブラウザーを操作できるシステムの administrator になります。
安全に運用する方法は 2 つあります。OPENBOT_SINGLE_USER=true を維持し、すべてのポートを 127.0.0.1 に bind して、SSH トンネルまたはプライベートネットワークインターフェース経由でのみアプリに接続します。
ssh -N -L 3010:127.0.0.1:3010 -L 3001:127.0.0.1:3001 you@your-vpsこの場合、アプリは自分のブラウザーで http://localhost:3010 にアクセスします。これは secure context として扱われるため、サインイン Cookie と、表示中の画面に必要なブラウザー機能の両方が動作します。もう 1 つの方法は、single-user mode を無効にして、実際の identity provider を設定することです。Google、Microsoft Entra、Okta、SAML、OIDC をサポートしています。どの provider でも、32 文字以上の BETTER_AUTH_SECRET、OAuth callback 用の公開 API base URL を指定する BETTER_AUTH_URL、INITIAL_ADMIN_EMAILS、TRUSTED_ORIGINS が必要です。provider の認証情報は完全に設定してください。設定が不完全な provider があると、open access にフォールバックせず、起動が停止します。
アプリに public name で接続できる場合は、その前段に TLS (transport layer security) を配置します。localhost 以外で plain http:// により配信されるページは secure context ではありません。そのため、Secure のマークが付いた Cookie は保存されず、OpenBot のバグに見える形でサインインに失敗します。
下位ポートをファイアウォールで遮断する
OpenBot のセキュリティに関する注意事項では、下位サービスのエンドポイントはトークンで保護されていること、非公開に保つべきこと、ゲートウェイの迂回に使用してはならないことが説明されています。トークンは2つ目の防御です。1つ目は、ポートにまったく到達できないようにすることです。
agent-computer は 4100 で待ち受け、COMPUTER_TOKEN を必要とします。bot のエンドポイントは 4200 と 4201 で待ち受けます。supervisor はホスト上の 4500 と、そのコンテナ内の 4300 で待ち受けます。PostgreSQL は 5432 で待ち受けます。これらをパブリックインターフェイスに公開してはなりません。シングルユーザー構成では、app と API も公開する必要はありません。
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status verboseここには、ファイアウォールだけで十分だと思う人が陥りやすい落とし穴があります。-p 3001:3001 でコンテナのポートを公開すると、Docker は DNAT ルールを設定します。そのため、トラフィックは FORWARD の経路で処理され、ufw のデフォルト拒否が適用される INPUT チェーンを通過しません。ufw status が Status: active と表示していても、ポートは開いたままです。公開ポートは、マッピング自体でループバックにバインドします。たとえば -p 127.0.0.1:3001:3001 のように指定するか、compose ファイルでホストアドレスを設定します。確認には ufw status ではなく ss -ltnp を使用します。
OpenBot はオフライン構成ではありません
デプロイを計画する前に、この点を明確にしてください。OpenBot は CopilotKit Intelligence プロジェクトに依存しています。このプロジェクトは、永続的なスレッドと会話メモリをサーバーの外部に保持します。サーバーは起動時に INTELLIGENCE_API_URL、INTELLIGENCE_GATEWAY_WS_URL、INTELLIGENCE_API_KEY、COPILOTKIT_LICENSE_TOKEN を検証します。4 つすべてが同時に存在しないと、起動に失敗します。2026 年 8 月時点では無料プランを利用できます。Intelligence 自体もセルフホストできるため、quickstart の手順より多くの作業は必要ですが、完全にローカルでデプロイできます。
モデルが 2 つ目の外部依存関係です。モデルは同梱されていません。BOT_PROVIDER は openai、anthropic、google を受け付けます。OPENAI_BASE_URL を使用すると、OpenAI 用の接続先を互換性のある任意のエンドポイントに指定できます。トークンを自分のハードウェア内に留めたい場合は、VPS で Ollama を実行して LLM をセルフホストする構成が該当します。ブラウザー操作はモデルに大きな負荷をかけるため、採用を決める前に、実際のタスクでローカルモデルをテストしてください。
現時点では 1 レプリカで実行
ゲートウェイはページのスナップショットをサーバープロセスのメモリにキャッシュします。2 つのレプリカを使用すると、一方のプロセスが取得したスナップショットをもう一方のプロセスから参照できません。そのため、要素が見つからないというエラーがランダムに見える形で断続的に発生し、操作が失敗します。デプロイメントのドキュメントには、1 レプリカで実行し、プラットフォームの最大インスタンス数を 1 に固定するよう明記されています。この制限は、スナップショットのキャッシュ先がデータベースに移行されるまで必要です。それまでは、ボックスを追加するのではなく、サーバーのリソースを増やして OpenBot をスケールします。ボット間の分離は、引き続きボットごとのコンテナによって実現されます。これは、セルフホスト型エージェントのサンドボックスが 1 つのエージェントのミスを他のエージェントから隔離するのと同じです。
障害の種類と確認できる内容
.env の入力直後に起動が終了する。 サーバーは何も提供する前に設定を検証します。Intelligence ブロックが不完全である場合、KEY_ENCRYPTION_KEY がない場合、または client ID だけが設定されて secret がない OAuth provider を使用している場合、いずれも静かに機能を縮退せず、起動を停止します。最初のエラーを確認し、そのフィールドだけを修正して、再度起動してください。
管理対象データベースでマイグレーションが失敗する。 vector 拡張機能はデフォルトで有効になっていないため、マイグレーションが PostgreSQL に認識されないカラム型に到達します。superuser として接続し、CREATE EXTENSION vector; を実行してから、マイグレーションの手順を再実行してください。
アプリケーションは読み込まれるが、サインイン状態が維持されない。 公開アドレスで平文の http:// を使用しています。これは secure context ではないため、Secure cookie が破棄されます。前段に TLS を配置するか、SSH tunnel を使用して、ブラウザーから localhost として認識されるようにしてください。
分離する想定だった bot でログイン情報が共有される。 supervisor が実行されていないため、bot ごとの computer がなく、すべての bot が共有 browser を使用しています。COMPUTER_SUPERVISOR_URL が設定されていることと、supervisor が Docker socket に接続できることを確認してください。
bot が停止し、支援を求める。 これは設計どおりの動作です。監査証跡に computer.help_requested が記録されるため、ライブ画面で操作を引き継ぎます。この handover は双方に記録されます。
FAQ
OPENBOT_SINGLE_USER を VPS へのデプロイで有効にしたままにしても安全ですか?
ゲートウェイにインターネットから接続できない場合に限り安全です。OPENBOT_SINGLE_USER=true はサインインなしで、すべてのリクエストを 1 人の administrator として受け入れるため、ポートを開ける人は誰でもデプロイメント、その保存済み認証情報、サインイン済みブラウザーを操作できます。すべてのポートを 127.0.0.1 にバインドし、SSH トンネルまたはプライベートネットワークインターフェース経由でアプリに接続する構成であれば許容できます。パブリックインターフェースでは無効にし、Google、Microsoft Entra、Okta または OIDC と BETTER_AUTH_SECRET、BETTER_AUTH_URL、INITIAL_ADMIN_EMAILS、TRUSTED_ORIGINS を設定してください。
OpenBot の bot 1 台にはどの程度の RAM が必要ですか?
プロジェクトが公開している単一の Bot に関する数値では、arm64 でのピークメモリは 0.55 GB です。文書化されている最小値は 2 GB、推奨値は 4 GB です。複数の bot を同時に実行した場合の公開値はありません。各 bot が専用の Chromium を保持するためです。実際のタスクで bot 1 台を実行し、docker stats でそのコンテナのメモリ使用量を確認します。ゲートウェイとデータベースの分を加え、同時に存在する bot の想定数を掛けてください。
OpenBot をセルフホストする場合、CopilotKit のアカウントは必要ですか?
はい。OpenBot は永続的なスレッドとメモリに CopilotKit Intelligence プロジェクトを使用します。Intelligence API URL、ゲートウェイの WebSocket URL、API key、license token をすべて設定しないと、サーバーは起動しません。2026 年 8 月時点では無料プランを利用できます。また、Intelligence はセルフホストできるため、追加の作業によってホスト型の依存関係をなくせます。OpenBot にはモデルが同梱されていないため、自分でモデル API key も用意します。
なぜ各 bot に専用のブラウザーが割り当てられ、共有されないのですか?
ブラウザープロファイルが ID だからです。ブラウザーを共有すると Cookie とセッションも共有されるため、ある bot がアカウントにサインインすると、すべての bot がそのアカウントにサインインした状態になります。bot ごとのコンテナにより、各 coworker に専用のプロファイルとログイン情報を割り当てられます。代わりにメモリを消費します。bot ごとに Chromium が必要になり、サイジング上で最大の項目になるためです。
ファイアウォールで開放すべき OpenBot のポートはどれですか?
下位レベルのポートは開放しません。4100 の agent-computer、4200 と 4201 の bot エンドポイント、4500 の supervisor、5432 の PostgreSQL はすべてプライベートに保ちます。プロジェクトはこれらを token で保護しており、いずれにしても到達不能にするよう求めています。人が開く必要のあるものだけを公開してください。また、-p 3001:3001 で公開されたコンテナポートは、ufw の default-deny ルールに関係なく到達可能であることに注意してください。Docker の DNAT ルールがそのトラフィックを INPUT ではなく FORWARD の経路に入れるためです。