NVIDIA NemoClaw là một hệ thống điều phối agent mã nguồn mở, cấp doanh nghiệp, được xây dựng trên OpenClaw. Nó vận hành các AI agent bên trong môi trường sandbox với gateway tích hợp, bộ nhớ hội thoại bền vững, khung tool-use và cơ chế định tuyến đa mô hình, tất cả gói trong một Docker image được build trực tiếp từ source của NVIDIA.

GreenNode AgentBase là môi trường runtime container được quản lý trên  GreenNode AI platform. Nó xử lý việc kéo image, health check, auto-scaling, tracking version và expose endpoint HTTPS, nên tôi không phải tự quản lý Kubernetes.

Nghe thì có vẻ đơn giản khi ghép hai thứ này lại với nhau. Thực tế thì không. Bài hướng dẫn này ghi lại chính xác những gì bị lỗi, vì sao lỗi, và cách fix cụ thể, để tôi có thể deploy NemoClaw lên GreenNode trơn tru trong một lượt.

Tôi viết từ góc nhìn của người vận hành. Thay vì một kiểu “hello world” chung chung, đây là đúng con đường tôi đi: từ lệnh docker build trên một máy Windows tới một endpoint đã có TLS, auto-scale, đặt trước một mô hình 27B tham số bên trong GreenNode.

Nếu bạn đang ở môi trường tương tự — network enterprise, private registry, health check chặt chẽ — các ràng buộc ở đây sẽ rất quen thuộc.

Chúng ta sẽ xây gì

Chúng ta sẽ deploy một runtime NemoClaw “thật” trên GreenNode AgentBase — build từ source chính thức của NVIDIA tại github.com/NVIDIA/NemoClaw, không dùng image dựng sẵn.

NemoClaw là hệ thống điều phối OpenClaw agent bảo mật của NVIDIA. Nó chạy các OpenClaw agent trong môi trường sandbox với gateway tích hợp, memory hội thoại và hỗ trợ nhiều mô hình.

Cuối cùng bạn sẽ có:

  • Một endpoint HTTPS đang chạy NemoClaw
  • NemoClaw sử dụng backend LLM MaaS của GreenNode (qwen3, llama, v.v.)
  • Auto-scaling — GreenNode tự xử lý khi tải tăng
  • Triển khai có version, có lịch sử, rollback được

nemoclaw-v2 runtime showing ACTIVE status on GreenNode AgentBase

Kết quả thực tế

Runtime nemoclaw-v2 đang ở trạng thái ACTIVE tại:   https://endpoint-4d91a252-b1ab-4e61-9a4f-fa8cfb50e6c1.agentbase-runtime.aiplatform.vngcloud.vn

Kiến trúc tổng quan

Vấn đề kiến trúc chính là lệch port: GreenNode kiểm tra health trên port 8080, trong khi dashboard NemoClaw chạy trên port 18789. Giải pháp là một Bash wrapper mỏng, khởi động một HTTP server Python trên :8080 rồi mới chuyển quyền cho nemoclaw-start.

[Máy của bạn] [GreenNode Cloud]
git clone NVIDIA/NemoClaw ──► vCR Container Registry
Fix CRLF + BOM (Windows) ──► AgentBase Runtime (port 8080 ✓)
Thêm wrapper port 8080 ──► HTTPS Endpoint (auto-TLS)
docker build (56 stage) ──► MaaS LLM: qwen3-27b
docker push :v1, :v2 ...

Những bẫy đã gặp (nên đọc trước khi bắt đầu)

Đây là 6 vấn đề từng làm deployment fail trong thực tế. Mỗi cái đều khá “im lặng” đủ để bạn mất hàng giờ nếu không biết trước. Các bước bên dưới đã tích hợp sẵn fix — bảng này là cheat sheet.

