Cài đặt OpenClaw bằng Portainer

Mục tiêu
Tài liệu này hướng dẫn cài OpenClaw bằng Portainer với Stack trên Web editor.
Hướng dẫn phù hợp cho 2 kiểu triển khai:
Kiểu 1: Docker host + NAS
Docker chạy trên một máy Ubuntu
Config/workspace lưu trên NAS mount vào Docker host
Kiểu 2: Một máy duy nhất
Docker, config, workspace đều lưu trên cùng một máy
Sau khi hoàn tất
OpenClaw container: openclaw-gateway
Port: 18789
Domain ví dụ: https://oclaw.example.com
WebSocket URL: wss://oclaw.example.com
Quản lý stack: Portainer Full Control
Mô hình truy cập qua domain
Client Browser
    ↓ HTTPS / WSS
Nginx Proxy Manager
    ↓ HTTP / WebSocket
Docker Host
    ↓
OpenClaw Gateway Container
Tóm tắt nhanh
Các bước chính:
Chọn kiểu lưu dữ liệu: NAS hoặc một máy
Tạo thư mục dữ liệu
Tạo Gateway Token
Tạo Portainer Stack bằng Web editor
Nhập biến môi trường cho đúng đường dẫn lưu trữ
Deploy OpenClaw Gateway
Compose tự tạo config ban đầu trước khi start gateway
Cấu hình NPM reverse proxy + WebSocket
Truy cập domain HTTPS
Approve device pairing nếu cần
Quản lý stack bằng Portainer để giữ Full Control
Chuẩn bị thông tin môi trường
Trước khi làm, cần xác định các giá trị sau.
Ví dụ trong bài:
Docker Host IP: 192.168.1.103
Nginx Proxy Manager IP: 192.168.1.102
Domain OpenClaw: oclaw.example.com
OpenClaw port: 18789
Thay lại theo môi trường thực tế của bạn.
Chọn kiểu lưu dữ liệu
Kiểu A — Docker host + NAS
Dùng khi Docker chạy trên một máy Ubuntu, còn dữ liệu lớn hoặc workspace lưu trên NAS.
Ví dụ:
Config:    /mnt/dsm/docker/OpenClaw/config → Lưu file cấu hình OpenClaw
Workspace: /mnt/dsm/docker/OpenClaw/workspace → Lưu workspace, file làm việc, memory, context
Auth:      /opt/appdata/openclaw/auth → Lưu auth secret local trên Docker host
Kiểu B — Cài toàn bộ trên một máy
Dùng khi không có NAS, mọi thứ lưu trên chính Docker host. Kiểu này đơn giản hơn, phù hợp với VPS, mini PC, hoặc homelab một máy.
Ví dụ:
Config:    /opt/appdata/openclaw/config → Lưu file cấu hình OpenClaw
Workspace: /opt/appdata/openclaw/workspace → Lưu workspace, file làm việc, memory, context
Auth:      /opt/appdata/openclaw/auth → Lưu auth secret local trên Docker host
Tạo thư mục dữ liệu
Nếu dùng NAS
sudo mkdir -p /mnt/dsm/docker/OpenClaw/config
sudo mkdir -p /mnt/dsm/docker/OpenClaw/workspace
sudo mkdir -p /opt/appdata/openclaw/auth
sudo chown -R 1000:1000 /mnt/dsm/docker/OpenClaw
sudo chown -R 1000:1000 /opt/appdata/openclaw
Các đường dẫn dùng trong Portainer:
OPENCLAW_CONFIG_HOST_DIR=/mnt/dsm/docker/OpenClaw/config
OPENCLAW_WORKSPACE_HOST_DIR=/mnt/dsm/docker/OpenClaw/workspace
OPENCLAW_AUTH_HOST_DIR=/opt/appdata/openclaw/auth
Nếu cài toàn bộ trên một máy
sudo mkdir -p /opt/appdata/openclaw/config
sudo mkdir -p /opt/appdata/openclaw/workspace
sudo mkdir -p /opt/appdata/openclaw/auth
sudo chown -R 1000:1000 /opt/appdata/openclaw
Các đường dẫn dùng trong Portainer:
OPENCLAW_CONFIG_HOST_DIR=/opt/appdata/openclaw/config
OPENCLAW_WORKSPACE_HOST_DIR=/opt/appdata/openclaw/workspace
OPENCLAW_AUTH_HOST_DIR=/opt/appdata/openclaw/auth
Tạo Gateway Token
Chạy trên Docker host:
openssl rand -hex 32
Ví dụ output:
aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899
Copy token này lại. Lát nữa sẽ nhập vào Portainer với biến:
OPENCLAW_GATEWAY_TOKEN
Token này dùng để đăng nhập OpenClaw Control UI.
Tạo OpenClaw Stack trong Portainer
Vào Portainer > Stacks > Add stack
Thiết lập:
Name: openclaw
Build method: Web editor
Dán compose sau vào Web editor:
Dán compose sau vào Web editor:
services:
  openclaw-gateway:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw-gateway
    restart: unless-stopped
    init: true
    environment:
      TZ: Asia/Bangkok
      HOME: /home/node
      OPENCLAW_STATE_DIR: /home/node/.openclaw
      OPENCLAW_CONFIG_DIR: /home/node/.openclaw
      OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
      OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
      OPENCLAW_AUTH_PROFILE_SECRET_DIR: /home/node/.config/openclaw
      OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN}
      OPENCLAW_DISABLE_BONJOUR: "1"
      OPENCLAW_DOMAIN: ${OPENCLAW_DOMAIN}
      OPENCLAW_TRUSTED_PROXY_IP: ${OPENCLAW_TRUSTED_PROXY_IP}
    volumes:
      - ${OPENCLAW_CONFIG_HOST_DIR}:/home/node/.openclaw
      - ${OPENCLAW_WORKSPACE_HOST_DIR}:/home/node/.openclaw/workspace
      - ${OPENCLAW_AUTH_HOST_DIR}:/home/node/.config/openclaw
    ports:
      - "18789:18789"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    cap_drop:
      - NET_RAW
      - NET_ADMIN
    security_opt:
      - no-new-privileges:true
    command:
      - sh
      - -lc
      - |
        node dist/index.js config set --batch-json "[
          {\"path\":\"gateway.mode\",\"value\":\"local\"},
          {\"path\":\"gateway.bind\",\"value\":\"lan\"},
          {\"path\":\"gateway.controlUi.allowInsecureAuth\",\"value\":false},
          {\"path\":\"gateway.controlUi.allowedOrigins\",\"value\":[
            \"https://${OPENCLAW_DOMAIN}\",
            \"http://127.0.0.1:18789\",
            \"http://localhost:18789\"
          ]},
          {\"path\":\"gateway.trustedProxies\",\"value\":[\"${OPENCLAW_TRUSTED_PROXY_IP}\"]}
        ]"
        exec node dist/index.js gateway --bind lan --port 18789
    healthcheck:
      test:
        [
          "CMD",
          "node",
          "-e",
          "fetch('http://127.0.0.1:18789/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
        ]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s
Điểm quan trọng của compose này:
Trước khi start gateway, container tự chạy: 
node dist/index.js config set ...
Sau đó mới chạy: 
node dist/index.js gateway --bind lan --port 18789
Nhờ vậy, cài mới sẽ không bị lỗi Missing config do thư mục config trống.
Thêm biến môi trường trong Portainer
Trong phần Environment variables của Portainer, thêm các biến dưới đây rồi nhấn Deploy the stack
Nếu dùng NAS
OPENCLAW_GATEWAY_TOKEN=token_vừa_tạo → Token dùng để đăng nhập Control UI
OPENCLAW_DOMAIN=oclaw.example.com → Domain dùng để truy cập OpenClaw, không có https:// phía trước
OPENCLAW_TRUSTED_PROXY_IP=192.168.1.102 → IP của Nginx Proxy Manager nhìn từ OpenClaw Gateway
OPENCLAW_CONFIG_HOST_DIR=/mnt/dsm/docker/OpenClaw/config
OPENCLAW_WORKSPACE_HOST_DIR=/mnt/dsm/docker/OpenClaw/workspace
OPENCLAW_AUTH_HOST_DIR=/opt/appdata/openclaw/auth
Nếu cài toàn bộ trên một máy
OPENCLAW_GATEWAY_TOKEN=token_vừa_tạo
OPENCLAW_DOMAIN=oclaw.example.com
OPENCLAW_TRUSTED_PROXY_IP=192.168.1.102
OPENCLAW_CONFIG_HOST_DIR=/opt/appdata/openclaw/config
OPENCLAW_WORKSPACE_HOST_DIR=/opt/appdata/openclaw/workspace
OPENCLAW_AUTH_HOST_DIR=/opt/appdata/openclaw/auth
Kiểm tra trạng thái Gateway
Chạy trên Docker host:
docker logs --tail 80 openclaw-gateway
Nếu thấy:
[gateway] ready
là OpenClaw Gateway đã chạy thành công.
Kiểm tra health:
curl -fsS http://127.0.0.1:18789/healthz
curl -fsS http://127.0.0.1:18789/readyz
Nếu lệnh trả về OK hoặc JSON hợp lệ thì gateway đã sẵn sàng.
Xem log realtime:
docker logs -f openclaw-gateway
Hoặc các bạn cũng có thể kiểm tra log và trạng thái trên Portainer nếu đã quen sử dụng.
Cấu hình Nginx Proxy Manager
Trong Nginx Proxy Manager, tạo hoặc sửa Proxy Host:
Domain Names: oclaw.example.com
Scheme: http
Forward Hostname / IP: 192.168.1.103 → IP của Docker host chạy OpenClaw
Forward Port: 18789
Websockets Support: ON
Block Common Exploits: ON
Tab SSL:
Request a new SSL Certificate hoặc chọn certificate đã có
Force SSL: ON
HTTP/2 Support: ON
Truy cập OpenClaw qua domain
Mở trình duyệt 
https://oclaw.example.com
Điền:
WebSocket URL: wss://oclaw.example.com 
Gateway Token: token đã tạo ở bước 6 
Password: bỏ trống
Sau đó bấm Connect
Nếu thiết bị hoặc trình duyệt này chưa từng được approve, OpenClaw có thể yêu cầu device pairing.
Approve thiết bị mới
Bạn có thể truy cập Portainer > Containers > openclaw (container mà bạn đã cài) > Console
Tại đây bạn chạy các lệnh 
// Lấy danh sách thiệt bị Paired và thiết bị Pending
openclaw devices list
// Thay 0883e383-3e7d-4abb-af40-65a52296a04c bằng request thực tế mà bạn thấy
openclaw devices approve 0883e383-3e7d-4abb-af40-65a52296a04c
Sau đó quay lại browser và bấm Connect lại.
Phụ lục
Ghi chú bảo mật
OpenClaw là agent gateway, có thể kết nối tool, browser, file, memory và automation. Không nên public rộng rãi nếu chưa có lớp bảo vệ phù hợp.
Khuyến nghị tối thiểu:
Luôn dùng HTTPS
 Không bật allowInsecureAuth khi dùng domain 
Giữ Gateway Token 
Giữ Device Pairing 
Bật WebSocket qua NPM 
Dùng NPM Access List nếu chỉ muốn truy cập nội bộ 
Với domain HTTPS: 
https://oclaw.example.com
WebSocket URL phải là: 
wss://oclaw.example.com
Không dùng 
ws://oclaw.example.com vì domain đang chạy qua HTTPS.
Lỗi Missing config
Hiện tượng
Container OpenClaw restart liên tục. Log có dạng:
[gateway] loading configuration…
[gateway] resolving authentication…
Missing config. Run `openclaw setup` or set gateway.mode=local (or pass --allow-unconfigured).
Nguyên nhân
Lỗi này xảy ra khi thư mục config của OpenClaw đang trống, chưa có 
openclaw.json hợp lệ.
Thường gặp khi:
Xóa thư mục config cũ 
Mount sai thư mục config 
Container start gateway trước khi tạo config
Cách tránh lỗi
Dùng compose trong tài liệu này.
Compose đã cấu hình để container tự chạy:
node dist/index.js config set --batch-json ...
trước khi chạy gateway.
Cách sửa nếu vẫn gặp lỗi
Kiểm tra mount config:
Nếu dùng NAS:
ls -lah /mnt/dsm/docker/OpenClaw/config
Nếu cài toàn bộ trên một máy:
ls -lah /opt/appdata/openclaw/config
Kiểm tra log:
docker logs --tail 80 openclaw-gateway
Nếu vẫn thiếu config, vào Portainer kiểm tra lại các biến:
OPENCLAW_CONFIG_HOST_DIR
OPENCLAW_WORKSPACE_HOST_DIR
OPENCLAW_AUTH_HOST_DIR
OPENCLAW_DOMAIN
OPENCLAW_TRUSTED_PROXY_IP
OPENCLAW_GATEWAY_TOKEN
Sau khi sửa biến, re-deploy stack trong Portainer.
Xóa OpenClaw cũ nếu đã từng cài
Xóa docker container
# Dừng stack cũ nếu trước đó cài bằng Docker Compose CLI
cd /opt/stacks/openclaw 2>/dev/null && docker compose down -v --remove-orphans || true
# Xóa mọi container có tên openclaw
docker ps -aq --filter "name=openclaw" | xargs -r docker rm -f
# Xóa network openclaw cũ nếu còn
docker network ls --format '{{.Name}}' | grep -E '^openclaw' | xargs -r docker network rm || true
# Xóa image cũ để lần sau pull lại mới
docker image rm ghcr.io/openclaw/openclaw:latest 2>/dev/null || true
Xóa dữ liệu cũ
Với kiểu NAS:
sudo rm -rf /opt/stacks/openclaw
sudo rm -rf /opt/appdata/openclaw
sudo rm -rf /mnt/dsm/docker/OpenClaw
Với kiểu một máy:
sudo rm -rf /opt/stacks/openclaw
sudo rm -rf /opt/appdata/openclaw
Kiểm tra lại:
docker ps -a | grep -i openclaw || echo "OK: no openclaw containers"
docker network ls | grep -i openclaw || echo "OK: no openclaw networks"