SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor

Cách tự host sandboxd trên VPS với Docker

Tự chạy sandboxd trên VPS với Docker: cài đúng version, thêm model key, cấu hình HTTPS preview, kiểm tra RAM và disk, rồi dọn sandbox cũ.

sandboxd là gì và bạn nhận được gì khi tự chạy nó

Để tự host sandboxd, bạn cần một máy chủ Linux có Docker và một domain. Bạn gửi một prompt, coding agent sẽ xây dựng một ứng dụng thực bên trong một container cô lập, rồi ứng dụng đó chạy tại URL preview riêng. Các công cụ xây dựng ứng dụng từ prompt là nhóm dịch vụ hosted nổi bật nhất trong 2026. sandboxd là công cụ chạy trên VPS của bạn, theo giấy phép MIT, với mã nguồn được tạo lưu ngay trên disk của bạn.

Thiết kế được cố ý giữ nhỏ gọn. Control plane viết bằng Go điều khiển Docker, Traefik v3 định tuyến mọi hostname preview, SQLite lưu state, và mỗi ứng dụng chạy trong một container. Không có Kubernetes và cũng không cần database server riêng. Vì vậy, một máy có 2 vCPU vẫn có thể chạy được hệ thống này.

Toàn bộ mô hình dựa trên 4 object. app là project lâu dài, chứa tên, metadata của git và secret. sandbox là Docker container chạy app đó, và mỗi app tại một thời điểm chỉ trỏ đến một sandbox. workspace là các file của app. Các file này nằm trên host và vẫn tồn tại sau khi container bị dừng hoặc xóa. task là một prompt được giao cho agent bên trong sandbox. Dừng sandbox sẽ giải phóng memory nhưng vẫn giữ các file. Xóa sandbox sẽ loại bỏ container, sau đó app có thể khởi động một container mới.

sandboxd khác Dify và OpenHands như thế nào?

Ba công cụ này thường bị nhầm lẫn vì đều chạy LLM (large language model) trên server của bạn, nhưng sản phẩm đầu ra khác nhau. Dify xây dựng các ứng dụng LLM: giao diện chat, pipeline truy xuất dữ liệu và workflow gọi model mỗi khi có người sử dụng. Model là một phần của sản phẩm hoàn chỉnh. OpenHands làm việc trên repository bạn đã có: bạn trỏ công cụ vào code của mình, rồi nó đọc file, chạy command và đề xuất thay đổi. sandboxd bắt đầu từ con số 0. Nó dựng khung project từ một preset, build project trong container mới và cung cấp cho bạn một URL để xem. Sản phẩm đầu ra là một ứng dụng React hoặc FastAPI thông thường, không cần model để chạy.

Vì vậy, hãy chọn dựa trên thứ bạn muốn có ở cuối quy trình. sandboxd phù hợp khi bạn muốn bắt đầu từ một câu mô tả rồi giữ lại code sau đó. Hai công cụ còn lại phù hợp khi repository hoặc sản phẩm dùng model đã tồn tại.

Điểm khác biệt còn lại là tuổi đời. Đây là yếu tố cần cân nhắc trước khi xây dựng bất cứ thứ gì thực tế nào dựa trên công cụ này.

Biểu đồGitHub stars and forks, read from the GitHub API on 4 August 2026
Dữ liệu đằng sau biểu đồ này
[
  {
    "tool": "sandboxd",
    "github_stars": "875",
    "forks": "50"
  },
  {
    "tool": "OpenHands",
    "github_stars": "83,091",
    "forks": "10,711"
  },
  {
    "tool": "Dify",
    "github_stars": "151,320",
    "forks": "23,886"
  }
]