#Vấn đềKhi nào xảy raCách xử lý nhanh
1Dòng CRLFKhi build Docker hoặc khởi động containerChạy vòng lặp PowerShell chuyển CRLF sang LF ở Bước 2a trước khi build.
2BOM UTF-8 trong file mớiBuild Docker, thường là lỗi SyntaxError ở dòng 1Dùng New-Object System.Text.UTF8Encoding($false) mỗi khi PowerShell ghi file.
3NemoClaw dùng port 18789, GreenNode đòi 8080Runtime kẹt ở trạng thái ERROR dù đã pull image thành côngThêm greennode-start.sh ở Bước 3.
4GreenNode cache image theo tagImage mới bị bỏ qua, code cũ vẫn chạyLuôn push với tag mới như :v2 hoặc :v3.
5Ô Image authentication không được tickFailed to pull image ngay lần deploy đầuPhải tick ô này — chỉ điền username và password là chưa đủ.
6Password bị xoá mỗi lần mở trang EditNút SAVE luôn bị mờNhập lại password của robot vCR mỗi lần mở form Edit.

Pitfall 1: Dòng CRLF

Trên Windows, Git thường để core.autocrlf=true nên tự động chuyển mọi \n thành \r\n khi clone. NemoClaw có hơn 1.810 script shell. Tất cả sẽ fail lúc runtime với lỗi:

env: 'bash\r': No such file or directory

Cách xử lý: vòng lặp PowerShell ở Bước 2a sẽ loại hết ký tự carriage return trước khi build.

Pitfall 2: UTF-8 BOM

Mặc định, [System.Text.Encoding]::UTF8 của PowerShell sẽ thêm BOM (\xEF\xBB\xBF) vào đầu mọi file. Bash từ chối chạy script mà byte đầu tiên không phải #, và Node.js sẽ ném syntax error ở dòng 1.

Cách xử lý: dùng New-Object System.Text.UTF8Encoding($false).

Pitfall 3: Port 8080 vs 18789

Health checker của GreenNode luôn gọi port 8080 và chỉ đánh dấu runtime ACTIVE nếu nhận HTTP 200. Dashboard NemoClaw lại lắng nghe trên port 18789. Container vẫn start và chạy, nhưng GreenNode không thấy 200 trên port 8080, nên runtime bị chuyển sang ERROR.

Wrapper greennode-start.sh ở Bước 3 sẽ chạy một HTTP server Python nhỏ trên port 8080 rồi mới gọi nemoclaw-start. Health check pass, NemoClaw chạy bình thường.

Pitfall 4: Cache image theo tag

GreenNode cache Docker image theo tag. Nếu bạn push image mới lên tag :latest và update runtime, GreenNode có thể bỏ qua pull mới và tiếp tục dùng layer cache cũ.

Luôn tăng tag — ví dụ :v1 → :v2 → :v3 — và cập nhật lại Image URL trong form edit runtime cho khớp.

Pitfall 5: Ô Image authentication

Form Create/Edit Runtime có checkbox Image authentication và mặc định là không tick. Việc điền username và password không có tác dụng nếu checkbox này chưa bật.

Nếu bỏ qua, GreenNode sẽ pull image không dùng auth và fail với thông báo Failed to pull image.

Pitfall 6: Password bị xoá khi Edit

Mỗi lần mở trang Edit runtime, GreenNode sẽ xoá nội dung field password. Nút SAVE sẽ bị disable cho tới khi cả username và password đều có giá trị.

Kể cả khi bạn chỉ mở Edit để đổi tag image, vẫn bắt buộc nhập lại password.

Yêu cầu kỹ thuật cần chuẩn bị

  • Tài khoản GreenNode — aiplatform.console.vngcloud.vn
  • Docker Desktop đã cài trên máy.
  • Git đã cài, và nắm rõ core.autocrlf trên Windows.
  • Đã tạo repository trên vCR — vcr.vngcloud.vn/YOUR-ORG/nemoclaw
  • Tài khoản robot trên vCR có quyền push/pull.
  • API key GreenNode MaaS từ mục API Keys trong portal.

