SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-08-28

วิธีติดตั้ง OpenHands บน VPS ด้วย Docker อย่างปลอดภัย

เรียนรู้วิธีติดตั้ง OpenHands บน VPS ด้วย Docker พร้อมคำแนะนำการตั้งค่าความปลอดภัยที่สำคัญ เนื่องจากระบบต้องเข้าถึง Docker socket ซึ่งมีความเสี่ยงต่อสิทธิ์ระดับ root ของโฮสต์

OpenHands คืออะไร และความเสี่ยงประการเดียวที่ต้องเข้าใจก่อน

OpenHands หรือชื่อเดิมคือ OpenDevin เป็นเอเจนต์วิศวกรรมซอฟต์แวร์แบบอัตโนมัติ คุณสามารถมอบหมายงานด้วยภาษาทั่วไป แล้วระบบจะวางแผนการทำงาน เขียนโค้ด รันคำสั่ง อ่านผลลัพธ์ และทำซ้ำจนกว่างานจะเสร็จสิ้น คุณสามารถรันระบบนี้บนเซิร์ฟเวอร์ของคุณเองผ่าน Docker และเชื่อมต่อกับโมเดลภาษา (LLM) เมื่อรันบน VPS ระบบจะกลายเป็นเอเจนต์เขียนโค้ดที่ทำงานให้คุณได้แม้ในเวลาที่คุณไม่ได้อยู่หน้าจอ

ข้อเท็จจริงประการหนึ่งที่ควรเป็นพื้นฐานในการตั้งค่าทั้งหมดของคุณคือ OpenHands ไม่ได้เพียงแค่แนะนำโค้ดเท่านั้น แต่ยังรันโค้ดนั้นด้วย เพื่อให้ทำเช่นนั้นได้ คอนเทนเนอร์ควบคุมของมันจะทำการ mount Docker socket ของโฮสต์ไว้ที่ /var/run/docker.sock เพื่อให้สามารถสร้าง sandbox container สำหรับแต่ละงานได้ สิ่งใดก็ตามที่สามารถสื่อสารกับ Docker socket ได้ จะสามารถเริ่มคอนเทนเนอร์ใหม่ที่ mount ระบบไฟล์ทั้งหมดของโฮสต์คุณได้ ซึ่งหมายความว่าการเข้าถึง socket นี้มีสิทธิ์เทียบเท่ากับ root บนเครื่อง ดังนั้น ให้ปฏิบัติต่อเครื่องที่รัน OpenHands เสมือนเป็นเซิร์ฟเวอร์ที่รันโค้ดที่ไม่น่าเชื่อถือ เพราะนั่นคือสิ่งที่มันทำอยู่จริง ทุกมาตรการการรักษาความปลอดภัยที่ระบุไว้ด้านล่างนี้ล้วนมีที่มาจากข้อเท็จจริงดังกล่าว

สิ่งที่ต้องเตรียม

คุณต้องมี VPS ที่รัน Ubuntu 24.04 พร้อมติดตั้ง Docker Engine เวอร์ชันล่าสุด, มี RAM อย่างน้อย 4 GB และมี API key สำหรับโมเดลภาษา (OpenAI, Anthropic หรือ Google) หรือใช้โมเดลที่รันในเครื่องผ่าน Ollama บน VPS เดียวกัน OpenHands รองรับโมเดล backend จำนวนมาก คุณจึงเลือกใช้ได้ตามต้องการ หากคุณไม่เคยตั้งค่าคอนเทนเนอร์มาก่อน พื้นฐานการใช้งาน Docker บน VPS จะครอบคลุมเนื้อหาที่คู่มือนี้ใช้เป็นพื้นฐาน

การติดตั้งด้วย Docker

OpenHands มีการเผยแพร่ในรูปแบบอิมเมจ 2 รายการ ได้แก่ อิมเมจของแอปพลิเคชันที่คุณเรียกใช้งาน และอิมเมจของ agent-server ที่แอปพลิเคชันจะดึงมาเพื่อสร้าง sandbox สำหรับรันแต่ละงาน ให้เรียกใช้งานด้วยคำสั่งดังนี้ โดยแทนที่ด้วยแท็กปัจจุบันจากเอกสารของโปรเจกต์:

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

