在 VPS 自行託管 OpenBot AI 協作者
了解如何在 VPS 自行託管 OpenBot:每個 AI 協作者使用獨立 container、Chromium 與 workspace,並由 gateway 依政策核准、記錄每項操作,同時評估 RAM 成本。
自行託管 OpenBot AI 協作者的成果
您可以在自己控管的硬體上執行 1 台 gateway server,以及每個 bot 各自使用 1 個 container,藉此自行託管 OpenBot AI 協作者。每個 bot container 都包含自己的 Chromium browser 與 workspace volume,並使用可在工作階段之間保留狀態的 browser profile。bot 在 computer、file、MCP(model context protocol)server 或 UI component 上執行的每個動作,都會先經過 gateway,由 gateway 依據 policy 檢查後才執行,並在執行後記錄。如果 gateway 所包裝的 agent loop 對您仍不熟悉,從頭學習 AI 代理程式中的分階段路徑,會先引導您自行撰寫一個簡易版本,再讓 bot 使用 browser 與您的登入資訊。
OpenBot 由 CopilotKit 以 MIT license 發布,程式碼位於 github.com/CopilotKit/openbot。第一個標記版本 v0.0.1 於 17 August 2026 發布,專案將自身描述為 alpha,且仍在積極開發中。請將它視為設計完整但仍存在早期版本限制的專案。
這種架構最值得注意的部分,也是成本最高的部分。每個 agent 都需要一個 browser,這是多數人規劃時最容易忽略的記憶體成本。因此,本指南會先進行容量規劃,再開始安裝。
閘道如何決定每項操作
連接埠 3001 上的 API 伺服器是通往 bot 電腦的唯一路徑。在執行瀏覽器操作前,閘道會先從頁面快照解析目標,再根據內容評估 CEL(common expression language)政策規則,將決策寫入稽核資料列,最後才呼叫容器。若執行在此之後失敗,閘道會再寫入第二筆資料列。文件明確說明這項邊界:電腦不負責決定政策,伺服器閘道才是操作邊界。
政策預設拒絕,且拒絕規則會在允許規則之前評估。失敗方向比規則語法更重要。缺少政策時不允許任何操作;規則損壞時,無論是拒絕規則或允許規則,都會以封鎖作為失敗結果。因此,政策中的錯誤會讓 bot 卡住,而不是讓 bot 未受限制地操作你的帳戶。這一層負責管控 bot 的操作,不負責管控它讀取的內容。因此,帶有要求代理程式執行指示的頁面仍是另一項問題;這與你在 將自有 SearXNG 執行個體的結果交給代理程式時面對的是相同的 prompt injection 攻擊面。
稽核軌跡儲存在 PostgreSQL,因此重新啟動後仍會保留。控制權交接會記錄為 computer.help_requested、computer.control_taken 和 computer.control_released;透過這些記錄,你可以看到 bot 要求人工介入,也可以看到人工將控制權交還。如果是 secret,只會記錄字元數,絕不記錄其值。檔案操作會記錄路徑與大小,絕不記錄內容。如果你需要在沒有瀏覽器的情況下,採用相同的控制邊界,在 AI 代理程式操作前設置核准流程涵蓋這種較狹義的情境。
Bot 所需的 RAM 與磁碟空間
該專案公布了 arm64 上單一 Bot 的實測數據。這是 OpenBot 唯一提供的容量規劃數字,描述的是單一架構上的單一 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
}
]單一 Bot 的峰值記憶體實測為 0.55 GB,文件記載的最低需求為 2 GB,建議值則為 4 GB。實測值與最低需求之間的差距,是為 Chromium 在負載下成長所保留的空間,因為瀏覽器的記憶體用量取決於目前開啟的頁面,而不是閒置時的程序用量。閒置 CPU 幾乎為零,在實測範圍上限僅占 0.06 個核心,因此真正需要規劃的是磁碟,而不是 CPU。映像檔本身就占用 5.3 GB,相較之下建議的 volume 容量為 10 GB。映像檔之所以這麼大,是因為其中除了 Chromium,還包含 Playwright 的 Firefox 與 WebKit binary。
這些數據無法告訴你同時執行多個 Bot 需要多少資源,而該專案也沒有公布相關數值。文件記載的最低需求,是專案認為適合公布的數字,不代表有人在負載下實際觀察到的數值。這也是為何 選擇 PhotoPrism 或 Immich 時,應比較實測的 RAM 下限,而不是文件公布的數值。請自行測量。啟動一個 Bot,讓它執行包含開啟頁面的實際工作,並在執行期間監控 container。
docker stats --no-stream
free -m將 Bot 的 container 所在的 MEM USAGE 欄位作為每個 Bot 的資源數值,再加上 gateway 與 PostgreSQL 的資源需求,最後將每個 Bot 的數值乘以預期同時存在的 Bot 數量。閒置中的 Bot 仍會保留 browser process,因此乘數適用於所有已存在的 Bot,而不只是忙碌中的 Bot。計算方式與 規劃 coding agent VPS 的 RAM 與 CPU 相同;其中瀏覽器部分則詳見 在 VPS 上為 agents 執行 headless browser。
其中一項 Chromium 細節會影響小型方案。OpenBot 使用 --disable-dev-shm-usage 啟動 Chromium,因此瀏覽器會寫入 /tmp,而不是 /dev/shm。這可避免在 /dev/shm 較小的主機上發生當機,但會將壓力轉移到 root filesystem。這也是建議磁碟容量大於映像檔大小的另一個原因。
如何在 VPS 上自架 OpenBot?
你需要 Docker、Bun 1.3 或更新版本、CopilotKit Intelligence 專案,以及模型 API key。開發文件也要求伺服器上有 lsof、python3 和 curl。請複製標記版本,而不是 main,因為 alpha 專案中的 main 可能在未事先通知的情況下變更。
git clone --branch v0.0.1 https://github.com/CopilotKit/openbot.git
cd openbot
cp .env.example .env佈建 Intelligence 專案。以下 3 個命令會將 runtime key 和 license token 寫入環境檔案。
npx --yes copilotkit@latest login
npx --yes copilotkit@latest project select
npx --yes copilotkit@latest license --write產生用於加密已儲存憑證的 key,並將輸出以 KEY_ENCRYPTION_KEY 的形式放入 .env。在同一個檔案中加入你的 OPENAI_API_KEY,或將 BOT_PROVIDER 設為 anthropic 或 google,並提供相符的 key。
openssl rand -base64 32接著安裝並啟動。
bun install
bash scripts/start.shscripts/start.sh 會啟動 Docker 服務、執行資料庫 migration、啟動 server 和 app,並檢查其健康狀態。完成後,app 會在 port 3010 回應,API 則在 port 3001 回應。此 script 會回報 port 衝突,並讓已在執行且相符的服務維持運作,因此重複執行是安全的。
在對外公開前,先直接從 server 本身檢查。
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 表示 app 正在提供服務。第二個命令會顯示這些 port 綁定的位址;對 VPS 而言,這才是重要結果。若某行顯示 127.0.0.1:3001,表示服務僅限本機使用。若某行顯示 0.0.0.0:3001,表示任何能將網路流量路由至該 server 的人都可以連線。
單一容器映像
部署文件也提供單一映像,其中包含應用程式、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,並在啟動時套用 migration。具名 volume 會在重新部署後保留稽核紀錄;沒有它,每次重新建置都會捨棄這些紀錄。若改用代管資料庫連線至 DATABASE_URL,就必須在該資料庫啟用 vector extension。RDS、Cloud SQL 與 Azure Database 等代管服務都支援此 extension,但不會替你啟用。因此,對全新的代管資料庫執行 migration 會失敗,因為其中尚未存在 vector 欄位型別。
資料庫位於外部時,請將 migration 作為 release 步驟執行。
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,而 serverless 平台不提供該 socket。沒有 supervisor 時,所有 bot 共用同一個瀏覽器,也共用同一組登入資訊,因此失去原本值得為每個 bot 執行獨立容器的隔離性。若你需要讓每個 bot 使用不同登入資訊,請在可接受此取捨的主機上,設定 COMPUTER_SUPERVISOR_URL 與 SUPERVISOR_TOKEN 後執行 compose stack。能夠與 Docker socket 通訊的程序可以啟動具備特殊權限的容器,因此實務上等同於取得主機的 root 權限。這也是應將 OpenBot 保留在專用主機上的充分理由,與提供 coding agents 可拋棄的 VM的原則相同。
為什麼 OPENBOT_SINGLE_USER 是筆記型電腦設定
.env.example 隨附 OPENBOT_SINGLE_USER=true。此設定會將每個請求視為同一位管理員,並完全略過登入。在筆記型電腦上,這很方便,因為只有你能連線到該埠。在 VPS 上,這表示第一個連線到 3010 埠的人,就能成為該系統的管理員,而系統會儲存加密的憑證,並操作已登入你帳戶的瀏覽器。
有兩種可行的執行方式。保留 OPENBOT_SINGLE_USER=true,將每個埠繫結至 127.0.0.1,並且只能透過 SSH tunnel 或私有網路介面存取應用程式。
ssh -N -L 3010:127.0.0.1:3010 -L 3001:127.0.0.1:3001 you@your-vps此時,你可以在自己的瀏覽器中透過 http://localhost:3010 存取應用程式。這屬於安全內容環境,因此登入 cookie 以及即時畫面所需的瀏覽器功能都能正常運作。另一種方式是關閉單一使用者模式,並設定正式的身分識別提供者。支援 Google、Microsoft Entra、Okta、SAML 和 OIDC。任何提供者也需要長度至少為 32 個字元的 BETTER_AUTH_SECRET、將 BETTER_AUTH_URL 設為 OAuth callback 使用的公開 API base URL、INITIAL_ADMIN_EMAILS 及 TRUSTED_ORIGINS。提供者憑證必須完整,因為設定不完整的提供者會使啟動失敗,不會退回開放存取模式。若你新增帳戶的原因,是團隊中的每個人都需要自己的 agent,而不是自己的瀏覽器,OneCLI 從一開始就是以這種架構為基礎,每個人都有一個隔離的 agent,而模型金鑰集中由單一 gateway 管理。
如果應用程式可透過公開名稱存取,請在前方配置 TLS(傳輸層安全性)。除了 localhost 以外,若頁面是透過純 HTTP 的 http:// 提供,便不屬於安全內容環境,因此標記為 Secure 的 cookie 不會儲存,登入也會失敗,表面上看起來像是 OpenBot 的錯誤。
封鎖低層服務連接埠
OpenBot 的安全說明指出,低層服務端點受到 token 保護,應保持私有,也不應用來繞過 gateway。Token 是第二層保護。第一層保護則是讓連接埠完全無法連線。
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 預設 deny 所管控的 INPUT chain。即使 ufw status 仍顯示 Status: active,連接埠依然保持開放。應直接在 mapping 中將發布的連接埠綁定至 loopback,例如 -p 127.0.0.1:3001:3001,或在 compose 檔案中設定主機位址。請使用 ss -ltnp 驗證,不要使用 ufw status。
OpenBot 並非離線堆疊
請在規劃部署前先確認這點。OpenBot 相依於 CopilotKit Intelligence 專案,該專案會在伺服器外部保存持久化執行緒與對話記憶。伺服器啟動時會驗證 INTELLIGENCE_API_URL、INTELLIGENCE_GATEWAY_WS_URL、INTELLIGENCE_API_KEY 和 COPILOTKIT_LICENSE_TOKEN,四者必須同時存在,否則啟動會失敗。截至 August 2026 已提供免費方案。Intelligence 本身也可自行託管,因此只要投入比快速入門指南更多的工作,就能完成完全本機部署。
模型是第二項外部相依性。此套件不會內建模型。BOT_PROVIDER 接受 openai、anthropic 或 google,而 OPENAI_BASE_URL 可將 OpenAI 路徑指向任何相容端點。若要讓 token 留在自己的硬體上,這正適合搭配在 VPS 上執行 Ollama 以自行託管 LLM。瀏覽器控制對模型的要求很高,因此在正式採用本機模型前,請先讓它執行實際任務進行測試。
目前只執行 1 個 replica
gateway 會將頁面快照快取在伺服器程序的記憶體中。執行 2 個 replica 時,其中一個程序建立的快照,另一個程序無法看見。因此,動作會間歇性失敗,並出現看似隨機的 element-not-found 錯誤。部署文件明確要求執行單一 replica,並將平台的 maximum instance count 固定為 1。快照快取移至資料庫後,才能取消這項限制。在此之前,請透過提升伺服器規格來擴充 OpenBot,而不是增加伺服器數量。各 bot 之間仍由個別容器提供隔離,這與 自架 agent sandbox 將某個 agent 的錯誤隔離在其他 agent 之外的方式相同。
失敗模式與你會看到的現象
填入 .env 後,啟動立即結束。 伺服器會先驗證設定,之後才提供服務。部分完成的 Intelligence 區塊、缺少 KEY_ENCRYPTION_KEY,或 OAuth provider 只有 client ID 而沒有 secret,都會讓啟動失敗,不會靜默降級。先讀取第一個錯誤,修正該欄位後再重新啟動。
受管理的資料庫上移轉失敗。 vector extension 預設未啟用,因此移轉會遇到 PostgreSQL 不認得的欄位型別。以 superuser 身分連線,執行 CREATE EXTENSION vector;,然後重新執行移轉步驟。
應用程式已載入,但登入狀態始終無法維持。 你在公開位址上使用純 http:// 提供服務,這不是安全內容環境,因此 Secure cookie 會被捨棄。請在前方設定 TLS,或使用 SSH tunnel,讓瀏覽器看到 localhost。
Bot 共用你原本預期應分開的登入狀態。 supervisor 未執行,因此沒有每個 bot 專用的 computer,所有 bot 都會使用共用瀏覽器。確認已設定 COMPUTER_SUPERVISOR_URL,並確認 supervisor 能連線至 Docker socket。
Bot 停止並要求協助。 這代表設計正常運作。稽核軌跡會記錄 computer.help_requested,你可在即時畫面接管操作,而交接也會記錄在雙方的紀錄中。
FAQ
保留 OPENBOT_SINGLE_USER 供 VPS 部署使用是否安全?
只有在 gateway 無法從網際網路連入時才安全。OPENBOT_SINGLE_USER=true 會將每個請求都視為同一位 administrator,且不要求登入。因此,任何能開啟該連接埠的人,都能控制此部署、其中儲存的認證資訊,以及已登入的瀏覽器。當所有連接埠都繫結至 127.0.0.1,並透過 SSH tunnel 或私有網路介面存取應用程式時,可以接受這種設定。在公開介面上,請關閉它,並搭配 BETTER_AUTH_SECRET、BETTER_AUTH_URL、INITIAL_ADMIN_EMAILS 和 TRUSTED_ORIGINS 設定 Google、Microsoft Entra、Okta 或 OIDC。
一個 OpenBot bot 需要多少 RAM?
專案針對單一 arm64 Bot 發布的數據顯示,尖峰記憶體使用量為 0.55 GB;文件記載的最低需求為 2 GB,建議配置為 4 GB。專案沒有同時執行多個 bot 的發布數據,因為每個 bot 都會各自執行一個 Chromium。請讓一個 bot 執行實際工作,在 docker stats 讀取該容器的記憶體使用量,再加上 gateway 和資料庫的用量,最後乘以預期同時存在的 bot 數量。
自行託管 OpenBot 需要 CopilotKit 帳戶嗎?
需要。OpenBot 依賴 CopilotKit Intelligence project 來保存 threads 和 memory,而且必須設定 Intelligence API URL、gateway WebSocket URL、API key 及 license token,否則 server 不會啟動。截至 August 2026 已提供免費方案;Intelligence 也可自行託管,因此投入額外工作後,可以移除託管依賴。你也必須提供自己的 model API key,因為 OpenBot 不會隨附 model。
為什麼每個 bot 都使用自己的瀏覽器,而不是共用一個?
因為瀏覽器 profile 就是一種身分。共用瀏覽器代表共用 cookies 和 sessions,因此一個 bot 登入某個帳戶後,所有 bot 都會登入該帳戶。每個 bot 使用獨立容器,可讓每位協作者擁有自己的 profile 和登入狀態。代價是記憶體用量增加,因為每個 bot 執行一個 Chromium,是 sizing 中最大的單項用量。
OpenBot 的哪些連接埠應在防火牆上開放?
較低層的連接埠都不應開放。agent-computer 使用 4100,bot endpoints 使用 4200 和 4201,supervisor 使用 4500,PostgreSQL 使用 5432;這些連接埠都應維持私有。專案以 tokens 保護它們,並要求你無論如何都不要讓它們可連入。只發布使用者需要開啟的服務,並注意:使用 -p 3001:3001 發布的 container port,不論 ufw 的 default-deny 規則為何都可連入,因為 Docker 的 DNAT 規則會將該流量放入 FORWARD 路徑,而不是 INPUT。