Quy trình triển khai từng bước

Đây là đúng chuỗi bước tôi dùng, từ một bản clone mới của repo NVIDIA đến khi runtime ACTIVE trên GreenNode. Làm lần lượt, bạn sẽ thấy cùng một kết quả.

Bước 1: Clone NVIDIA/NemoClaw

git clone https://github.com/NVIDIA/NemoClaw
cd NemoClaw

Người dùng Windows nên đọc đoạn này trước. Git trên Windows thường để core.autocrlf=true, âm thầm chuyển toàn bộ \n thành \r\n trong mọi file. Image NemoClaw có hơn 1.800 script shell và file JavaScript. Nếu build với dòng CRLF, container sẽ fail với:

env: 'bash\r': No such file or directory

Luôn xử lý lại line endings trước khi build.

Bước 2: Sửa line endings và BOM (chỉ Windows)

Người dùng macOS và Linux có thể bỏ qua bước này.

2a. Chuyển toàn bộ file từ CRLF sang LF

Chạy script PowerShell này trong thư mục NemoClaw:

# Convert CRLF → LF across all text files
Get-ChildItem -Recurse -File | Where-Object {
$_.Extension -match '.(sh|js|ts|json|md|txt|yaml|yml|env|conf|cfg|ini|py|rb|pl)$' -or
$_.Name -notmatch '.'
} | ForEach-Object {
$content = [System.IO.File]::ReadAllText($_.FullName)
$fixed = $content.Replace("rn", "n").Replace("r", "`n")
if ($content -ne $fixed) {
[System.IO.File]::WriteAllText(
$_.FullName,
$fixed,
(New-Object System.Text.UTF8Encoding($false))
)
} }
Write-Host "Done"

2b. Vì sao New-Object System.Text.UTF8Encoding($false) quan trọng

Writer UTF-8 mặc định của PowerShell sẽ thêm BOM. Kết quả là:

SyntaxError: Invalid or unexpected token

ngay dòng đầu trong các file JavaScript khi build Docker. Tham số $false tạo encoder UTF-8 không BOM.

Kiểm tra lại

# Kết quả phải là 0
$bytes = [System.IO.File]::ReadAllBytes("scripts\nemoclaw-start.sh")
($bytes | Where-Object { $_ -eq 13 }).Count

Bước 3: Thêm wrapper health check port 8080 cho GreenNode

GreenNode AgentBase chỉ đánh dấu runtime ACTIVE khi nhận được HTTP 200 trên port 8080. Dashboard NemoClaw thì chạy trên port 18789. Không có cầu nối, mọi lần deploy đều kết thúc bằng trạng thái ERROR.

Tạo file greennode-start.sh ở thư mục gốc repo NemoClaw:

#!/usr/bin/env bash

GreenNode AgentBase wrapper — bridges port 8080 health check to NemoClaw.
set -eu
echo "[greennode-start] Starting health server on :8080" >&2
cat > /tmp/greennode-health.py << 'PYEOF'
import http.server, threading, time
class Handler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-Type', 'text/plain; charset=utf-8')
self.send_header('Connection', 'close')
self.end_headers()
self.wfile.write(b'NemoClaw OK\n')
def do_HEAD(self):
self.send_response(200)
self.send_header('Content-Type', 'text/plain; charset=utf-8')
self.send_header('Connection', 'close')
self.end_headers()
def log_message(self, fmt, *args):
pass
server = http.server.HTTPServer(('0.0.0.0', 8080), Handler)
threading.Thread(target=server.serve_forever, daemon=True).start()
print('[greennode-start] Health server ready on :8080', flush=True)
while True:
time.sleep(3600)
PYEOF
python3 /tmp/greennode-health.py &
_HEALTH_PID=$!
echo "[greennode-start] Health server PID: $_HEALTH_PID" >&2
sleep 1
/usr/local/bin/nemoclaw-start "$@" || {
echo "[greennode-start] nemoclaw-start exited — container kept alive for diagnostics" >&2
}
wait $_HEALTH_PID

