วิธีติดตั้ง sandboxd บน VPS ของคุณเองแบบครบวงจร
เรียนรู้วิธีรัน sandboxd เครื่องมือสร้างแอปด้วย AI บน VPS ส่วนตัว ตั้งแต่การตั้งค่า Docker, Traefik v3, การจัดการ model keys ไปจนถึงการเคลียร์ sandbox ที่ค้างอยู่เพื่อประหยัดทรัพยากร
sandboxd คืออะไรและคุณจะได้อะไรจากการรันด้วยตนเอง
ในการ self-host sandboxd คุณต้องมีเซิร์ฟเวอร์ Linux หนึ่งเครื่องที่ติดตั้ง Docker และชื่อโดเมน เมื่อคุณส่ง prompt ตัว coding agent จะสร้างแอปพลิเคชันจริงขึ้นมาภายในคอนเทนเนอร์ที่แยกส่วน และแอปพลิเคชันนั้นจะปรากฏขึ้นที่ URL สำหรับดูตัวอย่าง (preview URL) ของตัวเอง เครื่องมือสร้างแอปจาก prompt เป็นหมวดหมู่บริการที่ได้รับความนิยมสูงสุดในปี 2026 และ sandboxd คือเครื่องมือที่คุณสามารถรันบน VPS ของคุณเองได้ภายใต้สัญญาอนุญาต MIT โดยที่โค้ดที่ถูกสร้างขึ้นจะถูกจัดเก็บไว้บนดิสก์ของคุณเอง
การออกแบบนี้มีขนาดเล็กโดยเจตนา โดยมี Go control plane ทำหน้าที่ควบคุม Docker, Traefik v3 ทำหน้าที่กำหนดเส้นทาง (route) ให้กับชื่อโฮสต์ของตัวอย่างแอปแต่ละรายการ, SQLite ทำหน้าที่เก็บสถานะ และแต่ละแอปจะรันอยู่ภายในหนึ่งคอนเทนเนอร์ ระบบนี้ไม่มี Kubernetes และไม่มีเซิร์ฟเวอร์ฐานข้อมูลแยกต่างหาก ซึ่งเป็นเหตุผลว่าทำไมเซิร์ฟเวอร์ขนาด 2 vCPU จึงสามารถรันระบบนี้ได้
โมเดลทั้งหมดขับเคลื่อนด้วยวัตถุ 4 ประเภท: app คือโปรเจกต์ที่คงอยู่ถาวร โดยเก็บชื่อ, ข้อมูล metadata ของ git และความลับ (secrets) ต่างๆ ไว้, sandbox คือคอนเทนเนอร์ Docker ที่แอปนั้นรันอยู่ โดยแอปหนึ่งตัวจะชี้ไปยัง sandbox ได้ทีละหนึ่งรายการ, workspace คือไฟล์ของแอปซึ่งอาศัยอยู่บนโฮสต์และยังคงอยู่แม้คอนเทนเนอร์จะหยุดทำงาน, และ task คือ prompt หนึ่งรายการที่ส่งให้กับ agent ภายใน sandbox การหยุด sandbox จะช่วยคืนหน่วยความจำแต่ยังคงเก็บไฟล์ไว้ ส่วนการทำลาย sandbox จะเป็นการลบคอนเทนเนอร์ทิ้ง ซึ่งแอปสามารถเริ่มการทำงานของคอนเทนเนอร์ใหม่ได้ในภายหลัง
sandboxd แตกต่างจาก Dify และ OpenHands อย่างไร
ทั้งสามโปรเจกต์นี้มักถูกเข้าใจผิดเนื่องจากต่างก็รัน LLM (large language model) บนเซิร์ฟเวอร์ของคุณ แต่ผลลัพธ์ที่ได้นั้นแตกต่างกัน Dify สร้างแอปพลิเคชัน LLM: เช่น อินเทอร์เฟซแชท, ไปป์ไลน์การดึงข้อมูล (retrieval pipelines) และเวิร์กโฟลว์ที่เรียกใช้โมเดลทุกครั้งที่มีการใช้งาน โดยตัวโมเดลจะเป็นส่วนหนึ่งของผลิตภัณฑ์สำเร็จรูปนั้น OpenHands ทำงานบน repository ที่คุณมีอยู่แล้ว: คุณระบุตำแหน่งโค้ดให้มัน จากนั้นมันจะอ่านไฟล์ รันคำสั่ง และเสนอการเปลี่ยนแปลง ส่วน sandboxd เริ่มต้นจากศูนย์ มันจะสร้างโครงร่างโปรเจกต์จากค่าที่ตั้งไว้ล่วงหน้า (preset) สร้างโปรเจกต์ในคอนเทนเนอร์ใหม่ และให้ URL เพื่อให้คุณเข้าชม ผลลัพธ์ที่ได้คือแอปพลิเคชัน React หรือ FastAPI ทั่วไปที่ไม่จำเป็นต้องใช้โมเดลในการรัน
ดังนั้น ให้เลือกตามสิ่งที่คุณต้องการในตอนท้าย sandboxd เหมาะสำหรับการเริ่มต้นจากประโยคคำสั่งและเก็บโค้ดไว้ใช้งานต่อ ส่วนอีกสองตัวเหมาะสำหรับกรณีที่มี repository หรือผลิตภัณฑ์ที่ขับเคลื่อนด้วยโมเดลอยู่แล้ว
ความแตกต่างอีกประการหนึ่งคืออายุของโปรเจกต์ ซึ่งเป็นสิ่งที่ควรพิจารณาก่อนที่จะสร้างสิ่งใดที่สำคัญบนโปรเจกต์นั้น
ข้อมูลเบื้องหลังแผนภูมินี้
[
{
"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 มีคะแนน 875 stars เทียบกับ 83,091 สำหรับ OpenHands และ 151,320 สำหรับ Dify ตัว repository ถูกสร้างขึ้นเมื่อวันที่ 3 มิถุนายน 2026 จึงมีอายุเพียงสองเดือน ณ เดือนสิงหาคม 2026 ในขณะที่ OpenHands เริ่มต้นตั้งแต่เดือนมีนาคม 2024 และ Dify ตั้งแต่เดือนเมษายน 2023 โดยรุ่น v0.1.0 ปล่อยออกมาเมื่อวันที่ 6 มิถุนายน 2026 และ v0.3.6 เมื่อวันที่ 1 สิงหาคม 2026 โปรเจกต์นี้ระบุสถานะว่าเป็นเบต้าและแจ้งว่ารุ่น 0.x อาจมีการเปลี่ยนแปลงที่ส่งผลต่อความเข้ากันได้ (compatibility) ให้มองตัวเลขเหล่านี้เป็นความเสี่ยงด้าน dependency มากกว่าการตัดสินคุณภาพ เพราะโปรเจกต์ที่มีอายุสองเดือนย่อมผ่านการตรวจสอบบั๊กจากผู้อื่นมาเพียงสองเดือนเท่านั้น
สิ่งที่เซิร์ฟเวอร์จำเป็นต้องมี และสิ่งที่มักจะล้มเหลวเมื่อทรัพยากรไม่เพียงพอ
โครงการระบุว่า vCPU 2 คอร์ และ RAM 4 GB เพียงพอสำหรับการเริ่มต้น ซึ่งเป็นข้อมูลที่ถูกต้องสำหรับ control plane และ sandbox ขนาดเล็กหนึ่งรายการ แต่ไม่เพียงพอสำหรับผู้ใช้สองคนที่กำลังพัฒนาพร้อมกัน คุณควรจัดสรรหน่วยความจำโดยแบ่งเป็นส่วนๆ Traefik และ Go control plane ใช้ทรัพยากรน้อย แต่ sandbox แต่ละรายการที่ทำงานอยู่จะบรรจุ toolchain ของ Node หรือ Python ไว้เต็มรูปแบบ โดยจุดสูงสุดของการใช้ทรัพยากรจะเกิดขึ้นในช่วง npm install ตามด้วยการ build เพื่อใช้งานจริง ควรวางแผนใช้ RAM 8 GB สำหรับเซิร์ฟเวอร์ที่ต้องรันแอปพลิเคชันหลายรายการ และให้มองว่า swap เป็นเพียงตาข่ายรองรับความปลอดภัย ไม่ใช่ความจุหลัก เพราะการ build ที่ต้องอาศัย swap จะใช้เวลาหลายนาทีแทนที่จะเป็นไม่กี่วินาที
เมื่อหน่วยความจำหมด คุณจะพบความล้มเหลวสองรูปแบบที่แตกต่างกันอย่างสิ้นเชิง ภายใน sandbox คอนเทนเนอร์จะถึงขีดจำกัด --memory ที่ sandboxd กำหนดไว้ และ kernel จะสั่งยุติกระบวนการที่ใช้หน่วยความจำมากที่สุด ส่งผลให้การ build ล้มเหลวโดยไม่มีข้อความแจ้งเตือนที่เป็นประโยชน์จาก agent โดย docker ps -a จะแสดง exit code 137 สำหรับคอนเทนเนอร์นั้น และ docker inspect จะรายงานสถานะเป็น "OOMKilled": true การ build ด้วย Node ที่ล้มเหลวในลักษณะนี้มักจะแสดงข้อความ JavaScript heap out of memory ออกมาก่อน
ความล้มเหลวรูปแบบที่สองเกิดขึ้นที่ระดับโฮสต์ sandboxd จะรัน pressure reaper เพื่อหยุดการทำงานของ sandbox เมื่อหน่วยความจำของโฮสต์เหลือน้อย ดังนั้นบนเซิร์ฟเวอร์ขนาดเล็ก sandbox อาจหายไปในขณะที่คุณกำลังดูตัวอย่าง (preview) ของแอปพลิเคชัน ไฟล์ต่างๆ ยังคงปลอดภัยและการเรียกใช้งานผ่าน URL ของ preview ในครั้งถัดไปจะปลุกให้ sandbox กลับมาทำงานอีกครั้ง แต่ภารกิจที่กำลังรันอยู่ขณะที่คอนเทนเนอร์หยุดทำงานจะไม่กลับมาทำงานต่อ
พื้นที่จัดเก็บข้อมูลเป็นปัญหาที่เงียบเชียบกว่า แอปพลิเคชันแต่ละรายการจะเก็บ workspace ของตนเองไว้บนโฮสต์ และโปรเจกต์ JavaScript มักจะมีโครงสร้าง node_modules ขนาดหลายร้อยเมกะไบต์ แอปพลิเคชัน 10 รายการอาจใช้พื้นที่หลายกิกะไบต์สำหรับ dependency ก่อนที่จะนับรวมไฟล์ image ต่างๆ ควรเริ่มต้นที่ 40 GB และคอยตรวจสอบพื้นที่ใช้งาน:
docker system df
sudo du -sh /var/lib/sandboxed/workspacesใน v0.3.6 ซึ่งเป็นรุ่นที่คู่มือนี้อ้างอิง ไดเรกทอรีข้อมูลเริ่มต้นคือ /var/lib/sandboxed ซึ่งสะกดโดยมี e เพิ่มเข้ามา การพิมพ์ /var/lib/sandboxd ในตำแหน่งดังกล่าวจะไม่พบข้อมูลใดๆ และอาจทำให้คุณเสียเวลาตรวจสอบอย่างสับสนถึงห้านาที ข้อมูลนี้มีการเปลี่ยนแปลงใน v0.3.9 (25 สิงหาคม 2026) ตัวติดตั้งรุ่นใหม่จะติดตั้งข้อมูลลงใน /var/lib/sandboxd และเก็บ /var/lib/sandboxed ไว้เฉพาะสำหรับการติดตั้งที่มีอยู่เดิมเท่านั้น สำหรับเซิร์ฟเวอร์ที่ติดตั้งด้วยรุ่นใหม่กว่า ให้ใช้ path ที่ไม่มี e ในทุกคำสั่งด้านล่างนี้
การติดตั้ง sandboxd รุ่นที่กำหนดเวอร์ชันไว้
ต้องติดตั้ง Docker Engine พร้อมปลั๊กอิน Compose และ git ลงบนเซิร์ฟเวอร์ก่อน การติดตั้ง Docker บน VPS ครอบคลุมขั้นตอนดังกล่าวแล้ว
docker compose version
git --versionทั้งสองคำสั่งต้องแสดงเวอร์ชันออกมา หากขึ้น docker: 'compose' is not a docker command แสดงว่าปลั๊กอิน Compose v2 หายไป ตัวติดตั้งจะเลือกใช้ปลั๊กอินเป็นอันดับแรก แต่จะถอยกลับไปใช้ไบนารี docker-compose แบบแยกเดี่ยวหากมีการติดตั้งไว้ และจะหยุดทำงานพร้อมแจ้ง Docker Compose not found ก็ต่อเมื่อไม่พบทั้งสองอย่าง คำสั่งในคู่มือนี้ใช้ docker compose ดังนั้นการติดตั้งปลั๊กอินจึงเป็นวิธีแก้ไขที่ง่ายที่สุด
ตัวติดตั้งเป็นเชลล์สคริปต์ที่ดึงผ่านเครือข่าย ดังนั้นควรตรวจสอบเนื้อหาก่อนเรียกใช้งาน และกำหนดเวอร์ชันให้ชัดเจน
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.shSANDBOXD_REF คือ git ref ที่ตัวติดตั้งจะ checkout ลงใน $HOME/.sandboxd/src โดยค่าเริ่มต้นคือ main การไม่กำหนดค่านี้จะทำให้การติดตั้งของคุณเป็นเวอร์ชันล่าสุดที่ถูก merge เข้ามาในเช้าวันนั้น ซึ่งเป็นเรื่องสำคัญสำหรับโปรเจกต์ที่มีการปล่อยรุ่นถึงหกครั้งในเดือนกรกฎาคม 2026 เพียงเดือนเดียว ให้กำหนดเวอร์ชันไว้ แล้วค่อยอัปเกรดด้วยความตั้งใจหลังจากอ่านบันทึกการเปลี่ยนแปลง (changelog) แล้ว ณ วันที่ 12 ตุลาคม 2026 รุ่นล่าสุดคือ v0.3.22 ซึ่งใหม่กว่ารุ่น v0.3.6 ที่กำหนดไว้ที่นี่ถึงสิบหกรุ่น
สคริปต์จะทำการ clone ซอร์สโค้ด, build อิมเมจ, เริ่ม stack ด้วย docker compose up -d และแสดง URL ของคอนโซลพร้อม API token ในตอนท้าย ให้บันทึก token นั้นไว้ในที่ปลอดภัย เพราะเป็นข้อมูลรับรองสำหรับ API ที่ใช้ควบคุม Docker ในสิทธิ์ root
curl http://127.0.0.1:9090/healthzคำสั่งดังกล่าวจะแสดง ok เมื่อ control plane พร้อมทำงาน หากไม่แสดงผลใดๆ แสดงว่า stack ไม่ได้เริ่มทำงาน ให้รัน docker compose ps จาก ~/.sandboxd/src เพื่อดูว่าบริการใดหยุดทำงาน จากนั้นใช้ docker compose logs sandboxd เพื่อดูสาเหตุ
การเข้าถึงคอนโซลบนเครื่องระยะไกล
คอนโซลจะถูกให้บริการผ่าน Traefik บน HTTP_PORT ซึ่งโดยปกติคือพอร์ต 80 ที่ชื่อโฮสต์ http://console.localhost เนื่องจาก Traefik ทำการกำหนดเส้นทางตามชื่อโฮสต์ การระบุ IP address ของเซิร์ฟเวอร์ในเบราว์เซอร์จึงไม่ตรงกับกฎใดๆ และจะส่งผลให้เกิดข้อผิดพลาด 404 จนกว่าคุณจะตั้งค่าโดเมนจริง ให้ทำการ forward พอร์ตและคงชื่อโฮสต์ไว้ดังนี้:
ssh -L 8080:127.0.0.1:80 you@your-vpsจากนั้นเปิด http://console.localhost:8080 บนแล็ปท็อปของคุณ บน Linux และ macOS ชื่อใดก็ตามที่ลงท้ายด้วย .localhost จะถูกแปลงเป็น 127.0.0.1 ดังนั้นคำขอจะถูกส่งผ่านอุโมงค์ (tunnel) ไปพร้อมกับส่วนหัว Host ที่ถูกต้อง ให้ตั้งรหัสผ่านสำหรับคอนโซลในการเข้าใช้งานครั้งแรก
กำหนดโมเดลให้กับเอเจนต์
อิมเมจพื้นฐานมาพร้อมกับเอเจนต์เขียนโค้ด 2 ตัว ได้แก่ OpenCode และ Claude Code โดย SANDBOXD_DEFAULT_AGENT จะเป็นตัวตัดสินใจเลือกเอเจนต์สำหรับงานที่ไม่ได้ระบุชื่อไว้ และค่าเริ่มต้นคือ opencode หากยังไม่ได้เชื่อมต่อคีย์ใดๆ งานจะรันบนโมเดลฟรีแบบไม่ใช้คีย์ของ OpenCode Zen ดังนั้นการบิลด์ครั้งแรกของคุณจะไม่มีค่าใช้จ่าย และคุณสามารถทดสอบกระบวนการทำงานทั้งหมดได้ก่อนที่จะเริ่มเสียค่าใช้จ่ายใดๆ
เชื่อมต่อคีย์ของคุณเองเมื่อต้องการใช้โมเดลที่มีประสิทธิภาพสูงขึ้น คีย์จะถูกส่งไปยัง control plane และไม่เคยถูกส่งเข้าไปใน sandbox โดยคีย์จะถูกจัดเก็บแบบเข้ารหัสไว้ภายใต้ data directory และถูกส่งผ่านเครือข่ายโดย credential proxy ดังนั้นทั้งตัวเอเจนต์และโค้ดที่เอเจนต์เขียนขึ้นจะไม่สามารถอ่านคีย์เหล่านี้ได้
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-..."}'คุณสามารถดำเนินการแบบเดียวกันได้ผ่านคอนโซลในเมนู Settings แล้วเลือก AI Agents ซึ่งรวมถึงขั้นตอนการทำ OAuth แบบมีคำแนะนำ หากคุณต้องการใช้การสมัครสมาชิก Claude แทนการใช้ API key โดยโมเดลเริ่มต้นของแต่ละเอเจนต์จะอยู่ในแผงควบคุมเดียวกัน และคุณสามารถกำหนดโมเดลใหม่สำหรับงานเฉพาะเจาะจงได้ในขณะสั่งงาน
สร้างแอปขนาดเล็กแบบครบวงจร
สร้างแอปพลิเคชัน เริ่มการทำงานของ sandbox จากนั้นส่งคำสั่ง (prompt) ระบบจะส่งคืนค่า id ในรูปแบบ JSON และคู่มือเริ่มต้นใช้งานจะดึงค่าเหล่านั้นออกมาด้วย sed ดังนั้นคุณจึงไม่จำเป็นต้องติดตั้ง 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"ตัวแปรทั้งสองต้องมีค่า id หาก $SB ว่างเปล่า หมายความว่า sandbox ไม่ได้เริ่มทำงาน ซึ่งสาเหตุทั่วไปคือ base image ยังคงอยู่ในระหว่างการสร้าง หรือโฮสต์มีหน่วยความจำไม่เพียงพอ หากพบ 401 แทนที่จะเป็น id แสดงว่า bearer token ไม่ถูกต้อง
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"}'การตอบกลับจะมี task id อยู่ด้วย GET /v1/sandboxes/$SB/tasks/<task id> จะส่งคืนผลลัพธ์ของงานนั้น และ path /events บน task เดียวกันจะเป็นสตรีม SSE (server sent events) แบบสดที่แสดงการทำงานของ agent คอนโซลจะแสดงสตรีมเดียวกันนี้ในรูปแบบแชท
จากนั้นแอปจะอยู่ที่ http://s-<sandbox id>-3000.preview.localhost โดยที่ 3000 คือพอร์ตที่คุณระบุไว้ หาก sandbox อยู่ในสถานะพัก คำขอแรกจะถูกส่งไปยัง catch-all ของ Traefik จากนั้น sandboxd จะเริ่มคอนเทนเนอร์ รอจนกว่าพอร์ตจะตอบสนอง และแสดงหน้า warming page สั้นๆ ซึ่งจะรีเฟรชเข้าสู่แอปของคุณโดยอัตโนมัติ หากหน้าตัวอย่างค้างอยู่ที่หน้านั้นตลอดเวลา แสดงว่ากระบวนการภายในไม่ได้ฟัง (listen) บนพอร์ตที่ประกาศไว้ใน sandbox.yaml ของแอป
การใช้งานพรีวิวบนโดเมนจริงด้วย HTTPS
Sandbox แต่ละรายการจะมีชื่อโฮสต์เป็นของตนเอง ดังนั้นคุณสามารถใช้ DNS record แบบ wildcard เพียงรายการเดียวเพื่อครอบคลุมทั้งหมดได้ ให้ชี้ *.preview.yourdomain.com ไปยัง IP address ของเซิร์ฟเวอร์ด้วย A record จากนั้นกำหนดค่าตัวแปรพรีวิวใน .env ภายในไฟล์ ~/.sandboxd/src:
PREVIEW_DOMAIN=yourdomain.com
PREVIEW_ENTRYPOINT=websecure
PREVIEW_TLS=true
SANDBOXD_API_AUTH_DISABLED=falseTraefik จำเป็นต้องมีการตั้งค่าในส่วนที่สอดคล้องกัน: ให้เปิดใช้งาน entrypoint websecure ใน traefik/traefik.yml และเพิ่ม certificate resolver โดยแนะนำให้ใช้การตรวจสอบสิทธิ์แบบ DNS-01 เนื่องจาก certificate แบบ wildcard เพียงใบเดียวจะครอบคลุมชื่อโฮสต์ของพรีวิวทั้งหมด หากใช้ HTTP-01 ตัว sandbox ใหม่แต่ละรายการจะต้องทำการออก certificate แยกกัน ซึ่งจะทำให้คุณติดข้อจำกัดด้านอัตราการร้องขอ (rate limits) ของ Let's Encrypt ได้อย่างรวดเร็วหากมีการใช้งานหนาแน่น การใช้ Wildcard certificates ผ่านการตรวจสอบสิทธิ์แบบ DNS-01 อธิบายรายละเอียดในส่วนของ DNS ไว้แล้ว
cd ~/.sandboxd/src
docker compose up -dURL ของพรีวิวจะเป็น https://s-<id>-3000.preview.yourdomain.com ให้เปิดพอร์ต 80 และ 443 บนไฟร์วอลล์ และปิดพอร์ต 9090 ไม่ให้เข้าถึงจากภายนอก: ดูรายละเอียดที่ กฎพื้นฐานของ ufw firewall โปรดจำไว้ว่าใครก็ตามที่สามารถเดาชื่อโฮสต์ของพรีวิวได้จะสามารถโหลดแอปพลิเคชันนั้นได้ ดังนั้นให้ถือว่าพรีวิวเป็นบริการสาธารณะ
หากคุณต้องการข้ามขั้นตอนการตั้งค่าโดเมน, DNS และ certificate ทั้งหมด ผู้พัฒนาได้เปิดให้บริการ sandboxd Cloud ซึ่งจะมอบที่อยู่ HTTPS สาธารณะภายใต้ sandboxd.io ให้กับเซิร์ฟเวอร์ของคุณ ในราคา 9.99 ดอลลาร์ต่อเซิร์ฟเวอร์ต่อเดือน หรือ 4.99 ดอลลาร์หากใช้ส่วนลดช่วงเปิดตัว (ข้อมูล ณ เดือนตุลาคม 2026) โปรดตรวจสอบเวอร์ชันที่รองรับก่อนตัดสินใจใช้งานหากคุณมีการล็อกเวอร์ชันไว้ที่ v0.3.6
โค้ดที่สร้างขึ้นจะถูกจัดเก็บไว้ที่ใด และสามารถส่งออกได้หรือไม่
บนโฮสต์ โค้ดจะถูกจัดเก็บไว้ภายใต้ไดเรกทอรีข้อมูล โดยแต่ละเวิร์กสเปซจะเป็นไดเรกทอรีปกติที่ /var/lib/sandboxed/workspaces/<id>/ สำหรับการติดตั้งเวอร์ชัน v0.3.6 ซึ่งจะถูก bind mount เข้าไปในคอนเทนเนอร์ และไฟล์ของแอปพลิเคชันจะอยู่ที่ /home/sandbox/workspace/app ภายในแซนด์บ็อกซ์ สถานะของ control plane จะอยู่ในไฟล์ SQLite ไฟล์เดียวที่ state/sandboxd.db และข้อมูลรับรองของเอเจนต์ที่เข้ารหัสไว้จะอยู่ที่ agent-auth/ ข้อมูลทั้งหมดไม่ได้ถูกซ่อนไว้ภายในเลเยอร์ของคอนเทนเนอร์ ดังนั้นการสำรองข้อมูลจึงทำได้โดยการคัดลอกไดเรกทอรีและไฟล์ฐานข้อมูลดังกล่าว การสำรองข้อมูลด้วย restic บน VPS สามารถจัดการทั้งสองส่วนนี้ได้
sudo ls /var/lib/sandboxed/workspaces
sudo du -sh /var/lib/sandboxed/workspaces/*การส่งออกผ่าน Git เป็นฟีเจอร์ที่มีมาให้ในตัว ไม่ใช่ส่วนเสริม โดย API จะเปิดให้เข้าถึงสถานะและ diff เพื่ออ่านข้อมูล จากนั้นจึงทำการ commit และ 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 จะส่งไปยัง branch ใหม่เสมอ หากเว้นว่าง branch ไว้ ระบบจะใช้ค่าเริ่มต้นเป็น sandboxd/<slug>-<shortsha> สำหรับ main, master และ branch ที่คุณนำเข้าข้อมูลมานั้นจะถูกปฏิเสธ ดังนั้นให้ทำการ merge ที่ฝั่งรีโมท
รีโมทแบบส่วนตัวจำเป็นต้องใช้ personal access token ซึ่งต้องตั้งค่าเพียงครั้งเดียวในคอนโซลภายใต้เมนู Settings, Git credentials ข้อมูลนี้จะถูกจัดเก็บโดยการเข้ารหัสและแยกออกจากแซนด์บ็อกซ์ เพื่อป้องกันไม่ให้เอเจนต์อ่านหรือใช้ข้อมูลนี้เพื่อ push โดยที่คุณไม่ทราบ ควรทำการ push บ่อยๆ และตั้งแต่เนิ่นๆ เพราะจนกว่าคุณจะทำเช่นนั้น ไดเรกทอรีเวิร์กสเปซจะเป็นสำเนาเดียวของโค้ด และคำสั่ง DELETE /v1/apps/<id> จะลบข้อมูลดังกล่าวทิ้งโดยไม่มีการเตือนหรือกู้คืนได้
การสร้างโปรเจกต์มีค่าใช้จ่ายเป็นโทเค็นของโมเดลเท่าใด
sandboxd ไม่ได้วัดปริมาณการใช้งานของคุณ ดังนั้นตัวเลขที่สำคัญจึงอยู่ในคอนโซลของผู้ให้บริการโมเดลของคุณ โมเดล OpenCode Zen แบบฟรีไม่มีค่าใช้จ่าย แต่จะทำงานช้าและมีประสิทธิภาพต่ำกว่าโมเดลแบบเสียค่าใช้จ่าย ซึ่งจะส่งผลให้ต้องมีการแก้ไขหลายรอบมากขึ้นในโปรเจกต์ที่ซับซ้อนกว่าแอปพลิเคชันทดลอง
รูปแบบของค่าใช้จ่ายจะขึ้นอยู่กับการทำงานของ agent loop ในแต่ละรอบการทำงาน ระบบจะส่งบริบทที่จำเป็นกลับไปใหม่เสมอ ดังนั้นค่าใช้จ่ายจึงขึ้นอยู่กับจำนวนรอบการทำงาน ไม่ใช่จำนวนแอปพลิเคชัน การส่ง prompt เพียงครั้งเดียวแล้วสำเร็จจะมีราคาถูก แต่การแก้ไข 15 รอบในหัวข้อ "แก้ไขระยะห่าง" สำหรับโปรเจกต์ที่มีไฟล์ 50 ไฟล์จะมีราคาสูง เนื่องจากเนื้อหาของไฟล์ทั้งหมดจะถูกส่งไปด้วยทุกครั้ง Input และ output tokens มีราคาที่แตกต่างกัน และ ค่าใช้จ่ายของ coding agent ต่อเซสชัน จะแสดงช่วงราคาที่เกิดขึ้นจริง คุณควรตั้งค่าจำกัดการใช้จ่ายสูงสุดไว้ที่ฝั่งผู้ให้บริการก่อนที่จะปล่อยให้ loop ทำงานโดยไม่มีการดูแล
การล้าง sandbox ที่ค้างอยู่
idle reaper จะหยุดการทำงานของ sandbox ใดก็ตามที่ไม่มีการใช้งานเกินกว่า SANDBOXD_IDLE_THRESHOLD_SECONDS ซึ่งค่าเริ่มต้นคือ 2100 วินาที หรือ 35 นาที การดำเนินการนี้จะคืนหน่วยความจำ RAM แต่ยังคงเก็บไฟล์ไว้ และเมื่อมีการร้องขอไปยัง preview URL อีกครั้ง คอนเทนเนอร์จะถูกปลุกขึ้นมาใหม่ หากคุณใช้เซิร์ฟเวอร์ขนาดเล็กควรลดค่านี้ลง เนื่องจากคอนเทนเนอร์ที่ไม่ได้ใช้งานนาน 35 นาที หมายถึงหน่วยความจำที่คุณไม่สามารถนำไปใช้ประโยชน์ได้นานถึง 35 นาที
การหยุดการทำงานไม่ใช่การลบ และนี่คือสาเหตุที่ทำให้ดิสก์เต็มโดยไม่รู้ตัว sandbox ที่ถูกหยุดการทำงานยังคงครอบครอง workspace และคอนเทนเนอร์ของตนเองอยู่ การลบ sandbox แต่ยังคงเก็บแอปไว้คือการทำ DELETE บน sandbox ซึ่งจะเป็นการลบทั้งคอนเทนเนอร์และ workspace ออกไปพร้อมกัน แต่หากลบแอปทิ้งจะเป็นการลบทุกอย่างออกอย่างถาวร
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หลังจากผ่านการทดลองไปสองสามสัปดาห์ docker system df จะแสดงพื้นที่ของ image ที่สามารถเรียกคืนได้มากกว่าที่คุณคาดไว้ เนื่องจากทุกแอปที่ดึง toolchain ของตัวเองมาใช้งานจะทิ้ง layer ต่างๆ ไว้เบื้องหลัง docker image prune จะทำการล้าง layer ที่ค้างอยู่เหล่านี้ออกไป ให้ตรวจสอบ GET /v1/apps ก่อนเสมอ เนื่องจาก image ที่ยังถูกอ้างอิงโดย sandbox ที่อยู่ในสถานะ sleeping จะไม่ถือว่าเป็นขยะ
ขอบเขตการทำงานของคอนเทนเนอร์และสิ่งที่ไม่ได้มอบให้
sandbox แต่ละตัวจะทำงานในฐานะผู้ใช้ที่ไม่มีสิทธิ์ (unprivileged user) โดยมีระบบไฟล์ root แบบอ่านอย่างเดียว (read-only) พร้อมทั้งตัด Linux capabilities ทั้งหมดออก, ตั้งค่า no-new-privileges, กำหนดเพดานหน่วยความจำ และจำกัดจำนวนโพรเซส โครงการนี้ระบุไว้อย่างชัดเจนถึงข้อจำกัดดังกล่าวว่า คอนเทนเนอร์ Linux ที่ใช้ kernel ร่วมกันนั้นเป็นขอบเขตการแยกส่วน (isolation) ที่แข็งแกร่ง แต่เป็นขอบเขตความปลอดภัยที่อ่อนแอ หากเกิดช่องโหว่ใน kernel จะส่งผลให้โฮสต์ถูกบุกรุกได้
มีข้อเท็จจริงสองประการที่ต้องดำเนินการจัดการ ประการแรก การเชื่อมต่อเครือข่ายขาออก (egress) จาก sandbox ในรุ่น self-hosted นั้นเปิดกว้าง ทำให้โค้ดที่ถูกสร้างขึ้นสามารถเข้าถึงอินเทอร์เน็ต, เครือข่ายภายในของคุณ และ endpoint ของ cloud metadata ได้ ระบบย่อย nftables สำหรับควบคุมขาออกมีอยู่ในซอร์สโค้ด แต่ถูกปิดการคอมไพล์ไว้ในรุ่น Docker Compose แบบพกพา ซึ่งหมายความว่าข้อจำกัดต่างๆ จะต้องถูกควบคุมผ่าน firewall ของโฮสต์แทน ประการที่สอง control plane API มีสิทธิ์เทียบเท่า root ของโฮสต์ เนื่องจากทำหน้าที่ควบคุม Docker socket โดยค่าเริ่มต้นจะผูกกับ 127.0.0.1:9090 และ SANDBOXD_API_AUTH_DISABLED จะต้องคงค่าเป็น false ไว้เสมอ รวมถึงไม่ควรเปิดเผย API นี้สู่สาธารณะบนอินเทอร์เน็ตโดยเด็ดขาด
หากคุณวางแผนที่จะอนุญาตให้ผู้อื่นส่งคำสั่ง (prompt) เข้ามายังระบบของคุณ โมเดลนี้เพียงอย่างเดียวถือว่าไม่เพียงพอ โครงการแนะนำให้ใช้ gVisor ร่วมกับ SANDBOXD_RUNTIME=runsc ซึ่งจะทำหน้าที่เป็น kernel ในระดับ userspace คั่นกลางระหว่าง sandbox กับโฮสต์ จากการวัดผลของโครงการเอง พบว่าการติดตั้งแพ็กเกจจะช้าลงประมาณ 1.7 เท่า และงานที่ต้องเรียกใช้ syscall จำนวนมากจะช้าลงประมาณ 4 เท่า คำตอบที่แข็งแกร่งกว่าคือการแยกเครื่องต่อผู้ใช้งานหนึ่งราย ซึ่งเป็นหลักการเดียวกับ การรัน coding agents ใน VM แบบใช้แล้วทิ้ง
ควรสร้างโปรเจกต์บนซอฟต์แวร์ที่มีอายุ 2 เดือนหรือไม่?
สำหรับเครื่อง build ส่วนตัว คำตอบคือได้ โดยต้องระมัดระวังตามปกติ: ให้ตรึงเวอร์ชันของ SANDBOXD_REF ไว้, สำรองข้อมูลในไดเรกทอรีข้อมูล (/var/lib/sandboxed ใน v0.3.6, /var/lib/sandboxd ในการติดตั้งใหม่เวอร์ชัน v0.3.9 ขึ้นไป) และ push แอปพลิเคชันทุกตัวที่คุณให้ความสำคัญไปยัง git remote สำหรับงานใดก็ตามที่เกี่ยวข้องกับลูกค้า ให้รอจนกว่าจะถึงเวอร์ชัน 1.0 หรือเตรียมงบประมาณไว้สำหรับกรณีที่ระบบเสียหาย เพราะผู้ดูแลโครงการระบุไว้อย่างชัดเจนว่าเวอร์ชัน 0.x อาจมีการเปลี่ยนแปลงได้ตลอดเวลา นอกจากนี้ ผู้ดูแลโครงการยังมีบริการติดตั้งแบบจัดการให้ (managed install) โดยมีค่าใช้จ่าย 199 ดอลลาร์สำหรับการตั้งค่า และ 79 ดอลลาร์ต่อเดือนสำหรับการดูแลรักษา ณ เดือนตุลาคม 2026 ซึ่งเป็นข้อมูลที่ควรทราบเมื่อคุณประเมินว่าโครงการนี้มีเหตุผลเพียงพอที่จะดำเนินการต่อไปหรือไม่
เหตุผลที่ความเสี่ยงนี้อยู่ในระดับที่ยอมรับได้คือผลลัพธ์ที่ได้ sandboxd จะสร้างแอปพลิเคชันทั่วไปใน git repository ปกติ ดังนั้นหากโครงการหยุดชะงัก คุณยังคงเก็บโค้ดไว้ได้และเสียเพียงแค่ตัว wrapper เท่านั้น ซึ่งถือเป็นสถานะที่ดีกว่าการใช้บริการ build บนคลาวด์ที่ถือสิทธิ์ในโปรเจกต์ของคุณ สำหรับมุมมองที่กว้างขึ้นว่ามีอะไรบ้างที่ควรค่าแก่การนำมา self-host บนเซิร์ฟเวอร์ของคุณในปีนี้ โปรดดู สิ่งที่ควรค่าแก่การ self-host ในปี 2026
FAQ
สเปกเซิร์ฟเวอร์ขั้นต่ำสำหรับ sandboxd คือเท่าใด
โครงการระบุว่า 2 vCPU และ 4 GB RAM เพียงพอสำหรับการเริ่มต้น ซึ่งครอบคลุมถึง control plane, Traefik และ sandbox ขนาดเล็กหนึ่งรายการ ให้ใช้ 8 GB และพื้นที่ดิสก์ 40 GB หากคุณต้องการให้แอปหลายรายการทำงานพร้อมกัน เนื่องจาก sandbox แต่ละรายการที่ทำงานอยู่จะเก็บ Node หรือ Python toolchain ฉบับเต็มไว้ และ workspace แต่ละแห่งจะเก็บ dependency tree ของตนเองไว้บนดิสก์ เมื่อโฮสต์มีทรัพยากรไม่เพียงพอ pressure reaper ของ sandboxd จะหยุดการทำงานของ sandbox เพื่อคืนหน่วยความจำ และการ build ที่ใช้หน่วยความจำเกินขีดจำกัดของ container จะถูก kernel สั่งยุติการทำงาน โดย docker ps -a จะแสดง exit code 137 สำหรับกรณีนี้
sandboxd แตกต่างจาก Dify หรือ OpenHands อย่างไร
เครื่องมือเหล่านี้สร้างผลลัพธ์ที่แตกต่างกัน Dify สร้างแอปพลิเคชันที่เรียกใช้โมเดลในขณะรันไทม์ เช่น อินเทอร์เฟซแชทและไปป์ไลน์การดึงข้อมูล OpenHands จะแก้ไข repository ที่คุณมีอยู่แล้ว โดยการรันคำสั่งและเสนอการเปลี่ยนแปลงโค้ดเดิม ส่วน sandboxd จะสร้างโครงร่างโครงการใหม่ทั้งหมดจาก prompt, ทำการ build ภายใน container ของตนเอง และให้บริการผ่าน URL สำหรับดูตัวอย่าง ผลลัพธ์ที่ได้คือเว็บแอปพลิเคชันทั่วไปที่ไม่จำเป็นต้องใช้โมเดลในการรัน
โค้ดที่ agent เขียนขึ้นถูกจัดเก็บไว้ที่ใด
จัดเก็บไว้บนระบบไฟล์ของโฮสต์ ไม่ใช่ภายใน container image แอปแต่ละรายการจะมีไดเรกทอรีอยู่ที่ /var/lib/sandboxed/workspaces/<id>/ สำหรับการติดตั้งเวอร์ชัน v0.3.6 (/var/lib/sandboxd/workspaces/<id>/ สำหรับการติดตั้งใหม่ในเวอร์ชัน v0.3.9 หรือใหม่กว่า) ซึ่งจะถูก bind mount เข้าไปใน sandbox และไฟล์จะปรากฏที่ /home/sandbox/workspace/app ภายในนั้น สถานะของ control plane จะเป็นไฟล์ SQLite ไฟล์เดียวภายใต้ state/ ในไดเรกทอรีข้อมูลเดียวกัน คุณสามารถ commit และ push ไปยัง branch ใหม่บน git remote ได้จากแท็บ Git ของคอนโซล หรือผ่าน endpoint /v1/apps/<id>/git/commit และ /git/push โดย token สำหรับ remote ส่วนตัวจะถูกจัดเก็บแบบเข้ารหัสโดย control plane แทนที่จะส่งมอบให้กับ sandbox
การเปิด sandboxd สู่สาธารณะมีความปลอดภัยหรือไม่
ให้เปิดเผยเฉพาะ URL สำหรับดูตัวอย่างและคอนโซลเท่านั้น ห้ามเปิดเผย API ของ control plane โดยเด็ดขาด เนื่องจาก API ดังกล่าวควบคุม Docker บนโฮสต์ ซึ่งเทียบเท่ากับการมีสิทธิ์ root และด้วยเหตุนี้จึงผูกไว้กับ 127.0.0.1:9090 ตามค่าเริ่มต้น นอกจากนี้ sandbox ยังมีการเปิด network egress ในรุ่น self-hosted ซึ่งหมายความว่าโค้ดที่ agent เขียนขึ้นสามารถเข้าถึงเครือข่ายภายในและ endpoint ของ cloud metadata ของคุณได้ ดังนั้นควรเพิ่มกฎ firewall ของโฮสต์หากเครื่องดังกล่าวมีเพื่อนบ้านที่ควรป้องกัน สำหรับ prompt จากบุคคลที่คุณไม่ไว้วางใจ ให้รันโฮสต์แยกต่อผู้ใช้งานหนึ่งราย แทนที่จะพึ่งพาขอบเขตของ container เพียงอย่างเดียว