Cách tự host OpenHands trên VPS an toàn
Hướng dẫn cài đặt OpenHands bằng Docker trên VPS. Lưu ý quan trọng về việc mount Docker socket có thể gây rủi ro root nếu bạn không cấu hình hardening.
OpenHands là gì, và rủi ro quan trọng nhất cần hiểu trước tiên
OpenHands, trước đây là OpenDevin, là một agent tự động thực hiện kỹ thuật phần mềm. Bạn đưa cho nó một nhiệm vụ bằng ngôn ngữ tự nhiên, nó sẽ lập kế hoạch, viết code, chạy lệnh, đọc output và lặp lại cho đến khi hoàn thành nhiệm vụ. Bạn chạy nó trên server riêng bằng Docker và kết nối với một language model. Trên một VPS, nó trở thành một coding agent làm việc trong khi bạn vắng mặt.
Có một thực tế quyết định toàn bộ cách thiết lập của bạn. OpenHands không chỉ gợi ý code, nó còn thực thi code đó. Để làm việc này, container controller sẽ mount Docker socket của host tại /var/run/docker.sock để có thể tạo các sandbox container cho mỗi nhiệm vụ. Bất kỳ thứ gì có thể giao tiếp với Docker socket đều có thể khởi tạo một container mới và mount toàn bộ filesystem của host, nghĩa là quyền truy cập socket tương đương với quyền root trên máy đó. Vì vậy, hãy coi máy chạy OpenHands như một server chạy code không đáng tin cậy, vì đó chính xác là những gì nó làm. Mọi lựa chọn hardening dưới đây đều dựa trên nguyên tắc này.
Những gì bạn cần
Bạn cần một VPS chạy Ubuntu 24.04 với Docker Engine phiên bản mới, tối thiểu 4 GB RAM, và một API key cho language model (OpenAI, Anthropic, hoặc Google), hoặc một model chạy local qua Ollama trên cùng VPS đó. OpenHands hỗ trợ hàng chục model backend, nên tùy bạn lựa chọn. Nếu bạn chưa từng thiết lập container trước đây, các kiến thức cơ bản về Docker trên VPS sẽ giải thích các nền tảng mà hướng dẫn này giả định.
Cài đặt với Docker
OpenHands gồm hai image: image ứng dụng để bạn chạy, và image agent-server mà nó sẽ pull về để chạy sandbox cho mỗi nhiệm vụ. Hãy chạy lệnh như sau, thay thế các tag hiện tại từ tài liệu của dự án:
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.8Hai chi tiết sau sẽ giúp bạn tránh mất một giờ loay hoay. Image app và image agent-server có số phiên bản khác nhau một cách cố ý, nên đừng cố làm cho chúng khớp nhau: hãy dùng tag agent-server mà tài liệu đi kèm với phiên bản app của bạn. Và lưu ý dùng -p 127.0.0.1:3000:3000 thay vì -p 3000:3000. Thay đổi duy nhất đó là sự khác biệt giữa một Web UI chỉ bạn có thể truy cập và một Web UI mà toàn bộ internet có thể truy cập, điều mà phần tiếp theo sẽ đề cập.
Giữ Web UI không lộ lên internet công cộng
OpenHands phục vụ interface trên port 3000. Interface đó điều khiển một agent chạy code, vì vậy việc public nó lên internet sẽ trao cho bất kỳ ai tìm thấy nó một đường dẫn từ xa để thực thi lệnh. Hãy bind nó vào loopback như lệnh chạy ở trên, và truy cập từ laptop của bạn qua một SSH tunnel:
ssh -L 3000:127.0.0.1:3000 you@your-vpsSau đó mở http://127.0.0.1:3000 trên máy cá nhân của bạn. Traffic sẽ chạy qua session SSH hiện có, và không có gì mới lắng nghe trên internet công cộng. Để thiết lập lâu dài hơn, hãy đặt nó sau một VPN. Dù cách nào, hãy đặt một firewall mặc định là deny trước máy chủ để không có gì bị lộ ngoài ý muốn, và hãy nhớ rằng một firewall chỉ bao gồm IPv4 sẽ vẫn để mở cùng port đó trên IPv6, đây chính là lỗ hổng IPv6 firewall khiến nhiều người gặp rắc rối.
Cách ly model key và mọi credentials của repo
OpenHands cần một API key cho model, và thường cần một token để clone và push vào các repository của bạn. Cả hai đều có thể tiêu tốn tiền và hành động dưới danh nghĩa của bạn, nên hãy coi chúng như mật khẩu. Hãy giữ chúng trong một file environment mà chỉ tài khoản phù hợp mới có quyền đọc, đừng bao giờ để trong lệnh chạy vì chúng sẽ nằm trong shell history và process list, và đừng bao giờ để trong một file bên trong git repository.
Chạy trên một máy có thể xóa bỏ bất cứ lúc nào
Vì controller phải giữ Docker socket, bạn không thể sandbox hoàn toàn OpenHands khỏi host. Cách giảm thiểu rủi ro thực tế nhất là cách ly bằng vị trí: hãy chạy OpenHands trên một VPS chuyên dụng không chứa bất kỳ dữ liệu quan trọng nào khác, đừng chạy trên server đang chạy database hoặc website của bạn. Hãy chụp snapshot trước khi bắt đầu, và rebuild từ snapshot đó thay vì tin tưởng một máy đã chạy code do agent viết trong một tuần. Một VPS rẻ, dễ dàng xóa bỏ và chỉ dùng cho một mục đích duy nhất là lựa chọn hợp lý nhất.
Hardening máy chủ
Phần còn lại là các bước vệ sinh server tiêu chuẩn, và nó quan trọng ở đây hơn bình thường vì khối lượng công việc này rủi ro hơn bình thường. Hãy tạo một user admin không có đặc quyền thay vì làm việc với quyền root, tuân theo chạy services với user không có đặc quyền. Chuyển SSH sang chế độ chỉ xác thực bằng key. Sau đó chạy checklist dưới đây và lưu nó ở nơi bạn có thể xem lại.
Để hiểu rõ các thành phần hoạt động thay vì chỉ chạy chúng, hãy xem tự xây dựng AI agent trên VPS; đối với một nền tảng ít code hơn, self-hosting Dify sẽ là một bước khởi đầu nhẹ nhàng hơn.
FAQ
Chạy OpenHands trên server có an toàn không?
Có thể an toàn nếu bạn cẩn thận, nhưng nó rủi ro hơn một web app thông thường vì nó viết và thực thi code, đồng thời controller của nó giữ Docker socket của host, thứ tương đương với quyền root trên máy. Hãy chạy nó trên một VPS chuyên dụng, có thể xóa bỏ và không chứa gì giá trị khác, giữ Web UI ở loopback sau một SSH tunnel hoặc VPN, cách ly các key, và hardening máy chủ. Đừng chạy nó cùng với các dịch vụ quan trọng của bạn.
Tại sao OpenHands cần Docker socket?
OpenHands chạy mỗi nhiệm vụ trong một sandbox container mới, và nó yêu cầu Docker daemon của host tạo các container đó bằng cách mount /var/run/docker.sock vào controller. Điều này cho phép container controller có quyền kiểm soát Docker trên host, một việc vừa mạnh mẽ vừa rủi ro, vì vậy bản thân host phải được coi là một máy chạy code không đáng tin cậy.
OpenHands có thể dùng model local thay vì API trả phí không?
Có. OpenHands hỗ trợ các model local được phục vụ bởi Ollama hoặc vLLM, vì vậy bạn có thể chạy nó hoàn toàn self-hosted mà không tốn chi phí theo token và không có dữ liệu nào rời khỏi server của bạn. Bạn cần một máy có đủ bộ nhớ cho một coding model đủ mạnh, tương tự như vấn đề về cấu hình trong hướng dẫn Ollama.
Tôi có nên chạy OpenHands trên server chính không?**
Không. Vì nó chạy code do agent viết và giữ Docker socket, hãy giữ nó trên một VPS riêng biệt, chuyên dụng mà bạn sẵn sàng rebuild. Việc đặt nó cùng với database, website hoặc các dịch vụ khác có nghĩa là một sai lầm của agent, hoặc một bug trong đó, có thể chạm tới những thứ mà nó không bao giờ được phép chạm vào.