Trên Windows, chuyển file này sang LF ngay sau khi lưu:

$f = "greennode-start.sh"
$content = [System.IO.File]::ReadAllText($f)
$fixed = $content.Replace("rn", "`n")
[System.IO.File]::WriteAllText($f, $fixed, (New-Object System.Text.UTF8Encoding($false)))

Sau đó thêm đoạn này vào cuối Dockerfile:

# -- GreenNode AgentBase compatibility -------------------------------------
COPY greennode-start.sh /usr/local/bin/greennode-start
RUN chmod +x /usr/local/bin/greennode-start
EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/greennode-start"]
CMD ["/bin/bash"]

Dockerfile lúc này sẽ có hai dòng ENTRYPOINT, linter sẽ cảnh báo nhưng có thể bỏ qua — Docker luôn dùng ENTRYPOINT ở cuối.

Bước 4: Dựng Docker image

Dockerfile của NemoClaw là multi-stage build 56 stage, dựa trên ghcr.io/nvidia/nemoclaw/sandbox-base:latest. Lần build đầu tiên thường mất 30–45 phút. Các lần sau nếu tận dụng cache layer sẽ khoảng 2–5 phút.

# Windows PowerShell
docker build `
--build-arg NEMOCLAW_MODEL=qwen/qwen3-5-27b `
--build-arg NEMOCLAW_INFERENCE_BASE_URL=https://maas-llm-aiplatform-hcm.api.vngcloud.vn/v1 `
--build-arg NEMOCLAW_INFERENCE_API=openai-completions `
--build-arg NEMOCLAW_DISABLE_DEVICE_AUTH=1 `
-t vcr.vngcloud.vn/YOUR-ORG/nemoclaw:v1 `
. 2>&1 | Tee-Object -FilePath docker-build.log

macOS / Linux
docker build
--build-arg NEMOCLAW_MODEL=qwen/qwen3-5-27b
--build-arg NEMOCLAW_INFERENCE_BASE_URL=https://maas-llm-aiplatform-hcm.api.vngcloud.vn/v1
--build-arg NEMOCLAW_INFERENCE_API=openai-completions
--build-arg NEMOCLAW_DISABLE_DEVICE_AUTH=1
-t vcr.vngcloud.vn/YOUR-ORG/nemoclaw:v1
. 2>&1 | tee docker-build.log
Tham sốGiá trịGhi chú
NEMOCLAW_MODELqwen/qwen3-5-27bHoặc bất kỳ model MaaS nào của GreenNode.
NEMOCLAW_INFERENCE_BASE_URLhttps://maas-llm-aiplatform-hcm.api.vngcloud.vn/v1Endpoint MaaS của GreenNode.
NEMOCLAW_INFERENCE_APIopenai-completionsDùng cho endpoint tương thích OpenAI.
NEMOCLAW_DISABLE_DEVICE_AUTH1Bỏ bước pair device trong môi trường headless/cloud.

Kiểm tra kết quả build

#56 naming to vcr.vngcloud.vn/YOUR-ORG/nemoclaw:v1 done
#56 DONE 2.3s

Nếu build fail, kiểm tra docker-build.log xem có lỗi liên quan tới CRLF hoặc BOM.

Bước 5: Đăng nhập vCR và push

docker login vcr.vngcloud.vn
--username YOUR-ROBOT-ACCOUNT
--password YOUR-ROBOT-PASSWORD

docker push vcr.vngcloud.vn/YOUR-ORG/nemoclaw:v1

Ghi lại digest từ output của lệnh push — bạn sẽ cần nó để đối chiếu các lần redeploy.

v1: digest: sha256:b2aa855806643cabfbef0f08e1450e3d2e2350f9078056f00ec60ee3f03ab7f5 size: 857

Luôn dùng tag version cụ thể như :v1, :v2, :v3 — đừng chỉ dựa vào :latest.

Bước 6: Deploy lên GreenNode AgentBase

6a. Vào mục Agent Runtime

https://aiplatform.console.vngcloud.vn/agent-runtime

Bấm Deploy a new Agent → Custom Agent.

6b. Điền form runtime

TrườngGiá trị
Agent runtime namenemoclaw-v2 (hoặc tên bạn chọn)
Image URLvcr.vngcloud.vn/YOUR-ORG/nemoclaw:v1
Flavorruntime-s2-general-2x4 (2 CPU, 4 GB — mức tối thiểu khuyến nghị)
Min/Max replicas1 / 1

6c. Quan trọng: bật Image authentication

Đây là chỗ dễ fail nhất. Form có ô Image authentication mặc định không tick. Kể cả khi điền username và password, GreenNode vẫn không dùng nếu bạn không tick ô này.

Sau khi tick, điền:

  • Username: tên tài khoản robot trên vCR.
  • Password: mật khẩu robot trên vCR.

6d. Thêm biến môi trường

KeyGiá trị
LLM_API_KEYAPI key MaaS của bạn trên GreenNode
OPENSHELL_SANDBOX1

6e. Lưu và xác nhận

Bấm SAVE, sau đó Confirm trong hộp thoại xác nhận.

Bước 7: Quan sát runtime chuyển sang ACTIVE

Sau khi lưu, runtime sẽ vào trạng thái UPDATING trong lúc GreenNode:

  • Kéo image từ vCR (lần đầu có thể mất 3–5 phút).
  • Khởi động container.
  • Gọi health check HTTP trên port 8080.
  • Nếu nhận HTTP 200, runtime chuyển sang ACTIVE.

Refresh trang chi tiết runtime khoảng 30 giây một lần. Trạng thái thường đi theo chuỗi:

UPDATING → ACTIVE
UPDATING → ERROR

Endpoints tab showing DEFAULT endpoint ACTIVE, associated with Version 4

 

TrườngGiá trị
Runtime statusACTIVE
Endpoint statusACTIVE
Associated versionVersion 4, hoặc version hiện tại của bạn
Endpoint URLhttps://endpoint-xxx.agentbase-runtime.aiplatform.vngcloud.vn

Bước 8: Test endpoint

Health check

curl https://endpoint-4d91a252-b1ab-4e61-9a4f-fa8cfb50e6c1.agentbase-runtime.aiplatform.vngcloud.vn

Kỳ vọng: HTTP 200, body: "NemoClaw OK"

Bạn cũng có thể mở endpoint trực tiếp trên trình duyệt và kỳ vọng thấy chuỗi NemoClaw OK.

Live endpoint returning "NemoClaw OK" from the port 8080 health server

Cập nhật deployment

Khi bạn push image mới (sửa bug, đổi model hoặc thay config):

docker build ... -t vcr.vngcloud.vn/YOUR-ORG/nemoclaw:v2 .
docker push vcr.vngcloud.vn/YOUR-ORG/nemoclaw:v2

Sau đó, trên GreenNode:

  • Bấm Edit trên runtime.
  • Đổi Image URL từ :v1 sang :v2.
  • Nhập lại password registry.
  • Đảm bảo ô Image authentication vẫn đang bật.
  • Bấm SAVE → Confirm.

Mỗi lần chỉnh sửa sẽ tạo ra một Version được đánh số trong tab Version, cho bạn lịch sử đầy đủ để rollback.

Version tab showing the complete deployment history with descriptions

Xử lý sự cố

Failed to pull image

Nguyên nhân: Ô Image authentication chưa được tick.

Cách xử lý: Edit runtime, tick lại checkbox, nhập password, rồi lưu.

env: 'bash\r': No such file or directory

Nguyên nhân: Script shell vẫn còn line ending CRLF của Windows.

Cách xử lý: Chạy lại bước chuyển CRLF → LF ở Bước 2a rồi build lại.

SyntaxError: Invalid or unexpected token ở dòng 1 file .js

Nguyên nhân: PowerShell ghi file với UTF-8 có BOM.

Cách xử lý: Dùng New-Object System.Text.UTF8Encoding($false) như Bước 2b, rồi build lại.

Runtime chuyển từ UPDATING sang ERROR sau khi pull image

Nguyên nhân: Container fail health check trên port 8080.

Cách xử lý: Đảm bảo đã thêm greennode-start.sh vào Dockerfile và test local:

docker run --rm -p 8080:8080 vcr.vngcloud.vn/YOUR-ORG/nemoclaw:v1

Trong terminal khác:
curl http://localhost:8080

Kỳ vọng: trả về "NemoClaw OK"

Runtime vẫn ERROR sau khi push image mới với tag :latest

Nguyên nhân: GreenNode cache image cũ của :latest và không pull lại.

Cách xử lý: Push với tag mới và cập nhật Image URL trong form edit runtime.

Nút SAVE vẫn mờ ở màn hình Edit runtime

Nguyên nhân: Field password rỗng (bị xoá mỗi lần tải lại trang).

Cách xử lý: Nhập lại password tài khoản robot vCR. Khi cả username và password đều có, nút SAVE sẽ sáng.

Mỗi Version chứa gì

VersionMô tảTrạng thái
Version 1Deploy lần đầu, image :latest gốc, chưa fix port 8080ERROR
Version 2Image đã fix LF, nhưng chưa có wrapper port 8080ERROR
Version 3Đã thêm wrapper cho port 8080ERROR do vẫn dùng image cache cũ
Version 4Ép GreenNode pull image mới bằng tag :v3ACTIVE 

Các thông số chính

MụcGiá trị
Source repogithub.com/NVIDIA/NemoClaw
Số stage Dockerfile56 (54 cho NemoClaw + 2 cho wrapper GreenNode)
Thời gian build đầu tiên~30–45 phút
Build lại có cache~2–5 phút
Image trên vCRvcr.vngcloud.vn/92566-openclaw-agent/nemoclaw:v3
Image digestsha256:b2aa855806643cabfbef0f08e1450e3d2e2350f9078056f00ec60ee3f03ab7f5
Runtime IDruntime-215aae39-b097-4ba4-ad6a-1547e9287eb1
Endpointhttps://endpoint-4d91a252-b1ab-4e61-9a4f-fa8cfb50e6c1.agentbase-runtime.aiplatform.vngcloud.vn
LLMqwen/qwen3-5-27b thông qua GreenNode MaaS
Flavorruntime-s2-general-2×4 (2 CPU, 4 GB RAM)

Build ngày 2026-06-09. Runtime nemoclaw-v2, Version 4.

Từ Endpoint HTTPS đến một trợ lý thực sự

Tới thời điểm này, NemoClaw thực sự đã chạy trên GreenNode AgentBase. Runtime nemoclaw-v2 đang ACTIVE, endpoint HTTPS đã up, qwen3-27b được nối qua GreenNode MaaS. Sáu cái bẫy ban đầu — từ CRLF âm thầm phá hỏng hơn 1.800 script tới ô auth tí hon chặn image pull mà không log gì rõ ràng — đều đã xử lý xong. Nhưng chỉ một endpoint HTTPS trần thì vẫn chưa phải là một AI assistant. Để NemoClaw thực sự trả lời ai đó, nó cần một lớp giao tiếp.

Phần 2 sẽ xây chính lớp đó: một Telegram bridge chạy như một runtime AgentBase riêng — nhận message từ Telegram, gọi trực tiếp LLM MaaS của GreenNode, rồi gửi câu trả lời về. Bạn sẽ thấy vì sao bridge buộc phải là một runtime tách biệt (proxy outbound của flavor 2×4 chặn kết nối tới Telegram), cách đăng ký webhook để Telegram chủ động push update thay vì bridge phải poll, và tám cái bẫy mới chỉ xuất hiện ở giai đoạn này.