OmniRoute Fly.io 部署实战指南:首次发布、密钥配置与数据持久化运维
OmniRoute 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, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute导读本文基于 OmniRoute 仓库中已实际验证通过的 Fly.io 部署指南及其 孟加拉语译本完整讲解如何将 OmniRoute 这个统一 AI 网关部署到 Fly.io从flyctl环境准备、首次发布到 Secrets 密钥体系、OAuth 回调配置、fork 同步发布与持久化验证。读完本文你将掌握一套可直接复用的 Fly.io 云部署与滚动升级方案并理解每个关键配置背后的源码实现原理。1. 部署目标平台Fly.io云主机托管自带边缘网络与卷存储部署方式本地flyctl直接发布无需额外 CI/CD 编排运行方式直接使用仓库内已有的 Dockerfile 与 fly.toml数据持久化Fly Volume 挂载到容器内/data目录访问地址https://omniroute.fly.dev/应用名omniroute本文所有命令均以该应用名为准覆盖三类场景首次把当前项目部署到 Fly.io、后续代码更新继续发布、新项目参考同一流程部署。2. 仓库现有配置解读fly.toml 关键项仓库根目录的fly.toml是本次部署的配置核心已确认包含以下关键项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决定部署目标 Fly 应用控制台看到的应用必须与之一致destination /data决定持久卷挂载目录本项目必须让DATA_DIR/data否则数据库和密钥会写到容器临时目录重启即丢失[processes]中的node run-standalone.mjs是容器入口进程。对比仓库中真实 fly.toml还有几个文档之外的细节值得注意均来自已验证配置卷自动扩容[[mounts]]段额外声明了auto_extend_size_threshold 80、auto_extend_size_increment 1GB、auto_extend_size_limit 10GB即卷使用率达 80% 时自动按 1GB 步长扩容、上限 10GBHTTP 服务强化force_https true强制 HTTPSauto_stop_machines stop与auto_start_machines true支持空闲停机、按需唤醒min_machines_running 1保证至少一台常驻资源规格[[vm]]段为 1 核 shared CPU、1024MB 内存部署钩子[deploy]中的release_command被注释掉本部署不需要迁移命令。在 Dockerfile 中可以看到与上述配置的对应关系基础镜像为node:26-trixie-slimENV PORT20128与internal_port一致ENTRYPOINT先执行 check-permissions.sh校验数据卷属主随后CMD [node, dev/run-standalone.mjs]启动服务镜像内置HEALTHCHECK每 30s 探测healthcheck.mjs。注意 Dockerfile 中默认ENV DATA_DIR/app/data这正是 Fly 部署时必须用环境变量覆盖为/data的原因。3. 环境准备安装 Fly CLI 并登录3.1 安装 Fly CLIWindows PowerShell 一键安装pwsh -Command iwr https://fly.io/install.ps1 -useb | iex如果安装脚本在当前环境失败也可以手动下载flyctl二进制并加入PATH。3.2 登录 Fly 账号flyctl auth login3.3 检查登录状态flyctl auth whoami flyctl versionwhoami输出当前登录账号确认与目标组织一致后再继续。4. 首次部署流程4.1 获取代码并进入目录git clone https://gitcode.com/GitHub_Trending/om/OmniRoute.git cd OmniRoute4.2 确认应用名打开 fly.toml重点看这一行app omniroute如果你要部署到自己的新应用可改成全局唯一名称例如app omniroute-yourname注意两点控制台里查看的应用必须与fly.toml里app一致如果以前用过别的名字例如oroute不要和omniroute混淆——它们对应不同的 Fly 应用Secrets 互不通用。4.3 创建应用如果该应用尚不存在flyctl apps create omniroute改名后请把omniroute替换成你的应用名。4.4 首次部署flyctl deployflyctl会依据fly.toml构建镜像并创建首批 Machine若尚未配置 Secrets可以先看下一节再部署避免首次启动回退到弱默认值。5. 必配参数Fly Secrets 密钥体系5.1 已验证使用的参数以下参数已经在当前omniroute应用上实际部署验证API_KEY_SECRETDATA_DIRJWT_SECRETMACHINE_ID_SALTNEXT_PUBLIC_BASE_URLOMNIROUTE_WS_BRIDGE_SECRET生产环境必需用于 WebSocket bridge 鉴权STORAGE_ENCRYPTION_KEY5.2 关于INITIAL_PASSWORD当前项目没有设置INITIAL_PASSWORD因为本次部署按需求不使用它。如果不设置启动日志会提示默认密码为CHANGEME源码见 bootstrap-env.mjs 中的告警逻辑部署后应尽快在系统设置中修改登录密码。如果希望无人值守初始化后台密码可后续补充INITIAL_PASSWORD。5.3 源码视角这些密钥为什么必需理解这些密钥的底层作用才能判断取舍。核心逻辑集中在 bootstrap-env.mjs它由 run-standalone.mjs 在进程启动时调用密钥自动生成与持久化首次启动时若JWT_SECRET、STORAGE_ENCRYPTION_KEY、API_KEY_SECRET缺失bootstrap 会用randomBytes自动生成并写入{DATA_DIR}/server.env因此只要DATA_DIR落在持久卷上密钥就能跨重启、跨升级存活这就是文档中/data/server.env成功标志的由来。环境变量优先级自动生成值 {DATA_DIR}/server.env 首选.env文件 process.envFly Secrets 注入的环境变量优先级最高且空字符串值会被过滤不会覆盖已持久化的真实密钥。STORAGE_ENCRYPTION_KEY的约束如果数据库中已存在enc:v1:前缀的加密凭据bootstrap 会拒绝自动生成新密钥并报错防止换钥匙导致数据不可解密启动时还会用 scrypt 派生密钥做解密探测密钥不匹配会给出告警。MACHINE_ID_SALT在 machineId.ts 中getConsistentMachineId以操作系统机器标识Windows MachineGuid / macOS IOPlatformUUID / Linux machine-id 文件等加盐后做 SHA-256取前 16 字符作为稳定机器 IDMACHINE_ID_SALT就是这里的盐不设置时回退到内置默认值endpoint-proxy-salt。OMNIROUTE_WS_BRIDGE_SECRET在 management.ts 中进程内 codex Responses-over-WebSocket 代理的内部调用通过请求头x-omniroute-ws-bridge-secret携带该密钥服务端以 SHA-256 摘要 timingSafeEqual做常数时间比较缺失该密钥会直接破坏 WebSocket bridge 握手因此生产环境必配。NEXT_PUBLIC_BASE_URL在 runtimeEnv.ts 中经 Zod 校验为合法 HTTP(S) URL用于调度器、前端回调等场景的绝对地址生成。6. 推荐参数说明6.1 Secrets 设置建议变量名是否推荐说明API_KEY_SECRET必需API Key 生成与校验使用JWT_SECRET必需登录态和 JWT 签名使用OMNIROUTE_WS_BRIDGE_SECRET生产必需WebSocket bridge 鉴权密钥STORAGE_ENCRYPTION_KEY强烈推荐加密存储敏感连接信息AES-256-GCMMACHINE_ID_SALT推荐生成稳定机器标识INITIAL_PASSWORD可选首次部署时直接指定后台初始密码OAuth/API 私密凭证按需各类外部平台鉴权配置6.2 当前项目推荐值变量名推荐值DATA_DIR/dataNEXT_PUBLIC_BASE_URLhttps://omniroute.fly.dev说明DATA_DIR/data非常关键必须与 fly.toml 中 Fly Volume 挂载点一致否则数据库与密钥落入容器临时目录默认/app/dataNEXT_PUBLIC_BASE_URL用于调度器和前端回调等场景改动应用名时必须同步更新。6.3 OAuth 回调地址配置启用 OAuth Provider 时如果要在 Fly 部署上启用基于 OAuth 的 Provider如 Antigravity、Gemini、Cursor 等需确认两点将NEXT_PUBLIC_BASE_URL设置为你的公网 HTTPS 域名flyctl secrets set NEXT_PUBLIC_BASE_URLhttps://omniroute.fly.dev -a omniroute使用自定义域名时替换为对应域名例如https://omniroute.yourdomain.com。在 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 侧登记的回调地址不一致OAuth 流程会在浏览器重定向环节失败。仓库中 OIDC 登录的回调实现可见 oidc/callback/route.ts它校验code与state常数时间比较防时序攻击、从设置中读取 issuer/client 信息、基于x-forwarded-proto与Host动态拼出绝对redirect_uri并完成授权码换令牌因此回调域名必须与NEXT_PUBLIC_BASE_URL严格对应。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_URLhttps://omniroute.fly.dev -a omniroute在 Linux / macOS 上也可以用openssl rand -hex生成适合 Shell 环境flyctl secrets set OMNIROUTE_WS_BRIDGE_SECRET$(openssl rand -hex 32) -a omniroute注意OMNIROUTE_WS_BRIDGE_SECRET生产环境必配缺失会破坏 WebSocket bridge 握手见 5.3 节源码分析。如果你还要加初始密码flyctl secrets set INITIAL_PASSWORD你的强密码 -a omniroute每次flyctl secrets set后 Fly 会自动滚动重启受影响 Machine。8. 查看当前参数flyctl secrets list -a omniroute如果控制台Secrets页面没有显示你期待的变量先检查看的应用是不是omniroutefly.toml的app是否和控制台应用一致。9. 后续更新发布代码有更新后发布步骤很简单git pull flyctl deploy如果只更新参数、不改代码flyctl secrets set KEYvalue -a omnirouteFly 会自动滚动更新机器期间服务基本不中断。9.1 跟踪原仓库更新并保留 fork 的 fly.toml如果当前仓库是 fork且要同步上游更新推荐按以下流程执行。先确认远程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.8.0或: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 自定义部署配置不被覆盖。如果你明确只想对齐某个发布标签也可以先确认标签是否已包含在upstream/maingit merge-base --is-ancestor 目标版本标签 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/storage.sqlite说明 SQLite 数据库写入持久卷。如果你看到的是/app/data/...说明DATA_DIR没配对回退到了 Dockerfile 中的默认值需要立即修正为/data并重新部署。12. 常见问题12.1 Secrets 页面是空的通常有两种原因你还没执行flyctl secrets set你打开的是另一个应用例如oroute不是omniroute。12.2 flyctl deploy 报 app not found先创建应用flyctl apps create omniroute12.3 fly.toml 解析失败重点检查注释里是否有乱码字符TOML 引号和缩进是否正确。12.4 数据没有持久化检查以下两点是否同时满足fly.toml中存在destination /dataDATA_DIR设置为/data。另外可核对日志中数据库路径是否为/data/storage.sqlite见第 11 节。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与旧数据库绑定换环境换库必须换钥匙其他密钥复用也会放大泄露面。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 omniroute第 7 节一键命令flyctl deployflyctl logs --no-tail -a omniroute延伸阅读部署指南英文原版docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md部署入口与密钥引导run-standalone.mjs / bootstrap-env.mjs容器镜像与启动命令Dockerfile / docker-compose.yml机器标识与 WS bridge 鉴权machineId.ts / management.ts运行时环境校验runtimeEnv.ts本地/自建部署对比参考DOCKER_GUIDE.md、SETUP_GUIDE.md【免费下载链接】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),仅供参考