sandboxd có 875 star, so với 83,091 của OpenHands và 151,320 của Dify. Repository được tạo vào ngày 3 tháng 6 năm 2026, nên tính đến tháng 8 năm 2026, nó mới được 2 tháng, trong khi OpenHands ra mắt từ tháng 3 năm 2024 và Dify từ tháng 4 năm 2023. Bản release v0.1.0 được phát hành vào ngày 6 tháng 6 năm 2026 và v0.3.6 vào ngày 1 tháng 8 năm 2026. Project tự gọi là beta và cho biết các bản release 0.x có thể làm hỏng tính tương thích. Hãy xem những con số này là rủi ro về dependency, không phải kết luận về chất lượng: một project mới 2 tháng chỉ mới có 2 tháng để người khác phát hiện bug.

Máy chủ cần gì và điều gì xảy ra khi thiếu tài nguyên

Dự án cho biết 2 vCPU và 4 GB RAM là đủ để bắt đầu. Mức này phù hợp với control plane và một sandbox nhỏ, nhưng không đủ khi hai người build cùng lúc. Hãy phân bổ bộ nhớ theo từng phần. Traefik và control plane viết bằng Go sử dụng ít tài nguyên. Mỗi sandbox đang chạy chứa đầy đủ toolchain Node hoặc Python, và mức sử dụng cao nhất thường xuất hiện khi chạy npm install rồi đến production build. Hãy dự trù 8 GB cho máy chủ cần duy trì vài app, và chỉ xem swap là lớp dự phòng an toàn chứ không phải dung lượng sử dụng chính, vì một build phải swap sẽ mất vài phút thay vì vài giây.

Khi hết bộ nhớ, bạn có thể gặp hai lỗi khác nhau và biểu hiện của chúng hoàn toàn không giống nhau. Bên trong sandbox, container chạm ngưỡng --memory do sandboxd đặt ra, rồi kernel kill process lớn nhất. Vì vậy build dừng mà agent không đưa ra thông báo hữu ích. docker ps -a hiển thị exit code 137 cho container đó, còn docker inspect trên container này báo "OOMKilled": true. Một Node build dừng theo cách này thường in JavaScript heap out of memory trước tiên.

Lỗi thứ hai xảy ra trên host. sandboxd chạy một pressure reaper để dừng các sandbox khi bộ nhớ của host xuống thấp. Vì vậy, trên máy chủ nhỏ, một sandbox có thể biến mất trong lúc bạn đang xem preview của nó. Các file vẫn an toàn và request tiếp theo đến URL preview sẽ đánh thức sandbox, nhưng task đang chạy lúc container dừng sẽ không tiếp tục.

Disk là vấn đề âm thầm hơn. Mỗi app giữ workspace riêng trên host, còn một dự án JavaScript thường có cây node_modules lớn hàng trăm megabyte. Mười app sẽ cần vài gigabyte cho dependencies, chưa tính các image. Hãy bắt đầu với 40 GB và theo dõi dung lượng:

docker system df
sudo du -sh /var/lib/sandboxed/workspaces

Trong v0.3.6, là release mà hướng dẫn này cố định, thư mục dữ liệu mặc định là /var/lib/sandboxed, được viết với e bổ sung. Gõ /var/lib/sandboxd vào đó sẽ không cho kết quả gì và khiến bạn mất 5 phút khó hiểu. Điều này đã thay đổi trong v0.3.9 (25 August 2026). Installer mới đặt các bản cài đặt mới vào /var/lib/sandboxd và chỉ giữ /var/lib/sandboxed cho một bản cài đặt vốn đã nằm ở đó. Trên máy chủ được thiết lập lần đầu bằng release mới hơn, hãy dùng đường dẫn không có e trong mọi command bên dưới.

Cài đặt bản sandboxd được ghim phiên bản

Docker Engine kèm plugin Compose và git phải được cài sẵn trên máy. Cài đặt Docker trên VPS trình bày phần này.

docker compose version
git --version