มีรายละเอียด 2 ประการที่จะช่วยให้คุณประหยัดเวลาจากการสับสน อิมเมจของแอปและอิมเมจของ agent-server มีหมายเลขเวอร์ชันที่แตกต่างกันโดยเจตนา ดังนั้นอย่าพยายามทำให้เวอร์ชันตรงกัน ให้ใช้แท็กของ agent-server ตามที่เอกสารระบุไว้คู่กับเวอร์ชันของแอปที่คุณใช้ และสังเกตการใช้ -p 127.0.0.1:3000:3000 แทนที่จะเป็น -p 3000:3000 การเปลี่ยนแปลงเพียงจุดเดียวนี้นำไปสู่ความแตกต่างระหว่าง Web UI ที่คุณเข้าถึงได้เพียงคนเดียว กับ Web UI ที่อินเทอร์เน็ตทั้งเครือข่ายสามารถเข้าถึงได้ ซึ่งเป็นหัวข้อที่จะกล่าวถึงในส่วนถัดไป

จำกัดการเข้าถึง Web UI ไม่ให้ผ่านอินเทอร์เน็ตสาธารณะ

OpenHands ให้บริการอินเทอร์เฟซผ่านพอร์ต 3000 อินเทอร์เฟซดังกล่าวทำหน้าที่ควบคุมเอเจนต์ที่รันโค้ด ดังนั้นการเปิดเผยอินเทอร์เฟซนี้สู่อินเทอร์เน็ตจะทำให้ใครก็ตามที่พบเข้าถึงช่องทางในการสั่งรันคำสั่งบนเซิร์ฟเวอร์ของคุณได้ ให้ผูกบริการไว้กับ loopback ตามคำสั่งรันด้านบน และเข้าถึงผ่าน SSH tunnel จากแล็ปท็อปของคุณแทน:

ssh -L 3000:127.0.0.1:3000 you@your-vps

จากนั้นเปิด http://127.0.0.1:3000 บนเครื่องของคุณ ทราฟฟิกจะถูกส่งผ่านเซสชัน SSH ที่มีอยู่เดิม และไม่มีพอร์ตใหม่ใดๆ เปิดรอรับการเชื่อมต่อบนอินเทอร์เน็ตสาธารณะ เอเจนต์บางตัวไม่จำเป็นต้องใช้พอร์ตเลย: เซสชัน Claude Code บน VPS เดียวกันสามารถสื่อสารกันผ่านเทอร์มินัลได้ ดังนั้นสิ่งเดียวที่คุณเปิดเผยคือ SSH เท่านั้น นิสัยการใช้ loopback และ tunnel เช่นนี้ควรนำไปใช้กับแดชบอร์ดของเอเจนต์ทุกตัวที่คุณโฮสต์; การเข้าถึง UI สำหรับการสแกนของ open-kritt ผ่าน tunnel ก็ใช้วิธีเดียวกัน เพียงแต่เปลี่ยนไปใช้พอร์ต 5173 หากต้องการการตั้งค่าที่ถาวรขึ้น ให้ใช้งานผ่าน VPN แทน ไม่ว่าจะเลือกวิธีใด ควรตั้งค่า firewall แบบ default-deny ไว้หน้าเซิร์ฟเวอร์เพื่อป้องกันไม่ให้มีการเปิดเผยบริการโดยไม่ตั้งใจ และโปรดจำไว้ว่า firewall ที่ครอบคลุมเฉพาะ IPv4 จะยังคงเปิดพอร์ตเดียวกันทิ้งไว้บน IPv6 ซึ่งเป็น ช่องโหว่ของ IPv6 firewall ที่ทำให้หลายคนพลาดมาแล้ว

แยกคีย์ของโมเดลและข้อมูลรับรองของ repository ออกมา

