วิธีติดตั้ง Open Connector แบบ Self-host สำหรับ AI Agent
เรียนรู้วิธีติดตั้ง Open Connector บน VPS เพื่อจัดการ OAuth และโทเค็นสำหรับ AI Agent อย่างปลอดภัย ป้องกันปัญหาโทเค็นรั่วไหลด้วยการตั้งค่า TLS และการสำรองข้อมูล SQLite
หน้าที่ของ Open Connector สำหรับ AI agent
การติดตั้ง Open Connector แบบ self-host จะสร้างเกตเวย์ยืนยันตัวตน (auth gateway) ไว้ระหว่าง AI agent ของคุณกับ API ของซอฟต์แวร์แบบ SaaS ทุกตัวที่ agent เรียกใช้งาน ทำให้ agent ไม่จำเป็นต้องถือครองโทเค็นของผู้ให้บริการ (provider token) โดยตรง Open Connector เป็นเกตเวย์แบบโอเพนซอร์สจาก OOMOL Lab ภายใต้สัญญาอนุญาต Apache 2.0 ทำงานในรูปแบบคอนเทนเนอร์เดียว เก็บสถานะไว้ในไฟล์ SQLite ไฟล์เดียว และเปิดเผยการทำงานของผู้ให้บริการผ่าน HTTP และ MCP (model context protocol)
ปัญหาจะเริ่มขึ้นเมื่อมีการเชื่อมต่อรายการที่สอง ทุกผู้ให้บริการมีขั้นตอน OAuth (open authorization) ของตนเอง มีอายุการใช้งานของ refresh token ที่ต่างกัน และมีชื่อ scope ที่ไม่เหมือนกัน การเชื่อมต่อผู้ให้บริการห้าแห่งเข้ากับ agent ด้วยตนเองหมายถึงการต้องเขียนตัวจัดการ redirect ห้าชุด, ระบบจัดเก็บข้อมูลประจำตัวห้าชุด และลูปการรีเฟรชโทเค็นห้าชุดที่ต้องทำงานก่อนที่โทเค็นจะหมดอายุ แทบไม่มีใครเขียนโค้ดเหล่านั้นเอง ส่วนใหญ่มักใช้วิธีสร้าง personal access token แบบอายุการใช้งานยาวนานหนึ่งชุดต่อหนึ่งบริการ แล้วนำไปวางในไฟล์ config ของ agent, ไฟล์ environment หรือแม้แต่ใน prompt โดยตรง โทเค็นดังกล่าวจะถูกอ่านได้โดยเครื่องมือทุกตัวที่ agent เรียกใช้ และจะหลุดเข้าไปอยู่ในบันทึกการสนทนา (transcript) ซึ่งเป็นความล้มเหลวที่อธิบายไว้ใน การรักษาความลับให้พ้นจาก AI agents
เกตเวย์ยืนยันตัวตนจะแยกข้อมูลประจำตัวออกเป็นสองส่วน เกตเวย์ทำหน้าที่เก็บข้อมูลประจำตัวของผู้ให้บริการและรันขั้นตอน OAuth ส่วน agent จะได้รับโทเค็นสำหรับใช้งานขณะรันไทม์ (runtime token) ซึ่งใช้ได้กับเกตเวย์เท่านั้น เมื่อ agent เรียกใช้งาน action เกตเวย์จะโหลดข้อมูลประจำตัวที่เก็บไว้มาใส่ในคำขอขาออกที่ฝั่งเซิร์ฟเวอร์ และส่งกลับเฉพาะเนื้อหาของผลลัพธ์เท่านั้น agent จะไม่ได้รับ access token ของผู้ให้บริการ ดังนั้นหากบันทึกการสนทนาของ agent รั่วไหล สิ่งที่คุณเสียไปจะเป็นเพียงโทเค็นรันไทม์ที่เพิกถอนได้ แทนที่จะเป็นบัญชี GitHub ของคุณ
แคตตาล็อกระบุว่ารองรับผู้ให้บริการมากกว่า 1,000 รายและมี action สำเร็จรูปมากกว่า 10,000 รายการ ซึ่งเป็นตัวเลขของโครงการเองและไม่ใช่สิ่งที่คุณจะตรวจสอบจากภายนอกได้ สิ่งที่คุณตรวจสอบได้คือรูปแบบการทำงาน: หนึ่ง HTTP endpoint ต่อหนึ่ง action, หนึ่งการเชื่อมต่อที่เก็บไว้ต่อหนึ่งผู้ให้บริการ, และหนึ่งโทเค็นต่อหนึ่ง agent หากฝั่งของ agent ยังเป็นเรื่องใหม่และคำศัพท์อย่าง tool call หรือ MCP server ยังไม่มีความหมายที่ชัดเจน เส้นทางการเรียนรู้ใน วิธีเรียนรู้ AI agents ตั้งแต่เริ่มต้น จะช่วยสร้างลูปการทำงาน, เครื่องมือ และนิสัยด้านความปลอดภัยที่เกตเวย์ประเภทนี้คาดหวังว่าคุณจะมีอยู่แล้ว
เหตุใดจึงควร self-host Open Connector แทนการใช้บริการ connector แบบ hosted
บริการ connector แบบ hosted ทำงานในลักษณะเดียวกัน โดยจะเก็บ refresh token ของทุกผู้ให้บริการที่คุณเชื่อมต่อไว้ บริการเหล่านี้เปรียบเสมือนกุญแจที่มีอายุการใช้งานยาวนานสำหรับเข้าถึงอีเมลและ repository ของคุณบน Google หรือ GitHub ซึ่งโดยปกติแล้วจะยังคงใช้งานได้แม้คุณจะเปลี่ยนรหัสผ่านแล้วก็ตาม หากบริการเหล่านั้นถูกเจาะ ข้อมูลของคุณก็จะถูกเจาะไปด้วย การทำ self-host จะย้ายบันทึกข้อมูลเหล่านี้มาเก็บไว้ใน SQLite บนเครื่องที่คุณเช่าและดูแลเอง โดยถูกล็อกไว้ด้วยกุญแจที่ไม่เคยถูกส่งออกจากเครื่องของคุณ
จงพิจารณาต้นทุนให้ชัดเจนก่อนเริ่มต้น VPS เครื่องนี้จะกลายเป็นเซิร์ฟเวอร์ที่มีค่าที่สุดที่คุณใช้งาน เนื่องจากมันเก็บ credential ของบริการต่างๆ ไว้ในไฟล์เดียว จึงควรได้รับการดูแลเช่นเดียวกับโฮสต์ของ password manager เช่น การตั้งค่า firewall ให้เปิดเฉพาะพอร์ต 443, ไม่ใช้บัญชีผู้ใช้ร่วมกัน, มีการสำรองข้อมูลที่คุณเคยทดสอบกู้คืนจริงแล้ว และมีการแจ้งเตือนเมื่อเซิร์ฟเวอร์ไม่ตอบสนอง หากคุณไม่ไว้วางใจที่จะเก็บ password vault ไว้บนเครื่องนี้ ก็ไม่ควรติดตั้ง connector ไว้บนเครื่องนี้เช่นกัน
กำหนดเวอร์ชันให้คงที่ก่อนเริ่มติดตั้งสิ่งใด
Open Connector ยังเป็นโครงการใหม่ โดย repository ปรากฏขึ้นครั้งแรกเมื่อวันที่ 29 มิถุนายน 2026 และ ณ วันที่ 1 สิงหาคม 2026 รุ่นล่าสุดที่มีการติดแท็กคือ v1.3.3 ซึ่งเผยแพร่เมื่อวันที่ 30 กรกฎาคม 2026 และมีแท็ก latest กำกับอยู่ด้วย นอกจากนี้ registry ยังเผยแพร่แท็ก tip ซึ่งสร้างจาก commit ล่าสุดบน main อีกด้วย
สำหรับโครงการที่ใหม่ขนาดนี้ แท็กที่มีการเปลี่ยนแปลงมักจะถูกอัปเดตบ่อยครั้ง การใช้ docker compose pull ที่ข้ามไปสองรุ่นอาจทำให้ endpoint ที่ agent ของคุณใช้งานอยู่เกิดการเปลี่ยนแปลง และคุณจะต้องเสียเวลาทั้งคืนเพื่อแก้ไขปัญหาโดยเข้าใจผิดว่าเป็นปัญหาที่ตัว agent เอง ดังนั้นควรตรึงอิมเมจไว้ที่แท็กของรุ่นที่ระบุ และค่อยทำการอัปเกรดเมื่อคุณตัดสินใจเอง หลังจากได้อ่านบันทึกประจำรุ่น (release notes) แล้วเท่านั้น
การติดตั้ง Open Connector หลัง TLS บน VPS ของคุณเอง
ก่อนที่ container จะเริ่มทำงาน คุณต้องมีสิ่งต่อไปนี้:
- Docker พร้อมปลั๊กอิน Compose บน Ubuntu 24.04 หรือเวอร์ชันที่ใกล้เคียงกัน
- ชื่อโฮสต์ (hostname) ที่มี A record ชี้มายัง VPS นี้ เช่น
connect.example.com - reverse proxy ที่ทำ TLS termination (transport layer security) สำหรับชื่อโฮสต์นั้นอยู่แล้ว
- รหัสลับแบบสุ่มสองชุด ซึ่งสร้างขึ้นตามขั้นตอนด้านล่าง
บทความ Traefik reverse proxy สำหรับแอป Docker Compose หลายตัว ครอบคลุมฝั่งการตั้งค่า proxy ส่วนขั้นตอนการจัดการ certificate ตั้งแต่ต้นจนจบสำหรับแอปเดียว สามารถดูได้จากคู่มือ n8n บน VPS ด้วย Docker และ HTTPS
ให้สร้างรหัสลับก่อน โดย encryption key จะทำหน้าที่ล็อกข้อมูลประจำตัวที่จัดเก็บไว้ ส่วน admin token จะป้องกันหน้าเว็บคอนโซลและพื้นที่ทั้งหมดของ /api ทั้งสองค่าไม่มีค่าเริ่มต้น และ runtime จะเริ่มทำงานได้แม้ไม่มีการตั้งค่าเหล่านี้
mkdir -p ~/open-connector && cd ~/open-connector
umask 077
printf 'OOMOL_CONNECT_ENCRYPTION_KEY=%s\n' "$(openssl rand -base64 32)" > .env
printf 'OOMOL_CONNECT_ADMIN_TOKEN=%s\n' "$(openssl rand -base64 32)" >> .env
chmod 600 .envคัดลอกทั้งสองค่าลงในโปรแกรมจัดการรหัสผ่านของคุณทันที ก่อนการเริ่มทำงานครั้งแรก encryption key ไม่มีช่องทางกู้คืน ซึ่งเหตุผลระบุไว้ในรายการข้อผิดพลาดด้านล่าง
ตอนนี้ให้สร้าง compose.yaml ซึ่งจะแตกต่างจากตัวอย่างต้นฉบับในสองจุดที่สำคัญ
services:
connector:
image: ghcr.io/oomol-lab/open-connector:v1.3.3
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
volumes:
- connector-data:/app/data
environment:
OOMOL_CONNECT_DATA_DIR: /app/data
OOMOL_CONNECT_ORIGIN: "https://connect.example.com"
OOMOL_CONNECT_ENCRYPTION_KEY: "${OOMOL_CONNECT_ENCRYPTION_KEY:?set this in .env}"
OOMOL_CONNECT_ADMIN_TOKEN: "${OOMOL_CONNECT_ADMIN_TOKEN:?set this in .env}"
volumes:
connector-data:การเปลี่ยนแปลงแรกคือการระบุเวอร์ชัน (pinned tag) แทนการใช้ latest ส่วนที่สองคือพอร์ต ไฟล์ต้นฉบับระบุ 3000:3000 ซึ่งเป็นการผูกพอร์ตกับทุกอินเทอร์เฟซบนโฮสต์ Docker จะเขียนพอร์ตที่เปิดใช้งานลงในตาราง NAT (network address translation) ก่อนที่ ufw filter chain จะเห็นแพ็กเก็ต ดังนั้น ufw deny 3000 จึงไม่สามารถปิดพอร์ตนั้นได้ ซึ่งเป็นกับดักที่อธิบายไว้ใน เหตุใดพอร์ต Docker จึงข้าม ufw การเขียน 127.0.0.1:3000:3000 จะเป็นการเปิดใช้งานบน loopback interface เท่านั้น และ reverse proxy ของคุณจะเชื่อมต่อจากโฮสต์เดียวกัน
:? จะระบุว่าตัวแปรแต่ละตัวจำเป็นต้องมี ดังนั้น stack จะปฏิเสธการเริ่มทำงานหาก .env หายไป แทนที่จะเริ่มทำงานโดยไม่มีการเข้ารหัสข้อมูลประจำตัว การเก็บค่าไว้ใน .env แทนที่จะใส่ในไฟล์ compose เป็นรูปแบบที่แนะนำจาก ไฟล์ env และ secrets ของ Docker Compose
docker compose up -d
docker compose logs -n 30 connector
curl -s http://127.0.0.1:3000/health
sudo ss -tlnp | grep 3000/health จะตอบกลับ { "ok": true } เมื่อ runtime พร้อมใช้งาน ss ต้องแสดงผลเป็น 127.0.0.1:3000 หากบรรทัดแสดงผลเป็น 0.0.0.0:3000 หมายความว่าการแมปพอร์ตยังคงเป็นค่าเดิมจากต้นฉบับ และ gateway กำลังตอบรับการเชื่อมต่อจากอินเทอร์เน็ตโดยตรง หากได้รับข้อความ Connection refused ในระหว่างการตรวจสอบ health check แสดงว่า container ยังไม่เริ่มทำงาน ดังนั้นให้อ่าน log ก่อนที่จะไปแก้ไขที่ proxy
Traefik labels สำหรับบริการเดียวกัน
labels:
- "traefik.enable=true"
- "traefik.http.routers.connector.rule=Host(`connect.example.com`)"
- "traefik.http.routers.connector.entrypoints=websecure"
- "traefik.http.routers.connector.tls.certresolver=le"
- "traefik.http.services.connector.loadbalancer.server.port=3000"เมื่อ Traefik ทำงานใน Docker บนโฮสต์เดียวกัน ให้เชื่อมต่อบริการนี้เข้ากับเครือข่ายของ Traefik และลบบล็อก ports: ออก เนื่องจาก Traefik สามารถเข้าถึง container ผ่านเครือข่ายภายในได้โดยตรงโดยไม่จำเป็นต้องเปิดพอร์ตใดๆ ออกสู่โฮสต์ certresolver=le ต้องตรงกับชื่อ resolver ในไฟล์ static config ของ Traefik มิฉะนั้น router จะทำงานโดยไม่มี certificate
เหตุผลที่ OAuth บังคับให้คุณต้องมี hostname จริง
OOMOL_CONNECT_ORIGIN คือการตั้งค่าที่ผู้คนมักข้ามไป และการข้ามขั้นตอนนี้จะทำให้ OAuth ทำงานผิดพลาดในลักษณะที่ดูเหมือนเป็นบั๊กของผู้ให้บริการ ตัว runtime จะสร้าง redirect URI จาก origin นั้นในรูปแบบ <origin>/oauth/callback หากไม่ได้ตั้งค่าไว้ origin จะมีค่าเริ่มต้นเป็น http://localhost:3000 ดังนั้น runtime จึงส่ง redirect URI ไปยังผู้ให้บริการเป็น http://localhost:3000/oauth/callback ในขณะที่แอป OAuth ของคุณลงทะเบียนไว้เป็น https://connect.example.com/oauth/callback สตริงทั้งสองค่านี้ไม่ตรงกัน GitHub จึงตอบกลับมาว่า:
The redirect_uri MUST match the registered callback URL for this application.ผู้ให้บริการ OAuth จะ redirect เบราว์เซอร์กลับไปยัง URI ดังกล่าว ซึ่งหมายความว่ามันต้องเป็นที่อยู่ที่โลกภายนอกสามารถเข้าถึงได้ และผู้ให้บริการจะปฏิเสธ http:// สำหรับทุกกรณีที่ไม่ใช่ localhost นี่คือเหตุผลทั้งหมดที่การติดตั้งใช้งานนี้จำเป็นต้องมี hostname และใบรับรอง (certificate) ให้ตั้งค่า origin ก่อนการเริ่มทำงานครั้งแรก เนื่องจากค่านี้จะถูกอ่านในขณะเริ่มต้นระบบ: หลังจากแก้ไข .env หรือ compose.yaml แล้ว ให้รัน docker compose up -d อีกครั้งเพื่อนำค่าไปใช้
เชื่อมต่อผู้ให้บริการรายแรกของคุณผ่าน OAuth
สร้างแอป OAuth ที่ฝั่งผู้ให้บริการก่อน สำหรับ GitHub ให้ไปที่เส้นทาง Settings ตามด้วย Developer settings จากนั้นเลือก OAuth Apps และ New OAuth App กำหนด URL สำหรับ authorization callback เป็น https://connect.example.com/oauth/callback เก็บ client ID และ client secret ไว้
การเรียกใช้งาน /api ทุกครั้งจะต้องใช้ admin token ดังนั้นให้ export ค่านี้ไว้สำหรับ session ของ shell หนึ่งครั้ง
export ADMIN_TOKEN='paste-the-admin-token'
curl -s https://connect.example.com/api/oauth/configs \
-H "authorization: Bearer $ADMIN_TOKEN"รายการดังกล่าวจะแสดง redirect URI ที่ runtime คาดหวังสำหรับผู้ให้บริการแต่ละราย ซึ่งเป็นวิธีตรวจสอบที่รวดเร็วที่สุดว่าค่า origin ที่คุณตั้งไว้มีผลแล้ว หากยังคงแสดงค่าเป็น localhost แสดงว่า container กำลังทำงานด้วยค่าเดิม และขั้นตอน OAuth จะล้มเหลวในขั้นตอนสุดท้าย
จัดเก็บ client credentials จากนั้นเริ่มกระบวนการ authorization
curl -s -X PUT https://connect.example.com/api/oauth/configs/github \
-H "authorization: Bearer $ADMIN_TOKEN" \
-H 'content-type: application/json' \
-d '{"clientId":"...","clientSecret":"..."}'
curl -s -X POST https://connect.example.com/api/oauth/authorizations \
-H "authorization: Bearer $ADMIN_TOKEN" \
-H 'content-type: application/json' \
-d '{"service":"github"}'การเรียกใช้งานครั้งที่สองจะส่งคืนค่า authorizationUrl ให้เปิด URL ดังกล่าวในเบราว์เซอร์ อนุมัติขอบเขตการเข้าถึง (scopes) แล้วผู้ให้บริการจะส่งเบราว์เซอร์กลับไปยัง /oauth/callback ซึ่ง runtime จะทำการแลกเปลี่ยน code และจัดเก็บ credential ไว้ เว็บคอนโซลที่ origin ของคุณจะดำเนินการตามขั้นตอนเดียวกันผ่านฟอร์ม โดยใช้ admin token เดียวกัน สำหรับผู้ให้บริการที่ใช้ API key แบบปกติจะข้ามขั้นตอนเหล่านี้ทั้งหมด โดยการใช้ PUT /api/connections/<service> ร่วมกับ {"authType":"api_key","values":{"apiKey":"..."}} จะเป็นการจัดเก็บ key โดยตรง
กำหนด runtime token ให้กับ agent แต่ละตัว แทนการใช้ credential
Agent จะยืนยันตัวตนกับ gateway ด้วย runtime token ซึ่งสร้างขึ้นผ่าน admin API
curl -s -X POST https://connect.example.com/api/runtime-tokens \
-H "authorization: Bearer $ADMIN_TOKEN" \
-H 'content-type: application/json' \
-d '{"name":"research-agent"}'การตอบกลับจะมี token ที่ขึ้นต้นด้วย oct_ ให้สร้าง token หนึ่งชุดต่อ agent หนึ่งตัว และตั้งชื่อตาม agent นั้น เนื่องจากหากคุณเพิกถอน token ที่ระบุตัวตนไม่ได้ คุณจะต้องเพิกถอน token ทั้งหมด จากนั้น agent จะเรียกใช้งาน action ต่างๆ ผ่าน HTTP ปกติ
curl -s -X POST https://connect.example.com/v1/actions/github.get_current_user \
-H "authorization: Bearer oct_..." \
-H 'content-type: application/json' \
-d '{"input":{}}'การตอบกลับที่ถูกต้องจะเป็น envelope ที่มีฟิลด์ success เป็น true โดยมี payload ของ provider อยู่ภายใต้ data ซึ่ง GitHub token จะไม่ปรากฏอยู่ในส่วนใดของการตอบกลับนั้น สำหรับ MCP client ให้ชี้ไปที่ https://connect.example.com/mcp โดยใช้ bearer header เดียวกัน และ gateway จะนำเสนอเครื่องมือสำหรับการค้นหา เช่น search_actions และ execute_action แทนที่จะใช้หนึ่งเครื่องมือต่อหนึ่ง API ซึ่งจะช่วยให้รายการเครื่องมือของ agent มีขนาดเล็ก การรัน MCP server บน VPS ครอบคลุมถึงฝั่ง client ของการเชื่อมต่อดังกล่าว
ให้ตรวจสอบอีกครั้งก่อนที่จะสรุปงานนี้ โดยลองเรียก action ซ้ำโดยลบ header authorization ออก คู่มือเริ่มต้นใช้งานฉบับย่อของโปรเจกต์มีการเรียก /v1 โดยไม่มี bearer ใดๆ ดังนั้นการติดตั้งที่ไม่ได้กำหนดค่า runtime auth ไว้จะอนุญาตให้ใครก็ตามที่เข้าถึงพอร์ตได้สามารถสั่งรัน action ต่างๆ ได้ หากการเรียกโดยไม่ยืนยันตัวตนของคุณสำเร็จ คุณมีทางเลือกสองทางคือ กำหนดค่า runtime token แล้วตรวจสอบว่าการเรียกแบบไม่ระบุตัวตนล้มเหลว หรือจำกัดการเข้าถึง /api, /v1 และ /mcp ที่ reverse proxy ให้เหลือเพียงที่อยู่ IP ของ agent ของคุณเท่านั้น โดยมีเพียง /oauth/callback เท่านั้นที่ต้องเปิดให้สาธารณะเข้าถึงได้ เนื่องจากเป็นเส้นทางเดียวที่จำเป็นสำหรับการ redirect เบราว์เซอร์ของ provider
จำกัดรายการคำสั่งให้เหลือเพียงสิ่งที่เอเจนต์จำเป็นต้องใช้
เกตเวย์ที่มีผู้ให้บริการจำนวนมากอยู่เบื้องหลังถือเป็นช่องทางที่กว้างเกินไปสำหรับการส่งต่อให้โมเดลภาษา และช่องทางนี้จะยิ่งกว้างขึ้นทันทีที่โมเดลเริ่มอ่านข้อความที่ไม่ได้เขียนขึ้นเอง เนื่องจากหน้าเว็บที่ส่งกลับมาจาก อินสแตนซ์ SearXNG ของคุณเองที่ตอบกลับการค้นหาเว็บของเอเจนต์ อาจมีคำสั่งที่มุ่งเป้าไปยังการกระทำใดก็ตามที่เอเจนต์นั้นมีสิทธิ์เข้าถึง การยับยั้งชั่งใจแบบเดียวกับที่ทำให้ เอเจนต์เขียนโค้ดเลือกการเปลี่ยนแปลงที่เล็กที่สุดที่ใช้งานได้ ควรนำมาใช้กับสิทธิ์ของเอเจนต์ด้วย นั่นคือให้สิทธิ์เฉพาะคำสั่งจำนวนน้อยที่จำเป็นต่องานจริงๆ เท่านั้น และห้ามให้สิทธิ์เกินกว่านั้น การควบคุมสองประการจะช่วยจำกัดขอบเขตนี้
OOMOL_CONNECT_ALLOWED_ACTIONS รับค่าเป็นรายการที่คั่นด้วยเครื่องหมายจุลภาค (allowlist) และรองรับ service.* รวมถึง * ส่วน OOMOL_CONNECT_BLOCKED_ACTIONS คือรายการที่ไม่อนุญาต (denylist) ซึ่งจะมีลำดับความสำคัญสูงสุด การตั้งค่า allowlist เป็น github.get_current_user,github.list_issues หมายความว่าคำสั่งอื่นทั้งหมดจะถูกปฏิเสธไม่ว่าเอเจนต์จะร้องขออย่างไรก็ตาม ซึ่งนี่คือจุดตัดสินระหว่างความผิดพลาดทั่วไปกับเหตุการณ์ความปลอดภัยร้ายแรง โทเค็นขณะรันไทม์ (runtime tokens) จะมีกฎการกระทำของตนเองเพิ่มเติมจากกฎส่วนกลาง และรายการ allowedProxies ของโทเค็นจะเริ่มต้นด้วยความว่างเปล่า ดังนั้น POST /v1/proxy/:service จะถูกปฏิเสธจนกว่าคุณจะอนุญาตให้ใช้ จุดเชื่อมต่อพร็อกซีนั้นจะส่งคำขอแบบดิบไปยังผู้ให้บริการพร้อมกับแนบข้อมูลประจำตัวของคุณไปด้วย ดังนั้นควรปล่อยให้ว่างไว้เว้นแต่จะมีเอเจนต์เฉพาะตัวที่จำเป็นต้องใช้มันจริงๆ
OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK มีค่าเริ่มต้นเป็น false ซึ่งจะป้องกันไม่ให้การเชื่อมต่อกับผู้ให้บริการที่โฮสต์เองชี้ไปยังที่อยู่ส่วนตัว เช่น บริการ metadata ของคลาวด์บน 169.254.169.254 หรือฐานข้อมูลของคุณที่อยู่ในเครือข่ายเดียวกัน ควรปล่อยให้ค่านี้ปิดไว้ และเปิดใช้งานเฉพาะสำหรับผู้ให้บริการที่คุณโฮสต์ด้วยตนเองเท่านั้น
สำรองข้อมูลเซิร์ฟเวอร์ที่เก็บโทเค็นทั้งหมด
มีสองสิ่งที่สำคัญ และแต่ละอย่างจะไร้ประโยชน์หากขาดอีกสิ่งหนึ่ง ฐานข้อมูลที่ /app/data/connect.sqlite ภายใน volume connector-data ทำหน้าที่เก็บข้อมูลรับรองที่ถูกปิดผนึกไว้ ส่วนกุญแจเข้ารหัสใน .env ใช้สำหรับปลดล็อกข้อมูลเหล่านั้น การสำรองข้อมูล volume โดยไม่มีกุญแจจะไม่สามารถกู้คืนสิ่งใดได้ และการมีกุญแจโดยไม่มี volume ก็ไม่สามารถกู้คืนสิ่งใดได้เช่นกัน ดังนั้นกุญแจควรถูกเก็บไว้ในโปรแกรมจัดการรหัสผ่านของคุณ และ volume ควรถูกรวมอยู่ในรอบการสำรองข้อมูลปกติ
ให้หยุดการทำงานของ container ก่อนที่คุณจะคัดลอกไฟล์ SQLite เนื่องจากสำเนาที่คัดลอกในขณะที่มีการเขียนข้อมูลอาจทำให้ฐานข้อมูลเสียหายเมื่อนำไปกู้คืน
docker volume ls | grep connector-data
docker compose stop connector
docker run --rm -v open-connector_connector-data:/data -v "$PWD":/backup alpine \
tar czf /backup/connector-data.tgz -C /data .
docker compose start connectorชื่อของ volume คือชื่อไดเรกทอรีโปรเจกต์ของคุณบวกด้วย _connector-data ซึ่งเป็นเหตุผลว่าทำไมคำสั่งแรกจึงอยู่ที่นั่น ให้คัดลอกชื่อจริงไปวางในคำสั่งที่สาม ส่งไฟล์ archive ออกจาก VPS ด้วย การสำรองข้อมูล restic จาก VPS ซึ่งจะทำการเข้ารหัสไฟล์ก่อนส่งออกไป เพราะไฟล์ archive นั้นคือที่เก็บข้อมูลรับรองทั้งหมด
ระบบ runtime จะเก็บประวัติการทำงานล่าสุดไว้เป็นบันทึกการตรวจสอบ โดยค่าเริ่มต้นจะเก็บไว้ 5,000 รายการ เพื่อให้คอนโซลสามารถแจ้งคุณได้ว่า agent ใดทำอะไรและเมื่อใด บันทึกดังกล่าวเป็นสิ่งแรกที่ควรตรวจสอบเมื่อ agent มีพฤติกรรมผิดปกติ นอกจากนี้ ให้เชื่อมต่อ หน้าสถานะ Uptime Kuma ไปยัง https://connect.example.com/health ด้วย เมื่อ gateway หยุดตอบสนอง agent จะทำงานล้มเหลวในรูปแบบที่ชวนสับสน การทราบว่า gateway ล่มจะช่วยประหยัดเวลาในการอ่านผลลัพธ์จาก agent ไปได้นับชั่วโมง
สิ่งที่มักจะเกิดข้อผิดพลาดและข้อความที่คุณจะพบ
redirect_uri_mismatch ที่ผู้ให้บริการ ต้นทางและ URL สำหรับ callback ที่ลงทะเบียนไว้ไม่ตรงกัน ให้เปรียบเทียบสตริงที่แน่นอนจาก /api/oauth/configs กับการตั้งค่าแอปของผู้ให้บริการ รวมถึงตรวจสอบ https เทียบกับ http และเครื่องหมาย slash ปิดท้าย
ทุกการเรียก /api ส่งค่ากลับเป็น 401 ส่วนหัวของ admin token หายไปหรือสะกดผิด ส่วนหัวดังกล่าวคือ Authorization: Bearer <token> และเว็บคอนโซลจะเรียกขอ token เดียวกันนี้
คอนเทนเนอร์ทำงานได้ แต่ข้อมูลประจำตัวยังคงเป็นข้อความธรรมดา (plain text) นี่คือสิ่งที่เกิดขึ้นเมื่อ OOMOL_CONNECT_ENCRYPTION_KEY ไม่ถูกส่งไปยังคอนเทนเนอร์ เนื่องจากรันไทม์จัดเก็บข้อมูลประจำตัวโดยไม่มีการเข้ารหัสแทนที่จะปฏิเสธการเริ่มทำงาน คุณสามารถตรวจสอบได้ด้วยตนเอง: เชื่อมต่อกับผู้ให้บริการด้วย API key ที่คุณจำได้ จากนั้นค้นหาในฐานข้อมูล
docker compose cp connector:/app/data/connect.sqlite /tmp/connect.sqlite
grep -c 'github_pat_' /tmp/connect.sqlite
shred -u /tmp/connect.sqliteหากผลลัพธ์มากกว่า 0 หมายความว่าคีย์นั้นไม่มีผล ให้ตรวจสอบว่า .env อยู่ในไดเรกทอรีเดียวกับ compose.yaml และ docker compose config แสดงค่าที่ถูกต้อง เมื่อตั้งค่าคีย์แล้ว การค้นหาแบบเดิมจะส่งค่ากลับเป็น 0 เนื่องจากบันทึกข้อมูลถูกปิดผนึกด้วย AES-256-GCM (มาตรฐานการเข้ารหัสขั้นสูง, คีย์ 256 บิต, โหมด Galois/counter)
ถอดรหัสไม่ได้หลังจากการกู้คืน คีย์การเข้ารหัสถูกเปลี่ยนหรือสูญหาย โดยการออกแบบ คีย์จะไม่ถูกเขียนไว้ข้างข้อมูล ดังนั้นจึงไม่มีช่องทางการกู้คืนและไม่มีการสนับสนุนใดๆ ที่จะช่วยได้ คุณต้องเชื่อมต่อผู้ให้บริการใหม่ทั้งหมด การหมุนเวียนคีย์ (rotation) รองรับผ่านตัวแปรคีย์แยกต่างหากและคำสั่งจัดการข้อมูลในรันไทม์ ดังนั้นโปรดอ่านบันทึกประจำรุ่น (release notes) ปัจจุบันก่อนที่คุณจะหมุนเวียนคีย์ใดๆ
เอเจนต์ได้รับข้อผิดพลาดที่ระบุถึงการกระทำที่ปรากฏในแคตตาล็อก การค้นพบ (discovery) และการดำเนินการ (execution) แยกออกจากกัน การกระทำหนึ่งอาจปรากฏใน search_actions แต่ยังคงถูกปฏิเสธโดย OOMOL_CONNECT_ALLOWED_ACTIONS, รายการที่ถูกบล็อก (denylist) หรือกฎของ token รันไทม์นั้นๆ
การอัปเกรด ให้สำรองข้อมูล volume, แก้ไข image tag เป็นรุ่นใหม่ จากนั้นใช้ docker compose pull && docker compose up -d คอยสังเกต docker compose logs -n 50 connector เพื่อดูบรรทัดการย้ายข้อมูล (migration) และเรียกใช้ health check รวมถึงการทดสอบการทำงานจริงหนึ่งครั้งก่อนที่คุณจะเชื่อมั่นในระบบอีกครั้ง การย้อนกลับ (rolling back) หมายถึงการใส่ tag เดิมกลับเข้าไป ซึ่งจะทำได้ก็ต่อเมื่อคุณได้กำหนดเวอร์ชัน (pinned) ไว้ก่อนหน้านี้เท่านั้น
FAQ
ฉันจำเป็นต้องมี public domain เพื่อ self-host Open Connector หรือไม่?
สำหรับผู้ให้บริการที่ใช้ API key นั้นไม่จำเป็น: gateway บน 127.0.0.1 ก็เพียงพอแล้ว แต่สำหรับการใช้งาน OAuth นั้นจำเป็นในทางปฏิบัติ เนื่องจากผู้ให้บริการจะ redirect เบราว์เซอร์ไปยัง callback URL ของคุณ ดังนั้น URL ดังกล่าวจึงต้องสามารถเข้าถึงได้จากอินเทอร์เน็ตสาธารณะ และผู้ให้บริการมักปฏิเสธการใช้ http:// ที่ไม่ใช่ localhost ให้ตั้งค่า OOMOL_CONNECT_ORIGIN เป็น hostname ของ https:// ก่อนการเริ่มทำงานครั้งแรก และลงทะเบียน <origin>/oauth/callback ในแอป OAuth ของผู้ให้บริการ
จะเกิดอะไรขึ้นหากฉันทำ encryption key ของ Open Connector หาย?
ข้อมูลประจำตัวที่จัดเก็บไว้จะไม่สามารถถอดรหัสได้และไม่มีวิธีกู้คืน คีย์ดังกล่าวถูกออกแบบมาให้ไม่ถูกจัดเก็บไว้พร้อมกับข้อมูล เพื่อป้องกันไม่ให้ผู้ที่เข้าถึงฐานข้อมูลอ่านข้อมูลได้ รวมถึงตัวคุณเองด้วย ทางเลือกเดียวคือการตั้งค่าคีย์ใหม่และเชื่อมต่อกับผู้ให้บริการทุกรายใหม่อีกครั้ง ควรเก็บคีย์ไว้ในโปรแกรมจัดการรหัสผ่านและเก็บฐานข้อมูลไว้ในรอบการสำรองข้อมูลของคุณ เพราะการกู้คืนระบบจำเป็นต้องใช้ทั้งสองอย่าง
AI agent ของฉันสามารถเห็น access token ของผู้ให้บริการได้หรือไม่?
ไม่สามารถเห็นได้เมื่อเรียกใช้งานผ่าน gateway ตัว agent จะยืนยันตัวตนด้วย runtime token ที่ขึ้นต้นด้วย oct_ และ gateway จะแทรกข้อมูลประจำตัวของผู้ให้บริการเข้าไปในคำขอขาออกที่ฝั่งเซิร์ฟเวอร์ โดยส่งกลับมาเพียงผลลัพธ์เท่านั้น มีสองกรณีที่ทำให้คุณสมบัตินี้ถูกยกเลิก: คือ endpoint /v1/proxy/:service ซึ่งส่งต่อคำขอแบบ raw โดยแนบข้อมูลประจำตัวของคุณไปพร้อมกัน (ซึ่งเหตุผลที่สิทธิ์การเข้าถึงถูกตั้งค่าเป็นว่างไว้ตั้งแต่ต้นนั้นมีที่มา) และการที่คุณคัดลอก API key ไปใส่ใน agent ด้วยตนเอง ซึ่งเป็นการข้ามการทำงานของ gateway โดยสิ้นเชิง
gateway ควรเข้าถึงได้จากอินเทอร์เน็ตสาธารณะหรือไม่?
ควรเข้าถึงได้เฉพาะ /oauth/callback เท่านั้น ให้ publish พอร์ตของ container บน 127.0.0.1 เพื่อให้กฎ NAT ของ Docker ไม่เปิดเผยพอร์ตออกไปนอก firewall ของคุณ และวาง reverse proxy ไว้ด้านหน้า จากนั้นให้ทดสอบการเรียกใช้งานหนึ่งครั้งโดยไม่มี header authorization หากทำได้สำเร็จ ให้จำกัดการเข้าถึง /api, /v1 และ /mcp ที่ตัว proxy ให้เหลือเพียงที่อยู่ IP ที่ agent ของคุณใช้งาน จนกว่าจะเหลือเพียงการเรียกใช้งานที่ผ่านการยืนยันตัวตนเท่านั้นที่ทำงานได้
Open Connector พร้อมสำหรับการใช้งานในระดับ production แล้วหรือยัง?
ซอฟต์แวร์นี้ใช้สัญญาอนุญาต Apache 2.0 และมีการพัฒนาอย่างรวดเร็ว: repository ปรากฏขึ้นเมื่อวันที่ 29 มิถุนายน 2026 และ v1.3.3 ได้รับการปล่อยออกมาเมื่อวันที่ 30 กรกฎาคม 2026 ดังนั้นให้ถือว่าหมายเลขเวอร์ชันทุกรายการในคู่มือนี้เป็นเพียงภาพรวม ณ วันที่ 1 สิงหาคม 2026 เท่านั้น ให้รันซอฟต์แวร์โดยระบุเวอร์ชันที่แน่นอน (pinned release tag) ห้ามใช้ latest หรือ tip โดยเด็ดขาด อ่านบันทึกการปล่อยเวอร์ชัน (release notes) ก่อนการอัปเกรดทุกครั้ง และเก็บสำรองข้อมูล volume ที่คุณเคยทดสอบการกู้คืนแล้วอย่างน้อยหนึ่งครั้ง การออกแบบนี้มีความมั่นคงสำหรับเซิร์ฟเวอร์ที่คุณดูแลเอง และความเสี่ยงหลักอยู่ที่การเปลี่ยนแปลงของเวอร์ชัน ไม่ใช่ที่ตัวสถาปัตยกรรม