Cả hai lệnh đều phải in ra phiên bản. docker: 'compose' is not a docker command có nghĩa là thiếu plugin Compose v2. Trình cài đặt ưu tiên plugin, nhưng sẽ dùng binary docker-compose độc lập nếu binary đó đã được cài. Trình cài đặt chỉ dừng với Docker Compose not found khi không có cả hai. Các lệnh trong hướng dẫn này dùng docker compose, nên cài plugin là cách sửa đơn giản hơn.

Trình cài đặt là một shell script được tải qua mạng. Vì vậy, hãy đọc script trước khi chạy và ghim phiên bản.

curl -fsSL https://raw.githubusercontent.com/tastyeffectco/sandboxd/v0.3.6/install.sh -o install-sandboxd.sh
less install-sandboxd.sh
SANDBOXD_REF=v0.3.6 bash install-sandboxd.sh

SANDBOXD_REF là git ref mà trình cài đặt checkout vào $HOME/.sandboxd/src. Giá trị mặc định là main. Nếu để trống, phiên bản cài đặt sẽ là bất kỳ phiên bản nào được merge vào sáng hôm đó. Điều này đáng lưu ý vì dự án đã phát hành sáu release chỉ trong tháng 7 năm 2026. Hãy ghim phiên bản, rồi chỉ nâng cấp sau khi đã đọc changelog. Tính đến ngày 12 tháng 10 năm 2026, release mới nhất là v0.3.22, tức đã có thêm mười sáu release sau v0.3.6 được ghim trong hướng dẫn này.

Script clone source, build các image, khởi động stack bằng docker compose up -d, rồi in URL của console và API token ở cuối. Hãy lưu token đó ở nơi an toàn. Đây là credential dùng cho API có thể điều khiển Docker với quyền root.

curl http://127.0.0.1:9090/healthz

Lệnh này in ok khi control plane đã hoạt động. Nếu không in gì, stack chưa khởi động. Hãy chạy docker compose ps từ ~/.sandboxd/src để xem service nào đang down, rồi chạy docker compose logs sandboxd để xem nguyên nhân.

Truy cập console trên máy chủ từ xa

Console được cung cấp thông qua Traefik tại HTTP_PORT, mặc định là cổng 80, với hostname http://console.localhost. Traefik định tuyến theo hostname, nên nếu nhập địa chỉ IP của máy chủ vào trình duyệt thì không khớp với rule nào và trả về lỗi 404. Cho đến khi cấu hình domain thật, hãy forward cổng và giữ nguyên hostname:

ssh -L 8080:127.0.0.1:80 you@your-vps

Sau đó mở http://console.localhost:8080 trên laptop. Trên Linux và macOS, mọi hostname kết thúc bằng .localhost đều phân giải về 127.0.0.1, nên request đi qua tunnel với header Host chính xác. Đặt mật khẩu console trong lần truy cập đầu tiên.

Cấp model cho agent

Trong base image có sẵn 2 coding agent: OpenCode và Claude Code. SANDBOXD_DEFAULT_AGENT quyết định agent nào chạy task không chỉ định agent cụ thể, và mặc định là opencode. Nếu chưa kết nối key nào, task sẽ chạy bằng các model miễn phí không cần key của OpenCode Zen. Vì vậy, lần build đầu tiên không tốn chi phí và bạn có thể kiểm thử toàn bộ quy trình trước khi phát sinh chi phí.

Kết nối key của bạn khi cần model mạnh hơn. Key được gửi đến control plane, không bao giờ được đưa vào sandbox. Key được lưu dưới dạng mã hóa trong data directory và được credential proxy inject trên đường truyền. Vì vậy, cả agent lẫn code do agent viết đều không thể đọc key.

export API=http://127.0.0.1:9090
export SANDBOXD_TOKEN=sk_...                       # printed by the installer
export AUTH="Authorization: Bearer $SANDBOXD_TOKEN"

curl -s -XPOST $API/v1/agents/claude-code/api-key -H "$AUTH" \
  -H 'content-type: application/json' \
  -d '{"api_key":"sk-ant-..."}'