OpenHands ต้องการ API key สำหรับโมเดล และมักต้องการ token เพื่อ clone และ push ข้อมูลไปยัง repository ของคุณ ข้อมูลทั้งสองประเภทนี้สามารถใช้จ่ายเงินและดำเนินการในนามของคุณได้ จึงต้องจัดการเหมือนกับรหัสผ่าน ให้เก็บไว้ในไฟล์ environment ที่อนุญาตให้เฉพาะบัญชีที่เกี่ยวข้องอ่านได้เท่านั้น ห้ามใส่ไว้ในคำสั่งรันโดยตรง เพราะจะทำให้ข้อมูลไปปรากฏในประวัติ shell และรายการ process รวมถึงห้ามเก็บไว้ในไฟล์ที่อยู่ภายใน git repository หากคุณเก็บข้อมูลต้นฉบับไว้ใน password manager ที่โฮสต์เอง ให้เพิ่มความปลอดภัยให้กับเซิร์ฟเวอร์นั้นด้วย เนื่องจากจุดอ่อนของ vault คือ admin token และไฟล์สำรองข้อมูล ไม่ใช่ตัวรายการที่เข้ารหัสไว้ ซึ่งอธิบายไว้ใน แนวทางการเพิ่มความปลอดภัยให้ Vaultwarden

รันบนเครื่องที่คุณสามารถทิ้งได้

เนื่องจาก controller จำเป็นต้องเข้าถึง Docker socket คุณจึงไม่สามารถแยก OpenHands ออกจากโฮสต์ได้อย่างสมบูรณ์ วิธีลดความเสี่ยงที่ตรงไปตรงมาที่สุดคือการแยกตำแหน่งที่ตั้ง: ให้รัน OpenHands บน VPS เฉพาะที่ไม่มีข้อมูลสำคัญอื่นใด ไม่ใช่บนเซิร์ฟเวอร์เดียวกับที่รันฐานข้อมูลหรือเว็บไซต์ของคุณ ให้ทำ snapshot ไว้ก่อนเริ่มใช้งาน และใช้วิธีสร้างเครื่องใหม่จาก snapshot นั้นแทนการเชื่อใจเครื่องที่รันโค้ดซึ่งเขียนโดย agent มาตลอดทั้งสัปดาห์ VPS ราคาประหยัดแบบใช้แล้วทิ้งและมีจุดประสงค์เดียวคือสภาพแวดล้อมที่เหมาะสมที่สุดสำหรับงานนี้ ตำแหน่งที่ตั้งเป็นเพียงตัวแปรเดียวที่ OpenHands มอบให้คุณในส่วนนี้ ดังนั้นหากคุณต้องการควบคุมขอบเขตการทำงานของ agent ก่อนที่มันจะหยุดเพื่อขออนุญาต โหมดการอนุญาตของ Claude Code จะแสดงให้เห็นว่ากลไกควบคุมชั้นที่สองนั้นมีลักษณะอย่างไรบนเซิร์ฟเวอร์ที่ไม่มีใครคอยเฝ้าดู

การเสริมความปลอดภัยให้กับเซิร์ฟเวอร์

ส่วนที่เหลือคือสุขอนามัยพื้นฐานของเซิร์ฟเวอร์ ซึ่งมีความสำคัญมากกว่าปกติในกรณีนี้เนื่องจากภาระงานมีความเสี่ยงสูงกว่าทั่วไป ให้สร้างผู้ใช้ระดับผู้ดูแลระบบที่ไม่มีสิทธิ์พิเศษ (unprivileged admin user) แทนการทำงานในฐานะ root โดยปฏิบัติตาม การรันบริการในฐานะผู้ใช้ที่ไม่มีสิทธิ์พิเศษ เปลี่ยนการเข้าถึง SSH ให้เป็นการยืนยันตัวตนด้วยกุญแจ (key-only authentication) เท่านั้น จากนั้นให้ดำเนินการตามรายการตรวจสอบด้านล่างและเก็บไว้ในที่ที่คุณสามารถเรียกดูได้อีกครั้ง

