
OmniRoute Fly.io 部署实战指南基于 flyctl、fly.toml 与持久卷的完整发布流程【免费下载链接】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, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute本篇技术指南以 OmniRoute 项目统一 AI 网关单端点路由数百家 LLM 提供商在 Fly.io 平台上的真实部署经验为蓝本完整覆盖从flyctl安装、首次部署、Secrets 密钥注入、Fly Volume 持久化到 fork 同步上游更新并保留自定义fly.toml的日常发版流程。读完本文你将能够独立把 OmniRoute或参考其结构的新项目稳定部署到https://your-app.fly.dev并正确诊断数据不持久、Secrets 缺失、WS Bridge 握手失败等典型问题。核心依据来自仓库中的 fly.toml、Dockerfile 以及本文档的英文权威版本 docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md。1. 部署目标与整体思路OmniRoute 在 Fly.io 上的部署采用本地flyctl直接发布的方式不引入额外 CI 流水线平台Fly.io基于 Firecracker 微虚拟机的应用托管平台发布方式本地flyctl执行flyctl deploy运行形态直接复用仓库内现成的 Dockerfile 与 fly.toml数据持久化Fly Volume 挂载到容器内/data目录访问地址https://omniroute.fly.dev/示例应用实际部署请替换为你自己的应用名这份部署方案同时适用于三类场景首次把当前项目部署到 Fly.io、后续代码更新后继续发布以及新项目参照同一流程部署。指南基于已在omniroute应用上验证通过的配置整理因此命令中的-a omniroute参数、端口、挂载目录等均与仓库实际配置一一对应。2. 仓库关键配置文件解读fly.toml当前仓库根目录的 fly.toml 是 Fly.io 部署的核心配置已确认包含以下关键项app omniroute primary_region sin [[mounts]] source data destination /data [processes] app node run-standalone.mjs [http_service] internal_port 20128 [env] TZ Asia/Shanghai HOST 0.0.0.0 HOSTNAME 0.0.0.0 BIND 0.0.0.0逐项说明app omniroute决定flyctl实际部署到哪个 Fly 应用后续所有-a omniroute命令都依赖这一行与 Fly 控制台中的应用一一对应。destination /data决定持久卷在容器内的挂载目录。仓库 fly.toml 中还配置了卷的自动扩容策略auto_extend_size_threshold 80使用率超过 80% 触发扩容、auto_extend_size_increment 1GB每次扩容 1GB、auto_extend_size_limit 10GB上限 10GB生产环境无需手工扩容。[processes] app node run-standalone.mjs指定 HTTP 服务的启动命令。仓库中的 scripts/dev/run-standalone.mjs 会先调用bootstrapEnv()完成密钥与数据库目录的初始化再以server-ws.mjs优先或server.js启动 Next.js standalone 服务端。internal_port 20128容器内部监听端口。这与 Dockerfile 中的ENV PORT20128、EXPOSE 20128保持一致Fly 边缘网络会把 443/80 流量转发到这个端口。[env]TZAsia/Shanghai固定时区HOST、HOSTNAME、BIND均绑定0.0.0.0让服务监听所有网卡接口以配合 Fly 运行时网络。fly.toml中还有几处值得注意的补充配置[http_service]开启force_https true强制 HTTPS、auto_stop_machines stop与auto_start_machines true无流量自动休眠、有请求自动唤醒、min_machines_running 1至少保持 1 台机器常驻[[vm]]声明memory 1gb、cpu_kind shared、cpus 1的最小资源档位满足日常流量的同时控制成本。关键约束本项目必须把DATA_DIR设置为/data。虽然 Dockerfile 中 runner 阶段的默认值是ENV DATA_DIR/app/data但 Fly 的持久卷挂载点是/data。如果保持默认值数据库与密钥会写入容器临时目录/app/data/...机器销毁或重建后数据全部丢失。因此必须通过 Secrets 注入DATA_DIR/data覆盖默认值与挂载点保持一致。3. 部署前置准备安装与登录 flyctl3.1 安装 Fly CLIWindows PowerShell 下执行官方安装脚本pwsh -Command iwr https://fly.io/install.ps1 -useb | iex如果安装脚本在当前环境失败网络受限或执行策略限制可以手动下载flyctl二进制并解压到PATH覆盖的目录中。3.2 登录 Fly 账号flyctl auth login该命令会在浏览器中完成 OAuth 授权登录后凭证缓存在本地。3.3 检查登录状态flyctl auth whoami flyctl versionwhoami输出当前登录账号邮箱version确认客户端版本。后续所有命令都以已登录为前提建议在每次发布前先执行flyctl auth whoami确认会话有效。4. 首次部署当前项目4.1 获取代码并进入目录git clone 项目仓库地址 cd OmniRoute4.2 确认应用名打开fly.toml重点看这一行app omniroute如果要把项目部署到自己的新应用可改成全局唯一名称例如app omniroute-yourname注意两点Fly 控制台里看的应用必须与fly.toml中的app一致如果历史上用过别的名字例如oroute不要和omniroute混淆否则会查到错误的 Secrets 与机器列表。4.3 创建应用如果该应用尚不存在先创建flyctl apps create omniroute如果已改应用名把omniroute替换成你自己的名字。4.4 首次部署flyctl deployflyctl deploy会在本地读取 Dockerfile 构建镜像并推送到 Fly随后自动创建/更新机器。首次构建耗时较长需要安装依赖、编译原生模块、执行npm run build属正常现象。5. 必配参数本项目在 Fly.io 上至少需要配置以下参数否则部分功能无法正常工作。5.1 已验证使用的参数以下参数已经在当前omniroute应用上实际部署验证API_KEY_SECRETAPI Key 生成与校验使用DATA_DIR数据目录必须为/dataJWT_SECRET登录态与 JWT 签名使用MACHINE_ID_SALT生成稳定机器标识NEXT_PUBLIC_BASE_URL前端回调与调度器使用的公共地址OMNIROUTE_WS_BRIDGE_SECRET生产环境必需用于 WebSocket Bridge 鉴权STORAGE_ENCRYPTION_KEY加密存储敏感连接信息其中OMNIROUTE_WS_BRIDGE_SECRET的底层作用可以从源码确认在 src/server/authz/policies/management.ts 中WS Bridge 内部路径/api/internal/codex-responses-ws的鉴权正是通过校验请求头x-omniroute-ws-bridge-secret与process.env.OMNIROUTE_WS_BRIDGE_SECRET是否一致来实现的。因此生产环境缺失该密钥会直接导致 WebSocket Bridge 握手失败带401/拒绝访问必须显式设置。5.2 关于INITIAL_PASSWORD当前项目未设置INITIAL_PASSWORD因为本次部署按需求不使用它。如果不设置启动日志会提示默认密码是CHANGEME部署完成后应尽快在系统设置中修改登录密码如果你希望无人值守初始化后台密码也可以后续补充INITIAL_PASSWORD设置后首次启动即写入后台管理员密码跳过默认密码阶段。6. 推荐参数与取值说明6.1 Secrets 推荐配置总表建议放入 Fly Secrets 的变量与推荐级别变量名推荐级别说明API_KEY_SECRET必需API Key 生成与校验使用JWT_SECRET必需登录态和 JWT 签名使用OMNIROUTE_WS_BRIDGE_SECRET生产必需WebSocket Bridge 鉴权密钥STORAGE_ENCRYPTION_KEY强烈推荐加密存储敏感连接信息MACHINE_ID_SALT推荐生成稳定机器标识INITIAL_PASSWORD可选首次部署时直接指定后台初始密码OAuth/API 私密凭证按需各类外部平台鉴权配置6.2 当前项目推荐值变量名推荐值DATA_DIR/dataNEXT_PUBLIC_BASE_URLhttps://omniroute.fly.dev说明DATA_DIR/data非常关键必须与 Fly Volume 挂载点一致。从 scripts/dev/run-standalone.mjs 与构建脚本scripts/build/bootstrap-env.mjs的实现看DATA_DIR决定两层关键路径{DATA_DIR}/server.env首次启动生成的运行时密钥持久化文件和{DATA_DIR}/storage.sqliteSQLite 数据库文件。DATA_DIR指向容器临时目录时这两者都会随机器重建而丢失。NEXT_PUBLIC_BASE_URL用于调度器回调、前端回调等场景必须是对外可访问的 HTTPS 地址。6.3 OAuth 回调地址配置如果需要在 Fly.io 部署上启用基于 OAuth 的提供商例如 Antigravity、Gemini、Cursor、GitLab Duo必须确认以下两点把NEXT_PUBLIC_BASE_URL设置为你的公网 HTTPS 域名flyctl secrets set NEXT_PUBLIC_BASE_URLhttps://omniroute.fly.dev -a omniroute如果使用自定义域名则替换为对应域名例如https://omniroute.yourdomain.com。在提供商控制台配置回调地址所有 OAuth 提供商共用同一个回调路径/callback不存在按提供商区分的回调路由NEXT_PUBLIC_BASE_URL/callback例如无论 Gemini、Antigravity、Cursor 还是 GitLab Duo回调地址统一都是https://omniroute.fly.dev/callback。如果NEXT_PUBLIC_BASE_URL与提供商控制台登记的回调地址不一致OAuth 流程会在浏览器重定向阶段失败。7. 一键设置 Secrets下面这条 PowerShell 脚本会生成安全随机值并把当前项目需要的参数一次性写入 Fly Secrets$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_URLhttps://omniroute.fly.dev -a omniroute说明该命令不包含INITIAL_PASSWORD适用于当前项目omniroute。API_KEY_SECRET使用 32 字节随机十六进制串JWT_SECRET使用 64 字节其余密钥均用 32 字节强度满足生产需要。在 Linux/macOS 上也可以用openssl rand -hex 32生成密钥例如flyctl secrets set OMNIROUTE_WS_BRIDGE_SECRET$(openssl rand -hex 32) -a omnirouteOMNIROUTE_WS_BRIDGE_SECRET生产环境必需缺失会导致 WebSocket Bridge 握手失败。如果你还要加初始密码flyctl secrets set INITIAL_PASSWORD你的强密码 -a omniroute从 scripts/dev/run-standalone.mjs 的启动链路可以看到Secrets 注入的环境变量会由bootstrapEnv()在进程启动阶段消费首次启动时若检测到必要的随机密钥缺失会生成并把它们持久化到{DATA_DIR}/server.env日志输出形如 Secrets persisted to: ...后续启动则优先从该文件与外部环境合并加载。这解释了为什么部署后日志出现server.env写入是判断持久化是否生效的重要标志。8. 查看当前参数flyctl secrets list -a omniroute如果 Fly 控制台的Secrets页面没有显示你期待的变量先检查两点看的应用是不是omniroutefly.toml里的app是否与控制台应用一致9. 后续更新发布代码有更新后发布步骤很简单git pull flyctl deploy如果只更新参数、不改代码flyctl secrets set KEYvalue -a omnirouteFly 会自动对机器执行滚动更新无需手动重启。9.1 跟踪上游更新并保留 fork 的 fly.toml如果当前仓库是 fork需要同步上游更新同时又要强制保留自己 fork 的fly.toml包含应用名、挂载卷、区域等自定义部署配置推荐按下面的流程执行。先确认远程配置git remote -v应至少包含两个远程origin指向你自己的 forkupstream指向原仓库如果没有upstream先添加git remote add upstream 上游仓库地址同步前先抓取上游最新提交与标签git fetch upstream --tags查看当前版本与上游标签git describe --tags --always git show --no-patch --oneline v3.4.7注v3.4.7是历史示例标签当前项目实际版本更高发布时请使用最新版本标签如v3.8.0或:latest。合并上游main并强制保留 fork 的fly.tomlgit 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返回成功表示upstream/main已经包含该版本直接合并upstream/main即可。9.2 同步上游后的标准发布顺序同步原仓库完成后推荐按以下顺序发布git fetch upstream --tagsgit merge upstream/main恢复 fork 的fly.tomlgit push origin mainflyctl deployflyctl status -a omnirouteflyctl logs --no-tail -a omniroute这就是当前项目历次升级时实际使用的流程。10. 发布后检查10.1 查看应用状态flyctl status -a omniroute10.2 查看启动日志flyctl logs --no-tail -a omniroute10.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说明运行时密钥落到了持久卷对应bootstrap-env.mjs中首次启动把生成的密钥持久化到{DATA_DIR}/server.env的逻辑/data/storage.sqlite说明 SQLite 数据库写入持久卷bootstrap-env.mjs中dbPath join(dataDir, storage.sqlite)数据库文件路径由DATA_DIR直接决定如果你看到的是/app/data/...而不是/data/...说明DATA_DIR没配对仍使用了 Dockerfile 中ENV DATA_DIR/app/data的默认值需要立即修正 Secrets 并重新部署。12. 常见问题排查12.1Secrets页面是空的通常有两种原因还没执行flyctl secrets set打开的是另一个应用例如oroute不是omniroute12.2flyctl deploy报app not found先创建应用flyctl apps create omniroute12.3fly.toml解析失败重点检查注释里是否有乱码字符TOML 引号和缩进是否正确12.4 数据没有持久化检查以下两点是否同时满足fly.toml中是否存在destination /dataDATA_DIR是否设置为/data两者缺一不可只有挂载点没有环境变量应用仍会写容器临时目录只有环境变量没有挂载点数据无法持久化。12.5 不设置INITIAL_PASSWORD是否能跑可以运行但登录密码会回退到默认的CHANGEME。生产环境建议尽快在系统设置中修改后台密码。13. 新项目复用建议如果以后是新项目照着这份文档部署最少需要改这几项修改fly.toml里的app修改NEXT_PUBLIC_BASE_URL保持DATA_DIR/data重新生成API_KEY_SECRET、JWT_SECRET、MACHINE_ID_SALT、STORAGE_ENCRYPTION_KEY以及生产环境必需的OMNIROUTE_WS_BRIDGE_SECRET首次部署后检查日志是否写入/data不要直接复用旧项目的密钥。STORAGE_ENCRYPTION_KEY与JWT_SECRET一旦泄露或跨项目复用等于把旧环境的加密数据和登录态暴露给新环境且STORAGE_ENCRYPTION_KEY更换会导致已加密存储的连接信息无法解密。14. 当前项目的最小发布清单当前项目后续最常用的命令flyctl auth whoami flyctl status -a omniroute flyctl secrets list -a omniroute flyctl deploy flyctl logs --no-tail -a omniroute如果只是正常发版核心命令就是flyctl deploy如果是新环境首次部署核心步骤是flyctl auth loginflyctl apps create omnirouteflyctl secrets set ... -a omnirouteflyctl deployflyctl logs --no-tail -a omniroute延伸阅读英文权威版本文档docs/ops/FLY_IO_DEPLOYMENT_GUIDE.mdFly 部署核心配置fly.toml、Dockerfile启动链路与密钥持久化scripts/dev/run-standalone.mjs内部调用scripts/build/bootstrap-env.mjsWS Bridge 鉴权实现src/server/authz/policies/management.ts【免费下载链接】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, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考