# แผน: รัน engine (ComfyUI, Whisper) ตรงบนเครื่อง ไม่ใช้ Docker สถานะ (2026-10-07): **เขียนโค้ดแล้ว ยังไม่ได้ deploy/ทดสอบบน GPU** (agent 0.13.0, `cmd/wxch-agent/hostengine.go`) และเจ้าของสั่งให้ **ค่าเริ่มต้นเป็น host แล้ว** (ไม่ใช่ docker ตามที่ร่างไว้ในข้อ 3.1) ส่วนที่ยังไม่ทำ: ล็อกแบบมี hash, RPC สลับโหมด, `host_bytes` ต่อโหมดในตัวติดตั้ง, `WXCH_ENGINE_MODE`; การสลับกลับ docker ทำโดยใส่ `"mode": "docker"` ใน state.json. รายละเอียดสถานะจริงดู docs/HANDOFF.md ## 1. ที่มาและสิ่งที่เจ้าของเลือก - เจ้าของเครื่องขอให้ "ติดตั้ง ComfyUI ตรงบนเครื่อง ไม่ใช้ Docker" และให้ครอบคลุม **ทุก engine** ที่ทำภาพ วิดีโอ เสียง และอื่นๆ (ตอนนี้มี 2 ตัว: `comfyui` ใช้ทำภาพ/วิดีโอ และ `whisper` ทำเสียง) - เลือกทั้งที่รับทราบแล้วว่า: ความปลอดภัยลดลงจากเดิมที่อยู่ในคอนเทนเนอร์ที่ล็อกสิทธิ์ และ PyTorch สำหรับ GB10 ต้องลงเอง - เหตุผลที่น่าจะทำให้คุ้ม (ตามที่เห็นจากการใช้งานจริงช่วงที่ผ่านมา): - image ของ engine ใหญ่ 38.5 GB บนดิสก์ (ใช้ NVIDIA PyTorch ทั้ง image) ในขณะที่ Python + PyTorch + แพ็กเกจจริงที่ใช้ราว 5-8 GB - ปัญหาที่เกิดขึ้นเพราะ Docker มาแล้วหลายเรื่อง: ค่าจำกัดไฟล์ที่เปิดได้ต่ำเกินไป (แก้แล้ว), ต้องส่งต่อพอร์ต/Host/Origin, ดู log ต้องผ่าน runner, ต้องมีขั้นดึง image - ไม่ต้องมี Docker และ runner ที่มีสิทธิ์ root สำหรับเครื่องที่ติดตั้งแค่โมดูล (ลดส่วนที่ต้องไว้ใจ) ## 2. ตัวเลือกที่พิจารณา และเหตุผล | ตัวเลือก | ข้อดี | ข้อเสีย | ผล | |---|---|---|---| | ก. คง Docker เดิม | ปลอดภัยสุด ใช้ได้แล้ว | image ใหญ่ ต้องมี runner (root) และ Docker | คงไว้เป็นโหมดสำรอง | | ข. รันตรงบนเครื่อง เป็น child process ของ agent (**เลือก**) | ไม่มี image ไม่ต้องใช้ root/Docker ผูกกับโฟลเดอร์ปกติ ดู log ตรงๆ | ไม่มี sandbox ของคอนเทนเนอร์ engine ตายตามเมื่อ agent รีสตาร์ท | ทำ | | ค. รันตรงบนเครื่อง เป็น systemd service แยก | engine อยู่รอดเมื่อ agent รีสตาร์ท | ต้องเขียนไฟล์ unit ด้วย root จึงต้องผ่านตัวติดตั้ง ซับซ้อนขึ้น | เก็บไว้ทำภายหลังถ้าจำเป็น | | ง. ดึง Python ออกจาก image NVIDIA มาใช้ | ได้ PyTorch ที่ NVIDIA ทดสอบกับ GB10 | ทำซ้ำยากและไม่เป็นทางการ | ไม่ทำ | เหตุผลที่เลือก ข.: agent ทำงานในสิทธิ์ผู้ใช้เดียวกับ engine อยู่แล้ว จึงเริ่ม/หยุด/ดู log ได้โดยไม่ต้องขอสิทธิ์เพิ่ม และติดตั้งผ่านหน้าเว็บ (ที่ agent ไม่มีสิทธิ์ root) ได้ด้วย ถ้าเลือก ค. การติดตั้งจากหน้าเว็บจะทำไม่ได้ ## 3. การออกแบบ ### 3.1 โหมด engine - โหมดต่อเครื่อง: `docker` (ค่าเริ่มต้นเดิม) หรือ `host`; เก็บใน `/state.json` (`mode`) เพื่อให้ agent เขียนเองได้ (ไม่ต้องแก้ `/etc/wxch/node.json` ซึ่ง agent เขียนไม่ได้) ถ้าไม่มีให้ดูคีย์ `engine_mode` ใน node.json (สำหรับตั้งตอนติดตั้ง) - **ค่าเริ่มต้นยังเป็น `docker`** จนกว่าจะยืนยันบนเครื่องจริง สลับกลับได้ทันทีถ้ามีปัญหา (เหตุผล: ยังไม่เคยรัน PyTorch บน GB10 นอก container ของ NVIDIA) - สลับโหมดด้วย RPC `modules.mode` (ปุ่มในหน้า "โมดูล AI"): หยุด engine ทุกตัวก่อน (ปฏิเสธถ้ามีงานรันอยู่) แล้วตั้งโหมด แล้วเริ่มติดตั้งรันไทม์ของโหมดใหม่ใน background ### 3.2 โครงโฟลเดอร์ (ทุกอย่างอยู่ใต้ `modules_dir`: ดิสก์หลักหรือ external ก็ได้) ``` / state.json โมดูลที่ติดตั้ง, โหมด, engine ที่ปักหมุด .host/uv ตัวติดตั้ง uv (ปักเวอร์ชัน+sha256) .host/python/ Python ที่ uv โหลดมา (3.12) .host/cache/ แคชแพ็กเกจของ uv (อยู่ดิสก์เดียวกับ venv เพื่อใช้ hard link ไม่ซ้ำพื้นที่) comfyui/ ComfyUI/ โค้ด ComfyUI + models/ (เหมือนโหมด docker ใช้ร่วมกันได้) venv/ Python venv ของ ComfyUI (+ .wxch-ready) home/, tmp/ HOME และ TMPDIR ของ engine engine.log, install.log whisper/ (ในรูปแบบเดียวกัน) ``` เหตุผล: โฟลเดอร์ `ComfyUI/` และ `models/` ใช้ที่เดียวกับโหมด docker จึง **ไม่ต้องโหลดโมเดลใหม่** และสลับโหมดได้โดยไม่ย้ายไฟล์ การให้ใช้ดิสก์ external ทำโดยตั้ง `modules_dir` ไปที่ดิสก์นั้น (ไม่มี mount เข้าคอนเทนเนอร์ที่ต้องดูแลแล้ว) ### 3.3 ขั้นติดตั้งรันไทม์ (ต่อ engine, ทำเป็น background, รายงานความคืบหน้าในหน้า) 1. **uv**: ดาวน์โหลด tar.gz ที่ปักเวอร์ชัน (0.12.23) ตรวจ sha256 (arm64 `6524bd33…`, amd64 `9167d72b…`) แล้วแตกเฉพาะไฟล์ `uv` (ไม่รันอะไรจากอินเทอร์เน็ตโดยไม่ตรวจ) 2. **Python**: `uv venv --python 3.12 --managed-python /venv` โดย `UV_PYTHON_INSTALL_DIR` และ `UV_CACHE_DIR` อยู่ใต้ `.host/` (ไม่แตะ Python ของระบบ, ไม่ต้อง `python3-venv`) 3. **PyTorch**: `uv pip install --python --torch-backend cu130 torch==2.14.1 torchvision==0.29.1 torchaudio==<ตามที่มีใน index>` (มีล้อ cp312 aarch64 ของ cu130 แล้ว ขนาดล้อ torch ~454 MB ยังไม่รวมไลบรารี CUDA ที่ตามมา) 4. **แพ็กเกจของ engine**: comfyui = `requirements.lab.txt` (ตัด torch ออกแล้ว); whisper = `transformers accelerate av numpy` 5. **ตรวจ GPU**: รัน `venv/bin/python -c "import torch; …"` ต้องได้ `cuda.is_available() == True` และพิมพ์รายการสถาปัตยกรรม (arch list) ลง log ถ้าไม่ผ่านให้ล้มเหลวด้วยข้อความชัด (เหตุผล: ตัดกรณี PyTorch ลงได้แต่ใช้ GPU ไม่ได้ออกก่อนผู้ใช้เจอตอนสั่งงาน) 6. เขียน `venv/.wxch-ready` (บันทึกเวอร์ชัน) ใช้เป็นตัวบอกว่า "พร้อม" (ตรงกับความหมาย `image_present` ของโหมด docker เพื่อให้โค้ดติดตั้งโมดูลเดิมใช้ร่วมกันได้) ### 3.4 การรัน engine (supervisor ใน agent) - เริ่ม: `venv/bin/python main.py --listen 127.0.0.1 --port <พอร์ตเดิม 8300/8301> --disable-auto-launch --disable-api-nodes --disable-metadata` (whisper: `whisper_server.py --host 127.0.0.1 --port … --model …`; เพิ่ม `--host` เพราะสคริปต์เดิมผูก `0.0.0.0`) - ผูกเฉพาะ `127.0.0.1` พอร์ตเดียวกับโหมด docker จึงไม่ต้องแก้ส่วนอุโมงค์ (comfy.), ตัวส่งงาน, ตรวจสุขภาพ - **ตั้ง environment เอง ไม่สืบทอดจาก agent**: เพราะ agent ถือ token ของเครื่อง (`WXCH_TOKEN`) ที่ engine ต้องไม่เห็น; ใช้เฉพาะ `PATH`, `HOME=/home`, `TMPDIR`, `LANG`, `PYTHONUNBUFFERED`, `DO_NOT_TRACK`, `HF_HUB_OFFLINE` - เริ่มเป็นกลุ่มโปรเซสของตัวเอง (`Setpgid`) เพื่อหยุดทั้งกลุ่มได้; หยุด = SIGTERM รอ 10 วินาที แล้ว SIGKILL - log เขียนลง `engine.log` (ตัดเมื่อเกิน 20 MB ตอนเริ่ม) ปุ่ม Log และหน้า "กำลังเริ่ม engine" อ่านท้ายไฟล์นี้ - จำนวนไฟล์ที่เปิดได้: agent เป็นโปรแกรม Go ซึ่งยกค่า soft limit ขึ้นเท่า hard limit เอง (524288) และ child สืบทอด (ปัญหา 1024 ที่เจอใน Docker จึงไม่เกิด) — **ต้องตรวจจริง** - **ข้อจำกัดที่ยอมรับ:** engine เป็นลูกของ agent systemd จึงหยุด engine พร้อมการรีสตาร์ท agent (เช่นตอนอัปเดต); engine เริ่มใหม่เองเมื่อมีการเรียกครั้งถัดไป ### 3.5 การต่อเข้ากับโค้ดเดิม - โค้ดเดิมเรียก engine ผ่านอินเทอร์เฟซ `modRunner` (Status/Pull/Start/Stop/Logs/Rmi) เพิ่ม `mixedRunner` ที่ส่งแต่ละ engine ไปยัง runner (docker) หรือ supervisor (host) ตามโหมด ส่วนอื่น (คิวงาน, อุ่น engine, หยุดเมื่อว่าง, ปักหมุด, หน้า comfy, ตัวติดตั้งโมดูล) ไม่ต้องรู้ว่าโหมดไหน - `Status` ของโหมด host: `state` = running/exited/ว่าง; `image_present` = มี `.wxch-ready`; `pulling` = กำลังติดตั้งรันไทม์; `pull_err` = ข้อผิดพลาดล่าสุด - ถ้าทุก engine เป็นโหมด host ไม่จำเป็นต้องมี runner/Docker (ตัวติดตั้งขั้น `modules` ผ่อนเงื่อนไขนี้เมื่อตั้ง `WXCH_ENGINE_MODE=host`) ### 3.6 ขนาดบนดิสก์ในหน้า "โมดูล AI" - แคตตาล็อกเพิ่ม `host_bytes` ต่อ engine (ค่าประมาณ ~5 GB: Python + torch + CUDA libs + แพ็กเกจ; ใช้ hard link ผ่านแคชของ uv ทำให้ engine ที่สองถูกกว่า) หน้าเว็บแสดงขนาดตามโหมดที่เลือก (docker = image 38.5 GB, host = `host_bytes`) ## 4. ความปลอดภัย: สิ่งที่เปลี่ยน และมาตรการ | เดิม (Docker) | ใหม่ (host) | |---|---| | ไม่มีสิทธิ์พิเศษ (`cap-drop ALL`, `no-new-privileges`) เห็นแค่โฟลเดอร์ engine | ทำงานเป็นผู้ใช้ `pgx` เห็นไฟล์ทั้งหมดของผู้ใช้นี้ | | ComfyUI ที่ผู้ดูแลเปิดผ่าน comfy. รัน workflow/custom node อะไรก็ได้ภายในกรง | โค้ดเดียวกันรันด้วยสิทธิ์ `pgx` | ข้อเท็จจริงที่ช่วยประเมิน: หน้า control มีเทอร์มินัลเว็บที่ให้เชลล์ของ `pgx` อยู่แล้ว (รหัสผ่านเดียวกัน + 2FA) ดังนั้นผู้ที่มีรหัสผ่านผู้ดูแลเข้าถึง `pgx` ได้อยู่แล้ว สิ่งที่เพิ่มขึ้นจริงคือ **ผู้ใช้ studio (งานที่ใช้ workflow สำเร็จรูป) และข้อบกพร่องของ ComfyUI/custom node** อยู่ในสิทธิ์ `pgx` แทนที่จะอยู่ในกรง มาตรการ: ผูก 127.0.0.1 เท่านั้น; ปิด API nodes; ไม่ส่ง environment/token ของ agent; ไม่มี custom node ที่ระบบติดตั้งให้; หน้า comfy. ยังเป็นผู้ดูแลเท่านั้น; ค่าเริ่มต้นยังเป็น docker สิ่งที่ **ไม่ทำ**: ไม่ผ่อนสิทธิ์ของ runner, ไม่เพิ่มสิทธิ์ให้ agent, ไม่ใช้ sudo ## 5. ความเสี่ยงและสิ่งที่ยังไม่รู้ 1. PyTorch 2.14.1+cu130 รองรับ GB10 (sm_121) จริงหรือไม่ — ยืนยันได้เฉพาะบนเครื่อง (ขั้นตรวจ GPU ในข้อ 3.3.5 จะบอก) → ถ้าไม่ได้ ใช้โหมด docker ต่อ 2. การแก้ dependency ของ `requirements.lab.txt` กับ torch ที่ pin (บางแพ็กเกจอาจดึง torch ตัวอื่น) → ใช้ `uv` ตรวจแล้วบังคับ constraint ให้ torch เป็นเวอร์ชันที่ pin 3. `av` (PyAV) ของ Whisper มีล้อที่รวม ffmpeg สำหรับ aarch64 หรือไม่ → ตรวจตอนติดตั้ง 4. GitHub/PyPI/PyTorch index ใช้งานไม่ได้ชั่วคราว → ติดตั้งต่อได้ (uv ใช้แคช) รายงานข้อผิดพลาดชัด 5. พื้นที่ดิสก์: ตรวจก่อนติดตั้ง (ใช้ `host_bytes` + พื้นที่สำรอง) 6. การติดตั้งซ้ำซ้อน/พร้อมกัน: ให้มีได้ทีละ engine (ล็อก) และติดตั้งซ้ำได้อย่างปลอดภัย (ต่อจากที่ค้าง) 7. engine ตายพร้อม agent รีสตาร์ท: ยอมรับ (บันทึกไว้) งานที่รันอยู่จะถูกส่งใหม่ตามกลไกเดิม ## 6. การทดสอบ - อัตโนมัติ (ไม่ต้องมี GPU): supervisor ด้วยโปรเซสจำลอง (ใช้ไบนารีทดสอบเองเป็น "python" ที่เปิดเซิร์ฟเวอร์เล็กๆ): เริ่ม/หยุด/สถานะ/ท้าย log/ฆ่าทั้งกลุ่ม; environment ไม่มี `WXCH_TOKEN`; ผูก 127.0.0.1; ตัวติดตั้งด้วย "uv" จำลอง (ตรวจลำดับคำสั่ง, ตรวจ sha256 ที่ไม่ตรงต้องปฏิเสธ, ตรวจข้อผิดพลาดของแต่ละขั้น); `mixedRunner` ส่งตามโหมด; การสลับโหมดปฏิเสธเมื่อมีงานรัน; ตรวจ `host_bytes` ในขนาดรวม - บนเครื่องจริง (ผู้ดูแลรัน): สลับโหมด → ติดตั้ง → ดู `import torch` + arch list → เริ่ม engine → สร้างภาพ 512×512 → วิดีโอ 2 วินาที → ถอดเสียง → สลับกลับ docker ตรวจว่ายังใช้ได้ ## 7. ขั้นตอนทำงาน (ตามลำดับ) 1. แคตตาล็อก: `host_bytes`, ค่า torch/uv ที่ปัก; ตารางโหมด; test ของแคตตาล็อก 2. `hostengine.go` (+ ไฟล์เฉพาะ Linux/อื่นๆ สำหรับ `Setpgid`): ติดตั้ง uv/venv/ขั้นตอน 3.3, supervisor 3.4 3. `mixedRunner` + `pickModRunner` + สถานะโหมดใน `state.json` + RPC `modules.mode` 4. `whisper_server.py --host` 5. หน้า "โมดูล AI": ตัวเลือกโหมด + ขนาดตามโหมด + ป้ายความคืบหน้าการติดตั้งรันไทม์ 6. ตัวติดตั้ง: `WXCH_ENGINE_MODE=host` ข้ามข้อกำหนด Docker/runner ของขั้น modules 7. เอกสาร (HANDOFF, INSTALL, เอกสารที่ note.), deploy; ค่าเริ่มต้นยังเป็น docker 8. ผู้ดูแลทดสอบบน PGX ตามข้อ 6 → ถ้าผ่าน เปลี่ยนค่าเริ่มต้นเป็น host (งานแยก) ## 8. คำถามที่อยากให้ผู้รีวิวดูเป็นพิเศษ - ลำดับ/คำสั่งติดตั้งในข้อ 3.3 ถูกต้องและกันกรณีล้มเหลวครบไหม (โดยเฉพาะ `--torch-backend cu130`, การปัก constraint ของ torch ตอนติดตั้ง requirements) - supervisor (ข้อ 3.4): มีช่องทางที่ environment หรือ token ของ agent รั่วเข้า engine หรือไม่; การหยุดทั้งกลุ่มโปรเซสครบหรือไม่; race ระหว่างเริ่ม/หยุด/ตรวจสถานะ - ความปลอดภัยข้อ 4: มีมาตรการที่เบาแต่ได้ผลที่ขาดไปไหม (เช่น ใช้ `systemd-run --user --scope`/ข้อจำกัดทรัพยากร หรือ user แยกต่างหาก) - การสลับโหมด: มีสถานะค้างหรือ engine ซ้ำสองโหมดพร้อมกันได้ไหม