ToolVPS hardening checklist

หากต้องการทำความเข้าใจส่วนประกอบต่างๆ แทนที่จะเพียงแค่รันคำสั่ง ให้ดูที่ การสร้าง AI agent ของคุณเองบน VPS สำหรับแพลตฟอร์มที่ใช้โค้ดน้อยกว่า การทำ self-hosting Dify เป็นจุดเริ่มต้นที่ง่ายกว่า

FAQ

การรัน OpenHands บนเซิร์ฟเวอร์มีความปลอดภัยหรือไม่?

สามารถทำได้หากใช้ความระมัดระวัง แต่มีความเสี่ยงสูงกว่าเว็บแอปพลิเคชันทั่วไป เนื่องจาก OpenHands สามารถเขียนและรันโค้ดได้ อีกทั้งตัวควบคุม (controller) ยังเข้าถึง Docker socket ของโฮสต์ ซึ่งมีสิทธิ์เทียบเท่า root บนเครื่องนั้นๆ ควรติดตั้งบน VPS เฉพาะกิจที่สามารถลบทิ้งได้และไม่มีข้อมูลสำคัญอื่นเก็บอยู่ ให้เข้าถึง Web UI ผ่าน loopback โดยใช้ SSH tunnel หรือ VPN เท่านั้น แยกกุญแจ (keys) ของระบบออกจากกัน และเสริมความปลอดภัยให้กับเซิร์ฟเวอร์ ห้ามรัน OpenHands ควบคู่ไปกับบริการสำคัญของคุณ

ทำไม OpenHands ถึงต้องใช้ Docker socket?

OpenHands จะรันแต่ละงานใน sandbox container ที่สร้างขึ้นใหม่ โดยจะสั่งให้ Docker daemon ของโฮสต์สร้าง container เหล่านั้นผ่านการ mount /var/run/docker.sock เข้าไปยังตัวควบคุม สิ่งนี้ทำให้ container ของตัวควบคุมสามารถสั่งการ Docker บนโฮสต์ได้ ซึ่งเป็นสิทธิ์ที่มีอำนาจสูงและมีความเสี่ยง ดังนั้นตัวโฮสต์เองจึงต้องถูกจัดการเสมือนว่าเป็นเครื่องที่รันโค้ดที่ไม่น่าเชื่อถือ

OpenHands สามารถใช้โมเดลในเครื่องแทนการจ่ายค่า API ได้หรือไม่?

ได้ OpenHands รองรับโมเดลในเครื่องที่ให้บริการผ่าน Ollama หรือ vLLM คุณจึงสามารถรันแบบ self-hosted ได้เต็มรูปแบบโดยไม่มีค่าใช้จ่ายต่อ token และไม่มีข้อมูลรั่วไหลออกจากเซิร์ฟเวอร์ของคุณ คุณจำเป็นต้องมีเครื่องที่มีหน่วยความจำเพียงพอสำหรับโมเดลเขียนโค้ดที่มีประสิทธิภาพ ซึ่งเป็นหลักการเดียวกับการเลือกขนาดเครื่องที่ระบุไว้ในคู่มือของ Ollama

ฉันควรรัน OpenHands บนเซิร์ฟเวอร์หลักหรือไม่?

ไม่ควร เนื่องจาก OpenHands รันโค้ดที่สร้างโดยเอเจนต์และถือสิทธิ์ Docker socket ไว้ จึงควรแยกไปรันบน VPS เฉพาะกิจที่คุณพร้อมจะล้างเครื่องใหม่ได้ตลอดเวลา การติดตั้งไว้ร่วมกับฐานข้อมูล เว็บไซต์ หรือบริการอื่นๆ อาจทำให้เกิดความผิดพลาดจากเอเจนต์หรือบั๊กในตัวเอเจนต์ ซึ่งอาจส่งผลกระทบต่อส่วนประกอบอื่นๆ ที่ไม่ควรถูกเข้าถึงได้