Tự host OpenBot AI coworker trên VPS cần bao nhiêu RAM?
Tự host OpenBot với một container và Chromium riêng cho mỗi AI coworker. Xem gateway duyệt mọi action qua policy, giữ browser profile và tính chi phí RAM.
Kết quả khi bạn tự host các AI coworker của OpenBot
Bạn tự host các AI coworker của OpenBot bằng cách chạy một gateway server và một container cho mỗi bot trên phần cứng do bạn kiểm soát. Mỗi container của bot có Chromium browser và workspace volume riêng, cùng một browser profile được giữ lại giữa các session. Mọi action bot thực hiện trên máy tính, file, MCP (model context protocol) server hoặc UI component đều đi qua gateway đó. Gateway kiểm tra action theo policy trước khi thực hiện và ghi lại sau đó.
OpenBot do CopilotKit phát hành theo giấy phép MIT tại github.com/CopilotKit/openbot. Bản release đầu tiên có tag, v0.0.1, được phát hành vào ngày 17 August 2026. Project tự mô tả là alpha và vẫn đang được phát triển tích cực. Hãy xem đây là một thiết kế nghiêm túc nhưng vẫn còn những điểm chưa hoàn thiện ở giai đoạn đầu.
Điểm đáng chú ý của kiến trúc này cũng là phần tốn tài nguyên nhất. Mỗi agent cần một browser, và đây là chi phí bộ nhớ mà nhiều người quên tính đến. Vì vậy, phần sizing được đặt trước phần cài đặt trong hướng dẫn này.
Cách gateway quyết định mọi hành động
API server trên port 3001 là đường duy nhất đến máy tính của bot. Trước khi một hành động trên trình duyệt chạy, gateway xác định target từ snapshot của trang, đánh giá các policy rule CEL (ngôn ngữ biểu thức chung) dựa trên context, ghi một audit row chứa quyết định, rồi mới gọi container. Nếu quá trình thực thi fail sau đó, gateway ghi thêm một row thứ hai. Tài liệu nêu rõ ranh giới này: máy tính không quyết định policy; server gateway là ranh giới thực thi hành động.
Policy mặc định là deny, và các deny rule được đánh giá trước allow rule. Hướng xử lý khi fail quan trọng hơn cú pháp của rule. Không có policy thì không cho phép gì, còn rule bị lỗi sẽ chuyển sang blocking, dù đó là deny rule hay allow rule. Vì vậy, lỗi trong policy sẽ khiến bot bị kẹt thay vì để bot tự do truy cập các account của bạn.
Audit trail nằm trong PostgreSQL nên vẫn còn sau khi restart. Các lần bàn giao quyền điều khiển được ghi dưới dạng computer.help_requested, computer.control_taken và computer.control_released. Nhờ đó, bạn biết khi bot yêu cầu người dùng can thiệp và khi người dùng trả lại quyền điều khiển. Secrets được ghi dưới dạng số lượng ký tự, không bao giờ ghi giá trị. Các thao tác với file ghi path và kích thước, không ghi nội dung. Nếu muốn có cùng ranh giới kiểm soát nhưng không chạy browser phía sau, đặt các hành động của AI agent sau bước phê duyệt trình bày trường hợp hẹp hơn đó.
Chi phí RAM và disk của một bot
Dự án công bố các số liệu đo được cho một Bot trên arm64. Đây là các số liệu sizing duy nhất mà OpenBot cung cấp. Chúng mô tả một bot trên một architecture, vì vậy hãy xem đây là điểm bắt đầu, không phải capacity plan.
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
}
]Memory peak được đo ở mức 0.55 GB cho một Bot. Mức tối thiểu được tài liệu ghi nhận là 2 GB và mức khuyến nghị là 4 GB. Khoảng chênh giữa số đo và mức tối thiểu là phần dự phòng để Chromium tăng memory khi tải cao, vì memory mà browser sử dụng phụ thuộc vào các page đang mở, không phải trạng thái process khi idle. CPU khi idle gần như không đáng kể, ở mức 0.06 core tại mức cao nhất trong khoảng đo được. Vì vậy, CPU không phải tài nguyên chính bạn cần mua. Disk mới là tài nguyên đó. Riêng image đã chiếm 5.3 GB, trong khi volume được khuyến nghị là 10 GB. Image lớn như vậy vì đi kèm Chromium là các binary Firefox và WebKit của Playwright.
Những số liệu này không cho biết chi phí khi chạy nhiều bot cùng lúc, và dự án không công bố số liệu cho trường hợp đó. Hãy tự đo. Khởi động một bot, giao cho bot một task thực tế có page đang mở, rồi monitor container trong khi bot làm việc.
docker stats --no-stream
free -mLấy cột MEM USAGE của container bot làm số liệu cho mỗi bot. Cộng thêm gateway và PostgreSQL, sau đó nhân số liệu cho mỗi bot với số bot bạn dự kiến sẽ tồn tại cùng lúc. Bot idle vẫn giữ một browser process, vì vậy hệ số nhân áp dụng cho tất cả bot đang tồn tại, không chỉ các bot đang bận. Cách tính này giống cách tính dùng trong sizing RAM và CPU cho coding agent trên VPS. Phần liên quan đến browser được trình bày trong chạy headless browser cho agent trên VPS.
Một chi tiết của Chromium ảnh hưởng đến các plan nhỏ. OpenBot khởi chạy Chromium với --disable-dev-shm-usage, vì vậy browser ghi dữ liệu vào /tmp thay vì /dev/shm. Cách này tránh lỗi crash trên các host có /dev/shm nhỏ, nhưng chuyển áp lực sang root filesystem. Đây là một lý do nữa khiến disk được khuyến nghị lớn hơn image.
Tự host OpenBot trên VPS như thế nào?
Bạn cần Docker, Bun 1.3 trở lên, một project CopilotKit Intelligence và model API key. Tài liệu dành cho môi trường development cũng yêu cầu lsof, python3 và curl trên máy chủ. Hãy clone một tagged release thay vì main, vì main trong một project alpha có thể thay đổi mà không báo trước.
git clone --branch v0.0.1 https://github.com/CopilotKit/openbot.git
cd openbot
cp .env.example .envProvision project Intelligence. 3 lệnh này ghi runtime key và license token vào environment file.
npx --yes copilotkit@latest login
npx --yes copilotkit@latest project select
npx --yes copilotkit@latest license --writeTạo key dùng để mã hóa credential đã lưu, rồi ghi output vào .env dưới dạng KEY_ENCRYPTION_KEY. Thêm OPENAI_API_KEY vào cùng file, hoặc đặt BOT_PROVIDER thành anthropic hoặc google cùng với key tương ứng.
openssl rand -base64 32Sau đó cài đặt và khởi động.
bun install
bash scripts/start.shscripts/start.sh khởi động các Docker service, chạy database migration, khởi động server và app, rồi kiểm tra health của chúng. Khi hoàn tất, app trả lời trên port 3010 và API trên port 3001. Script báo các port bị xung đột và không can thiệp vào service tương ứng đang chạy, nên chạy script 2 lần vẫn an toàn.
Kiểm tra ngay trên server trước khi expose bất kỳ dịch vụ nào.
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 từ lệnh đầu tiên cho biết app đang phục vụ request. Lệnh thứ 2 cho biết các port đó đang bind vào địa chỉ nào; đây mới là thông tin cần quan tâm trên VPS. Dòng có nội dung 127.0.0.1:3001 chỉ cho phép truy cập từ bên trong máy chủ. Dòng có nội dung 0.0.0.0:3001 có nghĩa là bất kỳ ai định tuyến được đến server đều có thể truy cập.
Image container duy nhất
Tài liệu triển khai cũng phát hành một image duy nhất chứa app, API và Chromium, chạy trên cổng 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 chạy PostgreSQL bên trong container và áp dụng migration khi khởi động. Named volume giữ lại lịch sử audit qua các lần triển khai lại. Nếu không có volume này, mỗi lần build lại sẽ xóa toàn bộ lịch sử đó. Nếu trỏ DATABASE_URL đến một database được quản lý, phải bật extension vector trên database đó. Các dịch vụ managed như RDS, Cloud SQL và Azure Database đều hỗ trợ extension này, nhưng không dịch vụ nào tự bật cho bạn. Vì vậy, migration trên một managed database mới sẽ fail vì kiểu cột vector chưa tồn tại.
Hãy chạy migration như một bước release khi database nằm bên ngoài.
docker run --rm --env-file .env openbot \
sh -c "cd /app/server && bun x drizzle-kit migrate --config=drizzle.config.ts"Image này cố ý không publish cổng của browser. Image cũng không có supervisor vì supervisor cần Docker socket, trong khi các nền tảng serverless không cung cấp socket này. Không có supervisor, mọi bot dùng chung một browser và cùng một bộ thông tin đăng nhập. Điều đó loại bỏ cơ chế isolation vốn là lý do cần chạy container riêng cho từng bot. Nếu lý do bạn dùng hệ thống này là cần bộ thông tin đăng nhập riêng cho từng bot, hãy chạy compose stack với COMPUTER_SUPERVISOR_URL và SUPERVISOR_TOKEN được thiết lập, trên một host mà bạn chấp nhận đánh đổi này. Một process có thể kết nối đến Docker socket thì có thể start một privileged container. Trên thực tế, process đó có quyền root trên host. Đây là lý do hợp lý để chạy OpenBot trên một máy riêng, tương tự như cấp cho coding agent một VM dùng một lần.
Vì sao OPENBOT_SINGLE_USER chỉ phù hợp với laptop
.env.example đi kèm với OPENBOT_SINGLE_USER=true. Cấu hình này coi mọi request là của cùng một administrator và bỏ qua hoàn toàn bước sign-in. Trên laptop, đây là cách tiện lợi vì chỉ bạn mới có thể truy cập cổng đó. Trên VPS, người đầu tiên truy cập được cổng 3010 sẽ trở thành administrator của hệ thống lưu credential đã mã hóa và điều khiển một browser đã sign-in vào các tài khoản của bạn.
Có 2 cách triển khai an toàn và rõ ràng. Giữ OPENBOT_SINGLE_USER=true, bind mọi cổng vào 127.0.0.1, rồi chỉ truy cập app qua SSH tunnel hoặc private network interface.
ssh -N -L 3010:127.0.0.1:3010 -L 3001:127.0.0.1:3001 you@your-vpsKhi đó, app có địa chỉ http://localhost:3010 trong browser của bạn. Địa chỉ này được xem là secure context, nên sign-in cookie và các tính năng browser mà live screen cần đều hoạt động. Cách còn lại là tắt single-user mode và cấu hình một identity provider thực sự. Google, Microsoft Entra, Okta, SAML và OIDC được hỗ trợ. Mọi provider cũng cần BETTER_AUTH_SECRET có độ dài từ 32 ký tự trở lên, BETTER_AUTH_URL được đặt thành public API base URL dùng cho OAuth callback, INITIAL_ADMIN_EMAILS và TRUSTED_ORIGINS. Credential của provider phải đầy đủ, vì provider cấu hình thiếu sẽ khiến app dừng khi startup thay vì chuyển sang open access.
Nếu app có thể truy cập qua một public name, hãy đặt TLS (transport layer security) phía trước app. Một page được phục vụ qua http://, nếu không phải localhost, không được xem là secure context. Vì vậy, cookie có thuộc tính Secure sẽ không được lưu và sign-in thất bại theo cách dễ khiến bạn tưởng đây là bug trong OpenBot.
Chặn các cổng tầng thấp
Ghi chú bảo mật của OpenBot nêu rõ các endpoint dịch vụ tầng thấp được bảo vệ bằng token, bạn nên giữ chúng ở chế độ riêng tư và không được dùng chúng để bypass gateway. Token là lớp bảo vệ thứ hai. Lớp đầu tiên là cổng hoàn toàn không thể truy cập được.
agent-computer lắng nghe trên cổng 4100 và yêu cầu COMPUTER_TOKEN. Các endpoint của bot lắng nghe trên cổng 4200 và 4201. Supervisor lắng nghe trên cổng 4500 trên host và cổng 4300 bên trong container. PostgreSQL lắng nghe trên cổng 5432. Không cổng nào trong số đó nên được bind vào interface public. Trong deployment một người dùng, app và API cũng không nên như vậy.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status verboseCó một bẫy khiến nhiều người cho rằng firewall là đủ. Khi publish một container port bằng -p 3001:3001, Docker sẽ cài một rule DNAT. Vì vậy, traffic được xử lý trong đường đi FORWARD và không bao giờ đi qua chain INPUT, nơi ufw áp dụng chính sách deny mặc định. Cổng vẫn mở dù ufw status vẫn in ra Status: active. Hãy bind published port vào loopback ngay trong mapping, như -p 127.0.0.1:3001:3001, hoặc đặt host address trong file compose. Xác minh bằng ss -ltnp, không dùng ufw status.
OpenBot không phải là một stack offline
Hãy xác định điều này trước khi lên kế hoạch triển khai. OpenBot phụ thuộc vào một project Intelligence của CopilotKit. Project này lưu các thread lâu dài và memory của cuộc trò chuyện bên ngoài máy chủ của bạn. Server kiểm tra INTELLIGENCE_API_URL, INTELLIGENCE_GATEWAY_WS_URL, INTELLIGENCE_API_KEY và COPILOTKIT_LICENSE_TOKEN khi khởi động. Cả 4 giá trị phải cùng tồn tại, nếu không quá trình khởi động sẽ fail. Tính đến August 2026, có một free plan. Intelligence cũng có thể self-host, nên bạn vẫn có thể triển khai hoàn toàn local, nhưng sẽ cần nhiều công sức hơn quickstart mô tả.
Model là dependency bên ngoài thứ 2. OpenBot không ship kèm model nào. BOT_PROVIDER nhận openai, anthropic hoặc google. OPENAI_BASE_URL trỏ OpenAI path đến bất kỳ endpoint tương thích nào. Đây là nơi chạy Ollama trên VPS để self-host một LLM phù hợp nếu bạn muốn giữ token trên phần cứng của mình. Browser control yêu cầu rất nhiều từ model, vì vậy hãy kiểm tra model local bằng một task thực tế trước khi quyết định dùng nó.
Chạy 1 replica trong thời gian hiện tại
Gateway lưu cache snapshot của trang trong bộ nhớ của server process. Khi có 2 replica, snapshot do một process tạo ra sẽ không hiển thị với process còn lại. Vì vậy, các action thỉnh thoảng thất bại với lỗi không tìm thấy element, trông như xảy ra ngẫu nhiên. Tài liệu triển khai nêu rõ: hãy chạy 1 replica và đặt số instance tối đa của platform về 1. Giới hạn này sẽ được gỡ bỏ khi việc cache snapshot chuyển sang database. Cho đến lúc đó, hãy scale OpenBot bằng cách nâng cấp máy chủ, không phải thêm máy chủ. Việc cô lập giữa các bot vẫn do các container riêng cho từng bot đảm nhiệm, tương tự như sandbox agent tự host giúp ngăn lỗi của một agent ảnh hưởng đến các agent khác.
Các chế độ lỗi và những gì bạn sẽ thấy
Startup thoát ngay sau khi bạn điền .env. Server kiểm tra cấu hình trước khi phục vụ bất kỳ nội dung nào. Một block Intelligence chưa hoàn chỉnh, thiếu KEY_ENCRYPTION_KEY hoặc OAuth provider có client ID nhưng không có secret đều khiến startup dừng lại thay vì âm thầm chuyển sang chế độ suy giảm. Đọc lỗi đầu tiên, sửa đúng trường đó rồi khởi động lại.
Migration thất bại trên managed database. Extension vector không được enable mặc định, nên migration gặp một kiểu column mà PostgreSQL không biết. Kết nối bằng superuser, chạy CREATE EXTENSION vector; rồi chạy lại bước migration.
App tải được nhưng đăng nhập không bao giờ được giữ lại. Bạn đang phục vụ qua http:// thuần trên địa chỉ public. Đây không phải secure context, nên cookie Secure bị trình duyệt loại bỏ. Đặt TLS ở phía trước hoặc dùng SSH tunnel để trình duyệt thấy localhost.
Các bot dùng chung những login mà bạn muốn tách riêng. Supervisor chưa chạy, nên không có computer riêng cho từng bot và mọi bot đều dùng chung browser. Xác nhận COMPUTER_SUPERVISOR_URL đã được set và supervisor có thể truy cập Docker socket.
Một bot dừng lại và yêu cầu trợ giúp. Đó là thiết kế đang hoạt động đúng. Audit trail ghi lại computer.help_requested, bạn tiếp quản trên màn hình đang chạy và việc handover được ghi nhận ở cả hai phía.
FAQ
Có an toàn không nếu để OPENBOT_SINGLE_USER bật khi triển khai trên VPS?
Chỉ an toàn khi không thể truy cập gateway từ Internet. OPENBOT_SINGLE_USER=true chấp nhận mọi request dưới danh nghĩa một administrator mà không cần đăng nhập, nên bất kỳ ai mở được cổng đều có toàn quyền trên deployment, các credential đã lưu và trình duyệt đang đăng nhập. Cách này chấp nhận được khi mọi cổng đều bind vào 127.0.0.1 và bạn truy cập app qua SSH tunnel hoặc private network interface. Trên public interface, hãy tắt tùy chọn này và cấu hình Google, Microsoft Entra, Okta hoặc OIDC cùng với BETTER_AUTH_SECRET, BETTER_AUTH_URL, INITIAL_ADMIN_EMAILS và TRUSTED_ORIGINS.
Một OpenBot bot cần bao nhiêu RAM?
Số liệu được project công bố cho một Bot duy nhất trên arm64 cho biết memory tối đa là 0.55 GB, mức tối thiểu được ghi nhận là 2 GB và mức khuyến nghị là 4 GB. Chưa có số liệu được công bố cho nhiều bot chạy đồng thời, vì mỗi bot giữ một Chromium riêng. Hãy chạy một bot với tác vụ thực tế, đọc memory của container đó trong docker stats, cộng thêm gateway và database, rồi nhân với số bot dự kiến chạy cùng lúc.
Tôi có cần tài khoản CopilotKit để self-host OpenBot không?
Có. OpenBot phụ thuộc vào một project CopilotKit Intelligence để lưu thread và memory lâu dài. Server sẽ từ chối khởi động nếu chưa đặt Intelligence API URL, gateway WebSocket URL, API key và license token. Tính đến August 2026, CopilotKit có free plan. Intelligence cũng có thể self-host, nên có thể loại bỏ dependency được host này nếu chấp nhận cấu hình thêm. Bạn cũng phải cung cấp model API key của mình, vì OpenBot không đi kèm model nào.
Vì sao mỗi bot có browser riêng thay vì dùng chung một browser?
Vì browser profile là một identity. Dùng chung browser đồng nghĩa với dùng chung cookie và session, nên nếu một bot đăng nhập vào một account thì mọi bot đều đăng nhập vào account đó. Container riêng cho từng bot cung cấp cho mỗi coworker một profile riêng và các thông tin đăng nhập riêng. Đổi lại, hệ thống tốn thêm memory, vì Chromium của từng bot là thành phần chiếm nhiều memory nhất trong sizing.
Những cổng OpenBot nào nên mở trên firewall?
Không nên mở các cổng cấp thấp. Agent-computer trên 4100, các bot endpoint trên 4200 và 4201, supervisor trên 4500 và PostgreSQL trên 5432 đều phải giữ ở private network. Project bảo vệ các endpoint này bằng token và vẫn yêu cầu bạn không cho chúng có thể truy cập từ bên ngoài. Chỉ publish những gì người dùng cần mở. Lưu ý rằng container port được publish bằng -p 3001:3001 vẫn có thể truy cập bất kể rule mặc định là deny của ufw, vì rule DNAT của Docker đưa traffic đó vào đường đi FORWARD thay vì INPUT.