OmniRoute 部署指南:基于 fly.toml 与 flyctl 在 Fly.io 上的完整实战流程
2026/9/11 4:14:37 网站建设 项目流程

OmniRoute 部署指南:基于 fly.toml 与 flyctl 在 Fly.io 上的完整实战流程

【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute

本指南以 OmniRoute 仓库内已验证通过的 fly.toml 和 docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md 为依据,完整讲解如何将 OmniRoute 网关部署到 Fly.io、配置持久化卷与运行时密钥、跟踪上游更新,以及发布后的检查与排障。读完本文,你将掌握一套可复制的部署流程:从安装flyctl、创建应用、写入 Fly Secrets 到验证日志落在持久卷/data,并能独立处理部署中的常见问题。


1. 部署目标与整体架构

本次部署的核心目标是:

  • 平台:Fly.io
  • 部署方式:使用本地flyctl直接发布,不依赖 CI 或第三方流水线
  • 运行方式:复用仓库内现成的 Dockerfile 与 fly.toml,无需额外生成配置
  • 数据持久化:Fly Volume 挂载到容器内/data,数据库与运行时密钥全部落盘
  • 访问地址:https://omniroute.fly.dev/

整条链路可以概括为:本地代码 → flyctl 构建镜像 → Fly Machines 容器运行 → Volume 持久化 → HTTP 服务对外暴露。其中决定部署目标与运行行为的关键,全部集中在fly.toml这一个文件里。


2. 当前项目关键配置解析(fly.toml)

仓库根目录的 fly.toml 是整套部署的"宪法"。它决定了部署到哪个应用、监听哪个端口、容器里跑什么进程、数据写到哪个目录。以下是经过实际验证的关键配置项:

app = 'omniroute' primary_region = 'sin' [processes] app = 'node run-standalone.mjs' [[mounts]] source = 'data' destination = '/data' auto_extend_size_threshold = 80 auto_extend_size_increment = '1GB' auto_extend_size_limit = '10GB' [http_service] internal_port = 20128 force_https = true auto_stop_machines = 'stop' auto_start_machines = true min_machines_running = 1 processes = ['app'] [[vm]] memory = '1gb' cpu_kind = 'shared' cpus = 1 [env] TZ = "Asia/Shanghai" HOST = "0.0.0.0" HOSTNAME = "0.0.0.0" BIND = "0.0.0.0"

逐项说明:

配置项含义与影响
appomniroute决定实际部署到哪个 Fly 应用,所有flyctl命令都要与它保持一致
primary_regionsin首选部署区域(新加坡),可在 Fly 控制台调整
[processes] appnode run-standalone.mjs容器启动命令,即 OmniRoute 独立运行入口
[[mounts]] destination/data持久卷挂载目录,本项目必须与DATA_DIR=/data一致,否则数据库和密钥会写进容器临时目录、机器重建即丢失
auto_extend_size_*80% / 1GB / 10GB卷容量自动扩容策略:使用率超过 80% 时每次自动增加 1GB,上限 10GB
[http_service] internal_port20128容器内部 HTTP 端口,Fly 的 edge 代理会将外部 443 流量转发到该端口
force_httpstrue强制 HTTPS,避免明文流量进入服务
min_machines_running1保证至少一台机器常驻运行
[[vm]]1GB / shared / 1 CPU默认算力规格,可按负载调整

值得注意的两点:

  • 端口一致性internal_port = 20128与本地开发端口一致,Fly edge 负责公网 443 → 容器 20128 的转发。
  • 环境变量绑定HOSTHOSTNAMEBIND统一设为0.0.0.0,确保服务监听所有网卡接口,这是 Fly 运行时网络能正常打进容器的前提(fly.toml)。

3. 必备工具与环境准备

3.1 安装 Fly CLI

Windows PowerShell 一键安装:

pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex"

如果安装脚本在当前环境失败,可以手动下载flyctl二进制并放入PATH。安装后务必新开终端,让 PATH 生效。

3.2 登录 Fly 账号

flyctl auth login

命令会打开浏览器完成 OAuth 授权,之后所有flyctl操作都基于该会话身份。

3.3 检查登录状态

flyctl auth whoami flyctl version

whoami应返回你的 Fly 账号邮箱或组织信息;version用于确认flyctl版本是否过旧(建议保持较新版本,避免 TOML 解析与 Machines API 兼容问题)。


