你需要准备什么
- 已安装 flyctl CLI
- Fly.io 账户(免费套餐即可)
- 模型认证:你所选模型提供商的 API key
- 频道凭证:Discord bot token、Telegram token 等。
新手快速路径
- 克隆仓库,自定义
fly.toml - 创建应用 + 卷,设置密钥
- 使用
fly deploy部署 - 通过 SSH 登录创建配置,或使用控制界面
1
创建 Fly 应用
lhr(伦敦)、iad(弗吉尼亚)、sjc(圣何塞)。2
配置 fly.toml
编辑 OpenClaw Docker 镜像的入口点是
fly.toml 以匹配你的应用名称和需求。仓库中跟踪的 fly.toml 是下面展示的公开模板;deploy/fly.private.toml 是加固过的、无公网 IP 的变体(参见 私有部署(加固版))。tini,默认运行 node openclaw.mjs gateway。Fly 的 [processes] 会替换 Docker 的 CMD(这里它直接运行 node dist/index.js gateway ...,即相同的编译后入口),而不会影响 ENTRYPOINT,因此进程仍然运行在 tini 之下。关键设置:3
设置密钥
--bind lan)需要有效的 gateway 认证路径。此示例使用 OPENCLAW_GATEWAY_TOKEN,但 gateway.auth.password 或配置正确的非 loopback trusted-proxy 部署也同样满足要求。有关 SecretRef 合同,请参见 密钥管理。把这些令牌当作密码处理。API 密钥和令牌应优先使用环境变量/fly secrets,而不是配置文件,这样机密信息就不会出现在 openclaw.json 中。4
部署
gateway ready。Fly 会在 internal_port = 3000 上检查 /startupz,并在启动工作完成后允许流量进入。镜像的 Docker HEALTHCHECK 会解析活动的 Gateway 锁端口,因此其 /healthz 存活检查也会遵循本次部署的 --port 3000 覆盖值。5
创建配置文件
通过 SSH 登录到机器以创建正确的配置:通过
OPENCLAW_STATE_DIR=/data,配置路径为 /data/openclaw.json。将 https://my-openclaw.fly.dev 替换为你真实的 Fly 应用来源。gateway 启动时会根据运行时的 --bind 和 --port 值为本地控制界面的来源设定初始值,因此首次启动即使配置尚不存在也可以继续,但通过 Fly 进行浏览器访问仍然需要在 gateway.controlUi.allowedOrigins 中列出准确的 HTTPS 来源。Discord 令牌可以来自以下任一方式:- 环境变量
DISCORD_BOT_TOKEN(推荐用于密钥);无需将其添加到配置中,gateway 会自动读取 - 配置文件
channels.discord.token
故障排查
“应用未监听预期地址”
gateway 绑定到了127.0.0.1,而不是 0.0.0.0。
修复: 在 fly.toml 的进程命令中添加 --bind lan。
健康检查失败 / connection refused
Fly 无法通过配置的端口访问 gateway,或者/startupz 仍在报告启动工作。
修复: 确保 internal_port 与 gateway 端口(--port 3000 或 OPENCLAW_GATEWAY_PORT=3000)匹配,然后检查 fly logs 以了解待处理的启动步骤。
OOM / 内存问题
容器一直重启或被杀死。表现:SIGABRT、v8::internal::Runtime_AllocateInYoungGeneration,或者静默重启。
修复: 增加 fly.toml 中的内存:
Gateway 锁问题
在容器重启后,Gateway 因“already running”错误而拒绝启动。 当设置了OPENCLAW_STATE_DIR=/data 时,锁目录位于
/data/tmp/openclaw-<uid> 下,并会随卷持久化。OpenClaw 通常会自动回收已失效的所有者。如果启动时仍然报告存在所有者,请先使用 fly status 和 fly logs 验证是否有其他机器或 Gateway 进程正在使用该卷。当所有者可能仍在运行时,不要删除锁目录;有关所有权和失效恢复约定,请参阅网关锁。
未读取配置
--allow-unconfigured 只会绕过启动保护。它不会创建或修复 /data/openclaw.json,因此请确保你的真实配置存在,并且在正常的本地 gateway 启动中包含 "gateway": { "mode": "local" }。
验证配置是否存在:
通过 SSH 写入配置
fly ssh console -C 不支持 shell 重定向。要写入配置文件:
fly sftp 可能会失败;请先删除:
状态未持久化
如果在重启后丢失了 auth profiles、channel/provider 状态或会话,则说明 state dir 正在写入容器文件系统,而不是卷。 修复: 确保在fly.toml 中设置了 OPENCLAW_STATE_DIR=/data 并重新部署。
更新
git pull + fly deploy 是这里受监督的更新路径:它会根据 Dockerfile 重新构建镜像,因此 CLI/gateway 版本、基础 OS 镜像以及任何 Dockerfile 的更改都会一起更新。运行中容器内的 openclaw update 不是同一种操作,因为该镜像以 Docker 构建的 dist/ 目录树形式提供,没有 .git 检出,也没有 npm 管理的全局安装可供其检测;有关 VM 风格安装的该流程,请参见 更新。
更新机器命令
要在不完整重新部署的情况下更改启动命令:fly deploy 会将机器命令重置回 fly.toml 中的内容;在重新部署后需要重新应用手动更改。
私有部署(加固)
默认情况下,Fly 会分配公共 IP,因此你的网关可通过https://your-app.fly.dev 访问,并且可被互联网扫描器(Shodan、Censys 等)发现。
使用 deploy/fly.private.toml 进行加固部署,不分配 公共 IP:它省略了 [http_service],因此不会分配公共入口流量。
何时使用私有部署
- 仅发出外呼/消息(不接收入站 webhook)
- 使用 ngrok 或 Tailscale 隧道处理任何 webhook 回调
- 通过 SSH、代理或 WireGuard 访问网关,而不是通过浏览器
- 需要让部署对互联网扫描器隐藏
设置
fly ips list 应只显示一个 private 类型的 IP:
访问私有部署
选项 1:本地代理(最简单)通过私有部署使用 Webhook
对于不公开暴露的 webhook 回调(Twilio、Telnyx 等):- ngrok 隧道:在容器内运行 ngrok,或作为 sidecar 运行
- Tailscale Funnel:通过 Tailscale 暴露特定路径
- 仅外呼:某些提供商(如 Twilio)在无需 webhook 的情况下也可用于外呼
plugins.entries.voice-call.config 下:
webhookSecurity.allowedHosts 设置为隧道主机名,以便接受转发的 host 头。
安全权衡
注意
- Fly.io 使用 x86 架构;该 Dockerfile 同时兼容 x86 和 ARM。
- 对于 WhatsApp/Telegram 入门,请使用
fly ssh console。 - 持久化数据存储在
/data挂载的卷上。 - Signal 需要镜像中包含 signal-cli(基于 Java 的 CLI);请使用自定义镜像,并将内存保持在 2GB 以上。
成本
使用推荐配置(shared-cpu-2x,2GB RAM)时,预计每月约 $10-15,具体取决于使用情况;免费套餐覆盖一些基础额度。有关当前费率,请参见 Fly.io 定价。