Hosting
Fly.io
Mục tiêu: OpenClaw Gateway chạy trên một máy Fly.io với lưu trữ bền vững, HTTPS tự động và quyền truy cập Discord/kênh.
Bạn cần có
- Đã cài đặt flyctl CLI
- Tài khoản Fly.io (gói miễn phí dùng được)
- Xác thực mô hình: khóa API cho nhà cung cấp mô hình bạn chọn
- Thông tin xác thực kênh: token bot Discord, token Telegram, v.v.
Lộ trình nhanh cho người mới
- Sao chép repo → tùy chỉnh
fly.toml - Tạo ứng dụng + volume → thiết lập secret
- Triển khai bằng
fly deploy - SSH vào để tạo cấu hình hoặc dùng Control UI
Create the Fly app
# Clone the repogit clone https://github.com/openclaw/openclaw.gitcd openclaw # Create a new Fly app (pick your own name)fly apps create my-openclaw # Create a persistent volume (1GB is usually enough)fly volumes create openclaw_data --size 1 --region iadMẹo: Chọn khu vực gần bạn. Các tùy chọn phổ biến: lhr (London), iad (Virginia), sjc (San Jose).
Configure fly.toml
Chỉnh sửa fly.toml để khớp với tên ứng dụng và yêu cầu của bạn.
Ghi chú bảo mật: Cấu hình mặc định để lộ một URL công khai. Để triển khai cứng hóa không có IP công khai, xem Triển khai riêng tư hoặc dùng deploy/fly.private.toml.
app = "my-openclaw" # Your app nameprimary_region = "iad" [build] dockerfile = "Dockerfile" [env] NODE_ENV = "production" OPENCLAW_PREFER_PNPM = "1" OPENCLAW_STATE_DIR = "/data" NODE_OPTIONS = "--max-old-space-size=1536" [processes] app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan" [http_service] internal_port = 3000 force_https = true auto_stop_machines = false auto_start_machines = true min_machines_running = 1 processes = ["app"] [[vm]] size = "shared-cpu-2x" memory = "2048mb" [mounts] source = "openclaw_data" destination = "/data"Docker image của OpenClaw dùng tini làm entrypoint. Lệnh tiến trình của Fly thay thế Docker CMD nhưng không thay thế ENTRYPOINT, nên tiến trình vẫn chạy dưới tini.
Thiết lập chính:
| Thiết lập | Lý do |
|---|---|
--bind lan |
Bind tới 0.0.0.0 để proxy của Fly có thể truy cập Gateway |
--allow-unconfigured |
Khởi động khi chưa có tệp cấu hình (bạn sẽ tạo tệp này sau) |
internal_port = 3000 |
Phải khớp với --port 3000 (hoặc OPENCLAW_GATEWAY_PORT) cho health check của Fly |
memory = "2048mb" |
512MB quá nhỏ; khuyến nghị 2GB |
OPENCLAW_STATE_DIR = "/data" |
Duy trì trạng thái trên volume |
Set secrets
# Required: Gateway token (for non-loopback binding)fly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32) # Model provider API keysfly secrets set ANTHROPIC_API_KEY=sk-ant-... # Optional: Other providersfly secrets set OPENAI_API_KEY=sk-...fly secrets set GOOGLE_API_KEY=... # Channel tokensfly secrets set DISCORD_BOT_TOKEN=MTQ...Ghi chú:
- Các bind không phải loopback (
--bind lan) yêu cầu một đường dẫn xác thực Gateway hợp lệ. Ví dụ Fly.io này dùngOPENCLAW_GATEWAY_TOKEN, nhưnggateway.auth.passwordhoặc một triển khaitrusted-proxykhông phải loopback được cấu hình đúng cũng đáp ứng yêu cầu. - Hãy xử lý các token này như mật khẩu.
- Ưu tiên biến môi trường thay vì tệp cấu hình cho mọi khóa API và token. Cách này giữ secret không nằm trong
openclaw.json, nơi chúng có thể vô tình bị lộ hoặc ghi vào log.
Deploy
fly deployLần triển khai đầu tiên sẽ build Docker image (~2-3 phút). Các lần triển khai sau sẽ nhanh hơn.
Sau khi triển khai, xác minh:
fly statusfly logsBạn sẽ thấy:
[gateway] listening on ws://0.0.0.0:3000 (PID xxx)[discord] logged in to discord as xxxCreate config file
SSH vào máy để tạo cấu hình phù hợp:
fly ssh consoleTạo thư mục và tệp cấu hình:
mkdir -p /datacat > /data/openclaw.json << 'EOF'{ "agents": { "defaults": { "model": { "primary": "anthropic/claude-opus-4-6", "fallbacks": ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4"] }, "maxConcurrent": 4 }, "list": [ { "id": "main", "default": true } ] }, "auth": { "profiles": { "anthropic:default": { "mode": "token", "provider": "anthropic" }, "openai:default": { "mode": "token", "provider": "openai" } } }, "bindings": [ { "agentId": "main", "match": { "channel": "discord" } } ], "channels": { "discord": { "enabled": true, "groupPolicy": "allowlist", "guilds": { "YOUR_GUILD_ID": { "channels": { "general": { "allow": true } }, "requireMention": false } } } }, "gateway": { "mode": "local", "bind": "auto", "controlUi": { "allowedOrigins": [ "https://my-openclaw.fly.dev", "http://localhost:3000", "http://127.0.0.1:3000" ] } }, "meta": {}}EOFGhi chú: Với OPENCLAW_STATE_DIR=/data, đường dẫn cấu hình là /data/openclaw.json.
Ghi chú: Thay https://my-openclaw.fly.dev bằng origin ứng dụng Fly thật của bạn. Khi Gateway khởi động, nó seed các origin Control UI cục bộ từ giá trị runtime --bind và --port để lần boot đầu tiên có thể tiếp tục trước khi cấu hình tồn tại, nhưng truy cập trình duyệt qua Fly vẫn cần origin HTTPS chính xác được liệt kê trong gateway.controlUi.allowedOrigins.
Ghi chú: Token Discord có thể đến từ một trong hai nguồn:
- Biến môi trường:
DISCORD_BOT_TOKEN(khuyến nghị cho secret) - Tệp cấu hình:
channels.discord.token
Nếu dùng biến môi trường, không cần thêm token vào cấu hình. Gateway tự động đọc DISCORD_BOT_TOKEN.
Khởi động lại để áp dụng:
exitfly machine restart <machine-id>Access the Gateway
Control UI
Mở trong trình duyệt:
fly openHoặc truy cập https://my-openclaw.fly.dev/
Xác thực bằng shared secret đã cấu hình. Hướng dẫn này dùng token Gateway từ OPENCLAW_GATEWAY_TOKEN; nếu bạn đã chuyển sang xác thực bằng mật khẩu, hãy dùng mật khẩu đó.
Log
fly logs # Live logsfly logs --no-tail # Recent logsBảng điều khiển SSH
fly ssh consoleKhắc phục sự cố
"App is not listening on expected address"
Gateway đang bind tới 127.0.0.1 thay vì 0.0.0.0.
Cách sửa: Thêm --bind lan vào lệnh tiến trình trong fly.toml.
Health check thất bại / kết nối bị từ chối
Fly không thể truy cập Gateway trên cổng đã cấu hình.
Cách sửa: Đảm bảo internal_port khớp với cổng Gateway (đặt --port 3000 hoặc OPENCLAW_GATEWAY_PORT=3000).
OOM / vấn đề bộ nhớ
Container liên tục khởi động lại hoặc bị kill. Dấu hiệu: SIGABRT, v8::internal::Runtime_AllocateInYoungGeneration, hoặc khởi động lại im lặng.
Cách sửa: Tăng bộ nhớ trong fly.toml:
[[vm]] memory = "2048mb"Hoặc cập nhật một máy hiện có:
fly machine update <machine-id> --vm-memory 2048 -yGhi chú: 512MB quá nhỏ. 1GB có thể hoạt động nhưng có thể OOM khi tải cao hoặc khi bật logging chi tiết. Khuyến nghị 2GB.
Vấn đề khóa Gateway
Gateway từ chối khởi động với lỗi "already running".
Điều này xảy ra khi container khởi động lại nhưng tệp khóa PID vẫn còn trên volume.
Cách sửa: Xóa tệp khóa:
fly ssh console --command "rm -f /data/gateway.*.lock"fly machine restart <machine-id>Tệp khóa nằm tại /data/gateway.*.lock (không nằm trong thư mục con).
Cấu hình không được đọc
--allow-unconfigured chỉ bỏ qua guard khi khởi động. Nó không tạo hoặc sửa /data/openclaw.json, vì vậy hãy đảm bảo cấu hình thật của bạn tồn tại và có gateway.mode="local" khi bạn muốn khởi động Gateway cục bộ bình thường.
Xác minh cấu hình tồn tại:
fly ssh console --command "cat /data/openclaw.json"Ghi cấu hình qua SSH
Lệnh fly ssh console -C không hỗ trợ chuyển hướng shell. Để ghi tệp cấu hình:
# Use echo + tee (pipe from local to remote)echo '{"your":"config"}' | fly ssh console -C "tee /data/openclaw.json" # Or use sftpfly sftp shell> put /local/path/config.json /data/openclaw.jsonGhi chú: fly sftp có thể thất bại nếu tệp đã tồn tại. Hãy xóa trước:
fly ssh console --command "rm /data/openclaw.json"Trạng thái không được duy trì
Nếu bạn mất hồ sơ xác thực, trạng thái kênh/nhà cung cấp, hoặc phiên sau khi khởi động lại, thư mục trạng thái đang ghi vào hệ thống tệp của container.
Cách sửa: Đảm bảo OPENCLAW_STATE_DIR=/data được đặt trong fly.toml và triển khai lại.
Cập nhật
# Pull latest changesgit pull # Redeployfly deploy # Check healthfly statusfly logsCập nhật lệnh của máy
Nếu bạn cần thay đổi lệnh khởi động mà không triển khai lại đầy đủ:
# Get machine IDfly machines list # Update commandfly machine update <machine-id> --command "node dist/index.js gateway --port 3000 --bind lan" -y # Or with memory increasefly machine update <machine-id> --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -yGhi chú: Sau fly deploy, lệnh của máy có thể được đặt lại về nội dung trong fly.toml. Nếu bạn đã thay đổi thủ công, hãy áp dụng lại sau khi triển khai.
Triển khai riêng tư (cứng hóa)
Theo mặc định, Fly cấp phát IP công khai, khiến Gateway của bạn truy cập được tại https://your-app.fly.dev. Cách này tiện lợi nhưng có nghĩa là triển khai của bạn có thể bị các trình quét internet phát hiện (Shodan, Censys, v.v.).
Để triển khai cứng hóa với không phơi bày công khai, hãy dùng mẫu riêng tư.
Khi nào nên dùng triển khai riêng tư
- Bạn chỉ thực hiện cuộc gọi/tin nhắn đi ra (không có Webhook đi vào)
- Bạn dùng đường hầm ngrok hoặc Tailscale cho mọi callback Webhook
- Bạn truy cập Gateway qua SSH, proxy hoặc WireGuard thay vì trình duyệt
- Bạn muốn triển khai được ẩn khỏi các trình quét internet
Thiết lập
Dùng deploy/fly.private.toml thay vì cấu hình tiêu chuẩn:
# Deploy with private configfly deploy -c deploy/fly.private.tomlHoặc chuyển đổi một triển khai hiện có:
# List current IPsfly ips list -a my-openclaw # Release public IPsfly ips release <public-ipv4> -a my-openclawfly ips release <public-ipv6> -a my-openclaw # Switch to private config so future deploys don't re-allocate public IPs# (remove [http_service] or deploy with the private template)fly deploy -c deploy/fly.private.toml # Allocate private-only IPv6fly ips allocate-v6 --private -a my-openclawSau đó, fly ips list chỉ nên hiển thị IP loại private:
VERSION IP TYPE REGIONv6 fdaa:x:x:x:x::x private globalTruy cập triển khai riêng tư
Vì không có URL công khai, hãy dùng một trong các phương thức sau:
Tùy chọn 1: Proxy cục bộ (đơn giản nhất)
# Forward local port 3000 to the appfly proxy 3000:3000 -a my-openclaw # Then open http://localhost:3000 in browserTùy chọn 2: VPN WireGuard
# Create WireGuard config (one-time)fly wireguard create # Import to WireGuard client, then access via internal IPv6# Example: http://[fdaa:x:x:x:x::x]:3000Tùy chọn 3: Chỉ SSH
fly ssh console -a my-openclawWebhook với triển khai riêng tư
Nếu bạn cần callback Webhook (Twilio, Telnyx, v.v.) mà không phơi bày công khai:
- Đường hầm ngrok - Chạy ngrok bên trong container hoặc dưới dạng sidecar
- Tailscale Funnel - Phơi bày các đường dẫn cụ thể qua Tailscale
- Chỉ gửi ra ngoài - Một số nhà cung cấp (Twilio) hoạt động tốt cho cuộc gọi gửi ra ngoài mà không cần Webhook
Ví dụ cấu hình cuộc gọi thoại với ngrok:
{ plugins: { entries: { "voice-call": { enabled: true, config: { provider: "twilio", tunnel: { provider: "ngrok" }, webhookSecurity: { allowedHosts: ["example.ngrok.app"], }, }, }, }, },}Đường hầm ngrok chạy bên trong container và cung cấp URL Webhook công khai mà không phơi bày chính ứng dụng Fly. Đặt webhookSecurity.allowedHosts thành hostname đường hầm công khai để các header host được chuyển tiếp được chấp nhận.
Lợi ích bảo mật
| Khía cạnh | Công khai | Riêng tư |
|---|---|---|
| Trình quét Internet | Có thể bị phát hiện | Ẩn |
| Tấn công trực tiếp | Có thể xảy ra | Bị chặn |
| Quyền truy cập UI điều khiển | Trình duyệt | Proxy/VPN |
| Phân phối Webhook | Trực tiếp | Qua đường hầm |
Ghi chú
- Fly.io sử dụng kiến trúc x86 (không phải ARM)
- Dockerfile tương thích với cả hai kiến trúc
- Để onboarding WhatsApp/Telegram, hãy dùng
fly ssh console - Dữ liệu bền vững nằm trên volume tại
/data - Signal yêu cầu Java + signal-cli; hãy dùng image tùy chỉnh và giữ bộ nhớ ở mức 2GB trở lên.
Chi phí
Với cấu hình được khuyến nghị (shared-cpu-2x, RAM 2GB):
- ~10-15 USD/tháng tùy theo mức sử dụng
- Gói miễn phí bao gồm một số hạn mức
Xem giá Fly.io để biết chi tiết.
Bước tiếp theo
- Thiết lập các kênh nhắn tin: Kênh
- Cấu hình Gateway: Cấu hình Gateway
- Luôn cập nhật OpenClaw: Cập nhật