Fly.io 部署
目标: 在 Fly.io 机器上运行 OpenClaw Gateway,配置持久化存储、自动 HTTPS 和 Discord/频道访问。
准备工作
- 安装 flyctl CLI
- Fly.io 账户(免费套餐可用)
- 模型认证:Anthropic API 密钥(或其他提供商密钥)
- 频道凭证:Discord 机器人令牌、Telegram 令牌等
新手快速路径
- 克隆仓库 → 自定义
fly.toml - 创建应用 + 卷 → 设置密钥
- 使用
fly deploy部署 - SSH 登录创建配置或使用控制 UI
1) 创建 Fly 应用
fly launch --no-deploy
fly volumes create openclaw_data --size 1 --region lhr提示: 选择离你最近的区域。常见选项:lhr(伦敦)、iad(弗吉尼亚)、sjc(圣何塞)。
2) 配置 fly.toml
编辑 fly.toml 以匹配你的应用名称和需求。
安全注意: 默认配置会暴露公共 URL。如需无公网 IP 的强化部署,请参见私有部署或使用 fly.toml.private。
app = 'your-app-name'
primary_region = 'lhr'
[build]
dockerfile = 'Dockerfile'
[env]
HOST = '0.0.0.0'
PORT = '8080'
SKIP_CONFIG = 'true'
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = false
auto_start_machines = true
[[http_service.checks]]
grace_period = "30s"
interval = "15s"
method = "GET"
timeout = "5s"
path = "/health"
[[vm]]
memory = '2gb'
cpu_kind = 'shared'
cpus = 1
[[mounts]]
source = 'openclaw_data'
destination = '/data'关键设置:
| 设置 | 原因 |
|---|---|
HOST = '0.0.0.0' | 绑定到 0.0.0.0 以便 Fly 代理可以访问网关 |
SKIP_CONFIG = 'true' | 启动时不需要配置文件(稍后创建) |
internal_port = 8080 | 必须与 PORT 匹配(或 8080)以便 Fly 健康检查 |
memory = '2gb' | 512MB 太小;建议 2GB |
destination = '/data' | 在卷上持久化状态 |
3) 设置密钥
fly secrets set ANTHROPIC_API_KEY=sk-ant-xxx
fly secrets set GATEWAY_TOKEN=your-secret-token
fly secrets set DISCORD_TOKEN=your-bot-token注意:
- 非回环绑定(
0.0.0.0)需要GATEWAY_TOKEN以确保安全。 - 将这些令牌视为密码。
- 优先使用环境变量而非配置文件存储所有 API 密钥和令牌。这样可以避免密钥出现在
config.yml中,防止意外暴露或记录到日志。
4) 部署
fly deploy首次部署会构建 Docker 镜像(约 2-3 分钟)。后续部署会更快。
部署后验证:
fly status你应该看到:
Status
Name = your-app-name
State = running
...5) 创建配置文件
SSH 进入机器创建正确的配置:
fly ssh console创建配置目录和文件:
mkdir -p /data/openclaw
cat > /data/openclaw/config.yml << 'EOF'
channels:
discord:
enabled: true
models:
- id: claude
provider: anthropic
EOF注意: 使用 SKIP_CONFIG 时,配置路径为 /data/openclaw/config.yml。
注意: Discord 令牌可以来自:
- 环境变量:
DISCORD_TOKEN(推荐用于密钥) - 配置文件:
channels.discord.token
如果使用环境变量,无需将令牌添加到配置。网关会自动读取 DISCORD_TOKEN。
重启以应用:
exit
fly apps restart6) 访问网关
控制 UI
在浏览器中打开:
https://your-app-name.fly.dev/control或访问 https://your-app-name.fly.dev
粘贴你的网关令牌(来自 GATEWAY_TOKEN)进行身份验证。
日志
fly logsSSH 控制台
fly ssh console故障排除
"App is not listening on expected address"
网关绑定到 127.0.0.1 而不是 0.0.0.0。
修复: 在 fly.toml 的进程命令中添加 HOST=0.0.0.0。
健康检查失败 / 连接被拒绝
Fly 无法在配置的端口上访问网关。
修复: 确保 internal_port 与网关端口匹配(设置 PORT=8080 或 internal_port=8080)。
OOM / 内存问题
容器持续重启或被杀死。迹象:OOMKilled、exit 137 或静默重启。
修复: 在 fly.toml 中增加内存:
[[vm]]
memory = '2gb'或更新现有机器:
fly scale memory 2048注意: 512MB 太小。1GB 可能可以工作但在负载下或详细日志记录时可能 OOM。推荐 2GB。
网关锁定问题
网关拒绝启动并显示"已在运行"错误。
这发生在容器重启但 PID 锁文件在卷上持久化时。
修复: 删除锁文件:
fly ssh console -C "rm /data/openclaw.lock"锁文件位于 /data/openclaw.lock(不在子目录中)。
配置未被读取
如果使用 SKIP_CONFIG,网关会创建一个最小配置。你在 /data/openclaw/config.yml 的自定义配置应在重启时被读取。
验证配置是否存在:
fly ssh console -C "cat /data/openclaw/config.yml"通过 SSH 写入配置
fly ssh console -C 命令不支持 shell 重定向。要写入配置文件:
fly ssh console
cat > /data/openclaw/config.yml << 'EOF'
[内容]
EOF
exit注意: 如果文件已存在,cat > 可能失败。先删除:
fly ssh console -C "rm /data/openclaw/config.yml"状态未持久化
如果重启后丢失凭证或会话,状态目录正在写入容器文件系统。
修复: 确保在 fly.toml 中设置 STATE_DIR=/data/openclaw 并重新部署。
更新
git pull
fly deploy更新机器命令
如果需要在不完全重新部署的情况下更改启动命令:
fly machine update <machine-id> --command "openclaw gateway --host 0.0.0.0"注意: 执行 fly deploy 后,机器命令可能会重置为 fly.toml 中的内容。如果你手动进行了更改,请在部署后重新应用。
私有部署(强化)
默认情况下,Fly 分配公网 IP,使你的网关可以通过 https://your-app.fly.dev 访问。这很方便,但意味着你的部署可被互联网扫描器(Shodan、Censys 等)发现。
对于无公网暴露的强化部署,请使用私有模板。
何时使用私有部署
- 你只进行出站调用/消息(无入站 webhooks)
- 你使用 ngrok 或 Tailscale 隧道处理任何 webhook 回调
- 你通过 SSH、代理或 WireGuard 而不是浏览器访问网关
- 你希望部署对互联网扫描器隐藏
设置
使用 fly.toml.private 而不是标准配置:
cp fly.toml.private fly.toml
fly launch --no-deploy
fly volumes create openclaw_data --size 1
fly deploy或转换现有部署:
fly ips release <public-ip>
fly ips allocate-v6 --private之后,fly ips list 应该只显示 private_network 类型的 IP:
VERSION IP TYPE REGION CREATED AT
v6 fdaa:x:x:x::x private_network global ...访问私有部署
由于没有公共 URL,请使用以下方法之一:
选项 1: 本地代理(最简单)
fly proxy 8080:8080选项 2: WireGuard VPN
fly wireguard create
# 添加到 WireGuard 客户端,然后访问 fdaa:x:x:x::x:8080选项 3: 仅 SSH
fly ssh console
curl localhost:8080/health私有部署的 Webhooks
如果你需要 webhook 回调(Twilio、Telnyx 等)但不想公开暴露:
- ngrok 隧道 - 在容器内或作为 sidecar 运行 ngrok
- Tailscale Funnel - 通过 Tailscale 暴露特定路径
- 仅出站 - 某些提供商(Twilio)在没有 webhooks 的情况下也能很好地处理出站呼叫
使用 ngrok 的语音呼叫配置示例:
voice:
twilio:
webhook_base: https://your-tunnel.ngrok.io
http:
trusted_proxies:
- 0.0.0.0/0
allowed_hosts:
- your-tunnel.ngrok.iongrok 隧道在容器内运行并提供公共 webhook URL,而不会暴露 Fly 应用本身。将 allowed_hosts 设置为公共隧道主机名,以便接受转发的 host 头。
安全优势
| 方面 | 公共 | 私有 |
|---|---|---|
| 互联网扫描器 | 可发现 | 隐藏 |
| 直接攻击 | 可能 | 被阻止 |
| 控制 UI 访问 | 浏览器 | 代理/VPN |
| Webhook 传递 | 直接 | 通过隧道 |
注意事项
- Fly.io 使用 x86 架构(非 ARM)
- Dockerfile 兼容两种架构
- 对于 WhatsApp/Telegram 上线,使用
fly ssh console - 持久化数据存储在卷上的
/data - Signal 需要 Java + signal-cli;使用自定义镜像并保持内存为 2GB+。
费用
使用推荐配置(shared-cpu-1x,2GB RAM):
- 每月约 $10-15,取决于使用量
- 免费套餐包含一些额度
详情请参见 Fly.io 定价。