如何在 VPS 上使用 Docker 架設 OpenHands AI 代理
本文教學如何在 VPS 上透過 Docker 安裝 OpenHands。由於其會掛載 Docker socket 導致具備 root 權限風險,指南特別強調如何正確配置 agent-server image 版本,並透過 SSH 隧道保護 Web UI 避免暴露於公開網路。
OpenHands 是什麼,以及首先必須了解的風險
OpenHands(前身為 OpenDevin)是一個自主軟體工程代理(autonomous software-engineering agent)。你只需使用自然語言下達任務,它便會進行規劃、編寫程式碼、執行指令、讀取輸出,並不斷迭代直到任務完成。你可以透過 Docker 在自己的伺服器上執行它,並連接至語言模型。在 VPS 上,它會變成一個在你不在時持續工作的編碼代理。
有一個事實會影響你的整體設定。OpenHands 不僅僅是建議程式碼,它還會執行程式碼。為了達成此目的,其 controller container 會將主機的 Docker socket 掛載至 /var/run/docker.sock,以便為每個任務啟動 sandbox containers。任何可以與 Docker socket 通訊的程序,都能啟動一個掛載你整個主機檔案系統的新容器,這意味著 socket 存取權限等同於該機器的 root 權限。因此,請將 OpenHands 主機視為執行不受信任程式碼的伺服器,因為這正是它的運作方式。下述所有的強化措施皆基於此原則。
必要條件
你需要一台執行 Ubuntu 24.04 且安裝了近期版本 Docker Engine 的 VPS、至少 4 GB RAM,以及語言模型的 API key(OpenAI、Anthropic 或 Google),或是透過 在同一台 VPS 上運行的 Ollama 提供的本地模型。OpenHands 支援數十種模型後端,可自行選擇。如果你從未設定過容器,VPS 上的 Docker 基礎知識 已涵蓋本指南所假設的內容。
使用 Docker 安裝
OpenHands 提供兩個映像檔:你執行的 application image,以及它用來執行各個任務 sandbox 的 agent-server image。請依照下列方式執行,並將目前的 tag 替換為專案文件中的版本:
docker run -it --rm --pull=always \
-e AGENT_SERVER_IMAGE_REPOSITORY=ghcr.io/openhands/agent-server \
-e AGENT_SERVER_IMAGE_TAG=1.26.0-python \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands:/.openhands \
-p 127.0.0.1:3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands \
docker.openhands.dev/openhands/openhands:1.8有兩個細節可以節省你一小時的困惑。App image 與 agent-server image 的版本號故意設計為不同,請勿嘗試讓它們一致:請使用文件建議與你的 app 版本配對的 agent-server tag。此外,請注意使用的是 -p 127.0.0.1:3000:3000 而非 -p 3000:3000。這單一的差異決定了該介面是僅限你存取,還是整個網際網路都能存取,下一節將說明此點。
避免將 Web UI 暴露於公開網路
OpenHands 在 port 3000 提供介面服務。該介面驅動著一個執行程式碼的代理,因此將其發布到網際網路,等於讓任何發現它的人都能透過遠端路徑執行指令。請將其綁定至 loopback(如上述執行指令所示),並透過 SSH tunnel 從你的筆電進行存取:
ssh -L 3000:127.0.0.1:3000 you@your-vps接著在你的電腦上開啟 http://127.0.0.1:3000。流量會經由你現有的 SSH session 傳輸,且公開網路上不會有新的監聽服務。若要進行更持久的設定,請改用 VPN。無論採取哪種方式,請在主機前部署預設拒絕(default-deny)的防火牆以防止意外暴露,並記住僅涵蓋 IPv4 的防火牆會在 IPv6 上開啟相同的 port,這就是導致許多人踩坑的 IPv6 防火牆漏洞。
隔離模型 Key 與任何 Repo 憑證
OpenHands 需要一個模型使用的 API key,通常還需要一個用於 clone 與 push 至你儲存庫的 token。兩者都可能消耗金錢並以你的身份執行操作,因此請將其視為密碼。請將它們存放在僅限正確帳戶讀取的環境變數檔中,切勿寫在執行指令中(否則會留在 shell history 與 process list 中),也切勿存放在 git 儲存庫內的檔案中。
在可隨時棄置的機器上執行
由於 controller 必須持有 Docker socket,你無法完全將 OpenHands 與主機進行沙箱隔離。最實際的緩解方案是透過位置進行隔離:將 OpenHands 執行在專用的 VPS 上,該機器不得存放任何你重視的資料,不要與執行資料庫或網站的伺服器放在一起。在開始前請先建立快照(snapshot),並從快照重建,而不是信任一台已經執行過代理撰寫程式碼一週的機器。使用廉價、可棄置且單一用途的 VPS 是最合適的選擇。
強化主機安全性
其餘部分屬於標準的伺服器維護,但在這裡比平常更重要,因為工作負載的風險較高。請遵循 以非特權使用者執行服務 的原則,建立一個非特權管理員使用者,而非直接使用 root。將 SSH 改為僅限金鑰驗證。接著執行下方的檢查清單,並將其妥善保存。
若想深入理解運作機制而非僅是執行,請參閱 在 VPS 上建立你自己的 AI agent;若需要低程式碼平台,self-hosting Dify 是更簡單的入門方式。
FAQ
在伺服器上執行 OpenHands 安全嗎?
若謹慎操作是可以的,但它比一般的 Web app 風險更高,因為它會編寫並執行程式碼,且其 controller 持有主機的 Docker socket,這等同於該機器的 root 權限。請將它執行在專用的、可棄置的 VPS 上,該機器不得存放其他重要資料,將 Web UI 限制在 SSH tunnel 或 VPN 後的 loopback,隔離其金鑰,並強化主機安全性。請勿將它與你的重要服務並行執行。
為什麼 OpenHands 需要 Docker socket?
OpenHands 會在全新的 sandbox container 中執行每個任務,它會透過將 /var/run/docker.sock 掛載到其 controller 中,要求主機的 Docker daemon 建立這些容器。這使得 controller container 擁有控制主機 Docker 的權限,這既強大且具風險,因此主機本身必須被視為執行不受信任程式碼的環境。
OpenHands 可以使用本地模型而非付費 API 嗎?
可以。OpenHands 支援由 Ollama 或 vLLM 提供的本地模型,因此你可以完全自行託管,無需支付 token 費用,且資料不會離開你的伺服器。你需要一台擁有足夠記憶體以執行高效能編碼模型的機器,這與 Ollama 指南中提到的規格問題相同。
我應該在我的主伺服器上執行 OpenHands 嗎?
不應該。由於它會執行代理撰寫的程式碼並持有 Docker socket,請將它放在一個你願意隨時重建的獨立、單一用途 VPS 上。將它與資料庫、網站或其他服務共置,意味著代理的一個錯誤或程式錯誤,可能會觸及它不該接觸的內容。