4. 首次部署当前项目

4.1 获取代码并进入目录

git clone https://github.com/diegosouzapw/OmniRoute.git cd OmniRoute

4.2 确认应用名

打开 fly.toml,重点看这一行:

app = 'omniroute'

如果准备部署到自己的新应用,可改成全局唯一名称,例如:

app = 'omniroute-yourname'

注意两个容易混淆的点:

  • 控制台里要看的是与fly.tomlapp一致的应用,而不是凭记忆找
  • 如果之前用过其他名字(例如oroute),不要与omniroute混淆,两者是不同的 Fly 应用

4.3 创建应用

如果该应用尚不存在:

flyctl apps create omniroute

改了应用名就把omniroute替换成你的名字。

4.4 首次部署

flyctl deploy

flyctl会依据 Dockerfile 构建镜像并创建 Machines,首次构建耗时较长属正常现象。部署完成后,Volume 与[http_service]会自动按fly.toml生效。


5. 必配参数(Fly Secrets)

OmniRoute 在 Fly.io 上运行时,密钥类配置必须通过 Fly Secrets 注入(而不是写死在镜像里)。以下参数已在当前omniroute应用上实际部署验证。

5.1 已验证使用的参数

  • API_KEY_SECRET—— API Key 生成与校验使用
  • DATA_DIR—— 数据目录,必须为/data
  • JWT_SECRET—— 登录态与 JWT 签名
  • MACHINE_ID_SALT—— 生成稳定机器标识
  • NEXT_PUBLIC_BASE_URL—— 对外公开访问地址
  • OMNIROUTE_WS_BRIDGE_SECRET—— 生产环境必需,WebSocket 网桥鉴权密钥
  • STORAGE_ENCRYPTION_KEY—— 加密存储敏感连接信息

5.2 关于INITIAL_PASSWORD

当前项目默认不设置INITIAL_PASSWORD,本次部署按需求也不使用它。行为如下:

  • 不设置时,启动日志会提示默认密码为CHANGEME(界面文案见 src/i18n/messages/zh-CN.json 中的defaultPasswordHint条目)
  • 部署后应尽快在系统设置中修改登录密码,否则任何人都可能用默认口令登录后台
  • 若希望无人值守初始化后台密码,可后续补充INITIAL_PASSWORD;源码中对已存在的明文INITIAL_PASSWORD会在设置接口中做惰性哈希迁移(见 src/app/api/settings/route.ts)

6. 推荐参数说明与安全含义

6.1 Secrets 中设置的建议清单

变量名是否推荐说明
API_KEY_SECRET必需API Key 生成与校验使用;缺失时启动流程会自动生成并持久化(见 src/instrumentation-node.ts),但显式设置可保证多实例一致
JWT_SECRET必需登录态和 JWT 签名使用。源码中没有硬编码回退——未配置时登录接口直接禁用认证(src/app/api/auth/login/route.ts)
OMNIROUTE_WS_BRIDGE_SECRET生产必需WebSocket 网桥鉴权密钥,缺失会导致网桥握手失败;管理面策略会在请求头x-omniroute-ws-bridge-secret上校验(src/server/authz/policies/management.ts)
STORAGE_ENCRYPTION_KEY强烈推荐对存储中的敏感连接信息做静态加密;如果密钥在保存后被轮换或取消,解密会失败并被 stale 守卫拦截(见 src/app/api/providers/[id]/models/staleEncryptionGuard.ts)
MACHINE_ID_SALT推荐生成稳定的机器标识;源码中未设置时使用默认盐endpoint-proxy-salt(src/shared/utils/machineId.ts),生产环境建议显式覆盖
INITIAL_PASSWORD可选首次部署时直接指定后台初始密码
OAuth/API 私密凭证按需各类外部平台的鉴权配置

6.2 当前项目推荐值

变量名推荐值
DATA_DIR/data
NEXT_PUBLIC_BASE_URLhttps://omniroute.fly.dev

说明:

  • DATA_DIR=/data非常关键,必须与fly.toml[[mounts]] destination = '/data'一致。从源码看,SQLite 数据库路径正是由DATA_DIR拼接而来(path.join(DATA_DIR, "storage.sqlite"),见 src/lib/db/core.ts),默认值则是process.cwd()/data(见 src/lib/catalog/openrouterCatalog.ts)——在容器里即/app/data,这就是文档中反复警告的"错误落盘位置"
  • NEXT_PUBLIC_BASE_URL被调度器、前端回调、OAuth 跳转等场景使用,OAuth 路由会优先读取它作为回调基础地址(src/app/api/oauth/[provider]/[action]/route.ts)