Console cũng thực hiện việc này trong Settings, AI Agents. Tại đây có cả OAuth flow có hướng dẫn nếu bạn muốn dùng subscription của Claude thay vì API key. Model mặc định của từng agent được đặt trong cùng panel này. Bạn cũng có thể ghi đè model cho từng task.

Tạo một app nhỏ từ đầu đến cuối

Tạo app, khởi động sandbox rồi gửi một prompt. Các id được trả về dưới dạng JSON, và quickstart dùng sed để lấy chúng ra nên bạn không cần cài jq.

APP=$(curl -s -XPOST $API/v1/apps -H "$AUTH" \
  -H 'content-type: application/json' \
  -d '{"name":"todo","runtime_preset":"react-vite"}' \
  | sed -E 's/.*"id":"([^"]+)".*/\1/')

SB=$(curl -s -XPOST $API/v1/apps/$APP/sandbox -H "$AUTH" \
  -H 'content-type: application/json' -d '{"ports":[3000]}' \
  | sed -E 's/.*"id":"([^"]+)".*/\1/')

echo "app=$APP sandbox=$SB"

Cả hai biến đều phải chứa một id. $SB rỗng nghĩa là sandbox chưa bao giờ khởi động. Nguyên nhân thường gặp là base image vẫn đang được build hoặc host đã hết memory. Nếu nhận được 401 thay cho id thì bearer token không đúng.

curl -s -XPOST $API/v1/sandboxes/$SB/tasks -H "$AUTH" \
  -H 'content-type: application/json' \
  -d '{"prompt":"Add a todo list with a text input, an add button, and a delete button on each row. Keep the list in localStorage.","agent":"opencode"}'

Response chứa một task id. GET /v1/sandboxes/$SB/tasks/<task id> trả về kết quả của task, còn path /events trên cùng task là một luồng SSE (server sent events) trực tiếp hiển thị những gì agent đang thực hiện. Console cũng hiển thị cùng luồng này dưới dạng chat.

Sau đó app sẽ có tại http://s-<sandbox id>-3000.preview.localhost, trong đó 3000 là port bạn đã yêu cầu. Nếu sandbox đang ở trạng thái ngủ, request đầu tiên sẽ vào catch-all của Traefik. sandboxd khởi động container, chờ port phản hồi rồi hiển thị một trang chờ ngắn. Trang này sẽ tự refresh để chuyển sang app của bạn. Nếu preview không bao giờ rời khỏi trang đó, nghĩa là process bên trong không listen trên port được khai báo trong sandbox.yaml của app.

Đưa preview lên domain thật với HTTPS

Mỗi sandbox có một hostname riêng, nên một bản ghi DNS wildcard có thể bao phủ tất cả sandbox. Trỏ *.preview.yourdomain.com đến địa chỉ IP của server bằng bản ghi A. Sau đó đặt các biến preview trong .env tại ~/.sandboxd/src:

PREVIEW_DOMAIN=yourdomain.com
PREVIEW_ENTRYPOINT=websecure
PREVIEW_TLS=true
SANDBOXD_API_AUTH_DISABLED=false

Traefik cần cấu hình tương ứng: bật entrypoint websecure trong traefik/traefik.yml và thêm một certificate resolver. Dùng thử thách DNS-01, vì một wildcard certificate có thể bao phủ mọi hostname preview. Với HTTP-01, mỗi sandbox mới sẽ cần được cấp certificate riêng. Nếu build liên tục, bạn có thể nhanh chóng chạm giới hạn rate limit của Let's Encrypt. Wildcard certificate qua thử thách DNS-01 giải thích phần DNS.

cd ~/.sandboxd/src
docker compose up -d

URL preview sẽ có dạng https://s-<id>-3000.preview.yourdomain.com. Mở cổng 80 và 443 trên firewall, đồng thời không mở cổng 9090 ra Internet: xem các firewall rule cơ bản của ufw. Lưu ý rằng bất kỳ ai đoán được hostname preview đều có thể tải ứng dụng, vì vậy hãy xem preview là public.

Nếu muốn bỏ qua hoàn toàn domain, DNS và certificate, hiện maintainer đã cung cấp sandboxd Cloud. Dịch vụ này cấp cho server của bạn một địa chỉ HTTPS public dưới sandboxd.io với giá 9.99 đô la cho mỗi server mỗi tháng, hoặc 4.99 đô la với ưu đãi ra mắt, tính đến tháng 10 năm 2026. Hãy kiểm tra release cần dùng trước khi phụ thuộc vào dịch vụ này bằng cách pin vào v0.3.6.

Mã được tạo nằm ở đâu và có thể export không?

Trên host, trong data directory. Mỗi workspace là một directory thông thường tại /var/lib/sandboxed/workspaces/<id>/ trên bản cài v0.3.6, được bind mount vào container; các file của app nằm tại /home/sandbox/workspace/app bên trong sandbox. Trạng thái control plane nằm trong một file SQLite duy nhất tại state/sandboxd.db, còn credential của agent đã mã hóa nằm tại agent-auth/. Không có dữ liệu nào bị ẩn trong container layer, nên backup chỉ cần copy directory và file database đó. backup bằng restic trên VPS xử lý được cả hai.

sudo ls /var/lib/sandboxed/workspaces
sudo du -sh /var/lib/sandboxed/workspaces/*

Git export được tích hợp sẵn, không phải phần bổ sung rời. API cung cấp status và diff để đọc, sau đó là commit và push:

curl -s $API/v1/apps/$APP/git/status -H "$AUTH"

curl -s -XPOST $API/v1/apps/$APP/git/commit -H "$AUTH" \
  -H 'content-type: application/json' \
  -d '{"message":"todo list, first pass"}'

curl -s -XPOST $API/v1/apps/$APP/git/push -H "$AUTH" \
  -H 'content-type: application/json' -d '{"branch":"todo-first-pass"}'

Push luôn chuyển mã lên một branch mới. Bỏ qua branch thì mặc định sẽ dùng sandboxd/<slug>-<shortsha>. main, master và branch mà bạn import từ đó đều bị từ chối, vì vậy hãy merge ở phía remote.

Remote private cần personal access token. Bạn chỉ cần thiết lập token một lần trong console tại Settings, Git credentials. Token được lưu dưới dạng mã hóa và nằm ngoài sandbox, nên agent không thể đọc hoặc tự ý dùng token để push. Hãy push sớm và thường xuyên. Trước khi push, directory của workspace là bản sao duy nhất của mã nguồn, và DELETE /v1/apps/<id> sẽ xóa nó mà không thể khôi phục.

Chi phí build tính theo token của model là bao nhiêu?

sandboxd không đo mức chi tiêu của bạn, vì vậy con số cần theo dõi nằm trong console của provider. Các model OpenCode Zen miễn phí không tốn chi phí, nhưng chậm và yếu hơn model trả phí. Điều này thể hiện qua số vòng sửa lỗi nhiều hơn đối với mọi thứ phức tạp hơn một app thử nghiệm đơn giản.

Hóa đơn phụ thuộc vào cách agent loop hoạt động. Mỗi lượt gửi lại context cần thiết, vì vậy chi phí phụ thuộc vào số lượt, không phải số app. Một prompt cho kết quả ngay sẽ ít tốn kém. Nhưng 15 vòng yêu cầu “bây giờ sửa khoảng cách” trên một project có 50 file thì không, vì nội dung các file được gửi kèm trong mỗi lượt. Token input và output có cách tính giá khác nhau, và chi phí của coding agent cho mỗi session đưa ra khoảng chi phí thực tế. Hãy đặt giới hạn chi tiêu cứng tại provider trước khi giao quyền cho một loop chạy unattended.

Dọn dẹp sandbox không còn được sử dụng

Idle reaper sẽ dừng mọi sandbox đã idle quá SANDBOXD_IDLE_THRESHOLD_SECONDS. Giá trị mặc định là 2100 giây, tương đương 35 phút. Thao tác này giải phóng RAM nhưng giữ lại các file. Request tiếp theo đến preview URL sẽ đánh thức container. Hãy giảm giá trị này trên máy có ít tài nguyên, vì các container idle trong 35 phút sẽ chiếm dụng lượng memory mà bạn không thể dùng cho việc khác trong suốt thời gian đó.

Dừng không đồng nghĩa với xóa, và đây là nguyên nhân khiến disk âm thầm đầy lên. Sandbox đã dừng vẫn giữ workspace và container của nó. Xóa sandbox nhưng giữ lại app là DELETE trên sandbox. Thao tác này đồng thời xóa container và workspace. Xóa app sẽ xóa mọi thứ vĩnh viễn.

curl -s -XPOST $API/v1/sandboxes/$SB/stop -H "$AUTH"     # frees RAM, keeps files
curl -s -XDELETE $API/v1/sandboxes/$SB -H "$AUTH"        # container and workspace gone
curl -s -XDELETE $API/v1/apps/$APP -H "$AUTH"            # app and everything under it

Sau vài tuần thử nghiệm, docker system df sẽ hiển thị nhiều image space có thể reclaim hơn bạn dự kiến, vì mỗi app tự pull toolchain của mình đều để lại các layer. docker image prune sẽ xóa những layer dangling. Trước tiên hãy kiểm tra GET /v1/apps, vì image vẫn được sandbox đang sleep tham chiếu thì chưa phải garbage.

Ranh giới của container cung cấp và không cung cấp gì

Mỗi sandbox chạy dưới một user không có đặc quyền, với root filesystem chỉ đọc, toàn bộ Linux capabilities bị loại bỏ, đặt no-new-privileges, giới hạn bộ nhớ và giới hạn số process. Project nêu rõ giới hạn này: container Linux dùng chung kernel là một ranh giới cô lập mạnh nhưng là một ranh giới bảo mật yếu. Lỗ hổng trong kernel có thể dẫn đến việc host bị xâm nhập.

Có 2 điểm cần xử lý. Network egress từ sandbox đang được mở trong bản self-hosted, vì vậy code được tạo có thể truy cập internet, local network và các cloud metadata endpoint. Source có subsystem nftables egress nhưng subsystem này bị tắt khi build Docker Compose portable, nghĩa là các giới hạn phải do firewall trên host áp dụng. API của control plane về thực chất có quyền root trên host vì nó điều khiển Docker socket. API bind vào 127.0.0.1:9090 theo mặc định, SANDBOXD_API_AUTH_DISABLED phải giữ nguyên false, và tuyệt đối không được publish ra internet.

Nếu bạn định cho người khác gửi prompt đến máy của mình, riêng mô hình này quá yếu. Project đề xuất dùng gVisor với SANDBOXD_RUNTIME=runsc, đặt một kernel ở userspace giữa sandbox và host. Theo các phép đo của chính project, cách này khiến việc cài package chậm hơn khoảng 1.7 lần và các tác vụ sử dụng syscall nhiều chậm hơn khoảng 4 lần. Giải pháp mạnh hơn là dùng 1 máy cho mỗi tenant. Đây cũng là lập luận giống với chạy coding agent trong VM dùng một lần.

Bạn có nên xây dựng trên một project đã hai tháng tuổi không?

Với một máy dùng để build cá nhân thì có, nhưng vẫn phải áp dụng các biện pháp thận trọng rõ ràng: pin SANDBOXD_REF, sao lưu thư mục dữ liệu (/var/lib/sandboxed trên v0.3.6, /var/lib/sandboxd trên lần cài mới của v0.3.9 trở lên), và push mọi app bạn cần giữ lên một git remote. Với bất kỳ thứ gì khách hàng sẽ sử dụng, hãy chờ đến 1.0 hoặc dự trù khả năng phát sinh lỗi, vì maintainer nói rõ rằng 0.x có thể thay đổi mà không tương thích ngược. Maintainer cũng bán managed install, có giá 199 đô la để thiết lập và 79 đô la mỗi tháng để vận hành tính đến tháng 10 năm 2026. Đây là thông tin cần biết khi đánh giá liệu project có đủ lý do để tiếp tục tồn tại hay không.

Rủi ro này có thể chấp nhận được vì đầu ra của nó. sandboxd tạo ra một ứng dụng thông thường trong một git repository thông thường. Vì vậy, nếu project bị đình trệ, bạn vẫn giữ được code và chỉ mất wrapper. Đây là vị thế tốt hơn nhiều so với một hosted builder nắm quyền sở hữu project của bạn. Để có góc nhìn rộng hơn về những gì đáng được self-host trên server trong năm nay, xem những gì đáng tự host trong năm 2026.

FAQ

Thông số máy chủ tối thiểu cho sandboxd là gì?

Dự án cho biết 2 vCPU và 4 GB RAM là đủ để bắt đầu. Mức này đáp ứng control plane, Traefik và một sandbox nhỏ. Dùng 8 GB RAM và 40 GB disk nếu bạn muốn chạy đồng thời nhiều ứng dụng, vì mỗi sandbox đang chạy chứa một toolchain Node hoặc Python đầy đủ, còn mỗi workspace lưu riêng cây dependency của nó trên disk. Khi máy chủ thiếu tài nguyên, pressure reaper của sandboxd sẽ dừng các sandbox để giải phóng bộ nhớ. Nếu một build vượt quá memory ceiling của container, kernel sẽ kill tiến trình đó: docker ps -a hiển thị exit code 137.

sandboxd khác Dify hoặc OpenHands như thế nào?

Chúng tạo ra các loại artifact khác nhau. Dify xây dựng các ứng dụng gọi model khi runtime, chẳng hạn giao diện chat và pipeline retrieval. OpenHands chỉnh sửa một repository có sẵn bằng cách chạy command và đề xuất thay đổi cho code hiện có. sandboxd dựng khung cho một project hoàn toàn mới từ prompt, build project trong container riêng rồi phục vụ project tại một preview URL. Kết quả là một web application thông thường và không cần model để chạy.

Code do agent viết thực sự nằm ở đâu?

Code nằm trên filesystem của host, không nằm trong container image. Mỗi app có một directory tại /var/lib/sandboxed/workspaces/<id>/ trong bản cài v0.3.6 (/var/lib/sandboxd/workspaces/<id>/ trong bản cài mới v0.3.9 hoặc mới hơn). Directory này được bind mount vào sandbox, và các file xuất hiện tại /home/sandbox/workspace/app bên trong sandbox. State của control plane là một file SQLite duy nhất nằm tại state/ trong cùng data directory. Bạn có thể commit và push lên một branch mới trên git remote từ tab Git của console, hoặc thông qua các endpoint /v1/apps/<id>/git/commit và /git/push. Token dùng cho remote private được control plane lưu dưới dạng encrypted, không chuyển cho sandbox.

Có an toàn không khi cho sandboxd truy cập Internet?

Chỉ expose các preview URL và console, không expose control plane API. API này điều khiển Docker trên host nên tương đương với quyền root. Vì lý do đó, API bind vào 127.0.0.1:9090 theo mặc định. Trong bản self-hosted, sandbox cũng có network egress mở. Điều này có nghĩa code do agent viết có thể truy cập mạng nội bộ và các cloud metadata endpoint của bạn. Vì vậy, hãy thêm rule cho host firewall nếu máy đó nằm cùng mạng với các hệ thống cần bảo vệ. Với prompt từ những người bạn không tin tưởng, hãy chạy mỗi tenant trên một host riêng thay vì chỉ dựa vào ranh giới container.

#sandboxd#ai-agents#self-hosted#app-builder#Docker