6.3 OAuth 回调地址配置(可选但重要)

如果要在 Fly.io 部署上启用基于 OAuth 的 Provider(如 Antigravity、Gemini、Cursor 等),必须同时满足两点:

  1. NEXT_PUBLIC_BASE_URL设为公网 HTTPS 域名

    flyctl secrets set NEXT_PUBLIC_BASE_URL=https://omniroute.fly.dev -a omniroute

    使用自定义域名时替换为对应域名,例如https://omniroute.yourdomain.com

  2. 在 Provider 控制台配置回调地址。所有 OAuth Provider 共享同一个回调路径/callback,不存在每个 Provider 各自独立的回调路由:

    <NEXT_PUBLIC_BASE_URL>/callback

    例如无论 Gemini、Antigravity、Cursor 还是 GitLab Duo,统一填写:

    https://omniroute.fly.dev/callback

    如果NEXT_PUBLIC_BASE_URL与 Provider 侧注册的回调 URL 不一致,OAuth 流程会在浏览器重定向这一步失败。


7. 一键设置参数(随机生成安全密钥)

下面命令会生成安全随机值,并把当前项目需要的参数一次性写入 Fly Secrets。注意:不包含INITIAL_PASSWORD,适用于当前项目omniroute

$apiKeySecret = [Convert]::ToHexString((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 })).ToLower() $jwtSecret = [Convert]::ToHexString((1..64 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 })).ToLower() $machineIdSalt = [Convert]::ToHexString((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 })).ToLower() $storageKey = [Convert]::ToHexString((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 })).ToLower() $wsBridgeSecret = [Convert]::ToHexString((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 })).ToLower() flyctl secrets set ` API_KEY_SECRET=$apiKeySecret ` JWT_SECRET=$jwtSecret ` MACHINE_ID_SALT=$machineIdSalt ` STORAGE_ENCRYPTION_KEY=$storageKey ` OMNIROUTE_WS_BRIDGE_SECRET=$wsBridgeSecret ` DATA_DIR=/data ` NEXT_PUBLIC_BASE_URL=https://omniroute.fly.dev ` -a omniroute

在 Linux / macOS 上,也可以用openssl rand -hex 32

flyctl secrets set OMNIROUTE_WS_BRIDGE_SECRET=$(openssl rand -hex 32) -a omniroute

注意:OMNIROUTE_WS_BRIDGE_SECRET在生产环境是必需的,缺失会直接破坏 WebSocket 网桥握手。

如果还要加初始密码:

flyctl secrets set INITIAL_PASSWORD=你的强密码 -a omniroute

8. 查看当前参数

flyctl secrets list -a omniroute

如果控制台Secrets页面没有显示你期待的变量,先检查两处:

  • 看的应用是不是omniroute
  • fly.toml 中的app是否与控制台应用一致

9. 后续更新发布

9.1 常规发版

代码有更新后,发布步骤很简单:

git pull flyctl deploy

如果只更新参数、不改代码:

flyctl secrets set KEY=value -a omniroute

Fly 会自动对 Machines 执行滚动更新(rolling update),无需手动重启。

9.2 跟踪原仓库更新并保留 fork 的 fly.toml

如果当前仓库是 fork,并且要同步上游https://github.com/diegosouzapw/OmniRoute的更新,推荐按下面流程执行。

先确认远程:

git remote -v

应至少包含:

  • origin指向你自己的 fork
  • upstream指向原仓库

如果没有upstream,先添加:

git remote add upstream https://github.com/diegosouzapw/OmniRoute.git

同步上游前,先抓取最新提交和标签:

git fetch upstream --tags

查看当前版本和上游标签:

git describe --tags --always git show --no-patch --oneline v3.4.7

注:文档中的v3.4.7属于历史示例(当前项目实际版本请以仓库为准),实际发布时使用:latest或当前版本标签即可。

如果你要合并上游最新main,并强制保留 fork 当前的fly.toml

git merge upstream/main git checkout HEAD~1 -- fly.toml git add -- fly.toml git commit -m "chore(deploy): keep fork fly.toml" git push origin main

命令含义:

  • git merge upstream/main:同步原仓库最新代码
  • git checkout HEAD~1 -- fly.toml:恢复合并前你 fork 自己的fly.toml
  • 如果上游没有改fly.toml,这一步不会带来额外差异
  • 如果上游改了fly.toml,这一步能确保 Fly 应用名、挂载卷、区域等 fork 自定义部署配置不被覆盖

如果你明确只想对齐某个发布标签(例如v3.4.7),可先确认该标签是否已包含在upstream/main中:

git merge-base --is-ancestor v3.4.7 upstream/main

返回成功(退出码 0)表示upstream/main已经包含该版本,直接合并upstream/main即可。

9.3 同步上游后的标准发布顺序

  1. git fetch upstream --tags
  2. git merge upstream/main
  3. 恢复 fork 的fly.toml
  4. git push origin main
  5. flyctl deploy
  6. flyctl status -a omniroute
  7. flyctl logs --no-tail -a omniroute

这就是文档所记录的项目升级时实际采用的流程。


10. 发布后检查

10.1 查看应用状态

flyctl status -a omniroute

确认 Machines 状态为started、健康检查通过。

10.2 查看启动日志

flyctl logs --no-tail -a omniroute

10.3 检查网站可访问

try { (Invoke-WebRequest -Uri "https://omniroute.fly.dev" -MaximumRedirection 5 -UseBasicParsing).StatusCode } catch { if ($_.Exception.Response) { $_.Exception.Response.StatusCode.value__ } else { throw } }

返回200说明站点已正常响应。


11. 成功标志

部署成功后,日志里应看到类似内容:

[bootstrap] Secrets persisted to: /data/server.env [DB] SQLite database ready: /data/storage.sqlite

这两行是部署成败的核心判据

  • /data/server.env说明运行时密钥(含自动生成的API_KEY_SECRET)落到了持久卷
  • /data/storage.sqlite说明 SQLite 数据库写入持久卷,这条日志对应源码中的[DB] SQLite database ready: ${sqliteFile}输出(见 src/lib/db/core.ts)

如果你看到的是/app/data/...,说明DATA_DIR没配对,需要立即修正——机器一旦重建,数据就会丢失。


12. 常见问题(FAQ)

12.1 Secrets 页面是空的

通常有两种原因:

  • 还没执行flyctl secrets set
  • 打开的是另一个应用(例如oroute),不是omniroute

12.2 flyctl deploy 报 app not found

先创建应用:

flyctl apps create omniroute

12.3 fly.toml 解析失败

重点检查:

  • 注释里是否有乱码字符(尤其从 Windows 编辑器粘贴时)
  • TOML 引号和缩进是否正确

12.4 数据没有持久化

检查两点是否同时成立:

  • fly.toml 中存在destination = '/data'
  • DATA_DIR设置为/data

12.5 不设置 INITIAL_PASSWORD 是否能跑

可以运行,但会回退到默认密码CHANGEME。生产环境建议尽快修改后台密码,并配合JWT_SECRET等密钥一起做好保密管理。


13. 新项目复用建议

如果以后照这份文档把新项目部署上去,最少改这几项:

  1. 修改 fly.toml 里的app
  2. 修改NEXT_PUBLIC_BASE_URL
  3. 保持DATA_DIR=/data
  4. 重新生成API_KEY_SECRETJWT_SECRETMACHINE_ID_SALTSTORAGE_ENCRYPTION_KEY(以及生产环境的OMNIROUTE_WS_BRIDGE_SECRET
  5. 首次部署后检查日志是否写入/data

不要直接复用旧项目的密钥——密钥泄漏意味着 API 网关的鉴权体系形同虚设。


14. 最小发布清单(速查)

当前项目后续最常用的命令:

flyctl auth whoami flyctl status -a omniroute flyctl secrets list -a omniroute flyctl deploy flyctl logs --no-tail -a omniroute

正常发版,核心就是一条:

flyctl deploy

新环境首次部署,核心步骤是:

  1. flyctl auth login
  2. flyctl apps create omniroute
  3. flyctl secrets set ... -a omniroute
  4. flyctl deploy
  5. flyctl logs --no-tail -a omniroute

部署完成后,用第 11 节的两条日志(/data/server.env/data/storage.sqlite)验证持久化是否生效,再用第 10 节的 HTTP 探测确认公网入口可达,整个 Fly.io 部署链路即宣告闭环。

【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询