
OmniRoute Fly.io 部署实战指南基于 flyctl 的首次发布、密钥配置与持久化运维【免费下载链接】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 平台上的完整部署指南覆盖两类核心场景首次将当前项目部署到 Fly.io以及后续代码更新后的持续发布。指南基于仓库内已经验证通过的fly.toml与Dockerfile实际配置整理应用名为omniroute。读完本文你将掌握 flyctl 环境搭建、应用创建与首次发布、Fly Secrets 密钥体系API_KEY_SECRET、JWT_SECRET、STORAGE_ENCRYPTION_KEY等、Fly Volume 数据持久化、fork 同步上游并保留自定义部署配置以及发布后状态检查与故障排查的完整实操能力。1. 部署目标本次部署的目标形态如下项目目标平台Fly.io部署方式本地flyctl直接发布运行方式使用仓库内现有Dockerfile与fly.toml数据持久化Fly Volume 挂载到/data访问地址https://omniroute.fly.dev/核心思路是不需要自建 Docker Registry 或 CI 发布链本地安装 Fly 官方 CLIflyctl后一条flyctl deploy即可完成镜像构建、机器编排与流量切换。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 应用控制台、Secrets、日志查询都必须以它为准destination /data决定持久卷挂载目录是所有持久化文件的落点internal_port 20128是容器内 HTTP 服务监听端口与 Dockerfile 中EXPOSE 20128一致[env]中的HOST/HOSTNAME/BIND全部绑定0.0.0.0确保 Fly 运行时网络gateway 转发到内部端口可以正常访问。本项目必须让DATA_DIR/data否则数据库和密钥会写到容器临时目录机器重建后数据全部丢失。2.1 源码中的额外配置项fly.toml 比文档展示更完整当前仓库实际生效的 fly.toml 还包含以下配置它们对生产部署同样重要[[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 memory_mb 1024要点挂载卷启用了自动扩容用量达到 80% 时自动增加 1GB上限 10GB避免 SQLite 增长撑爆卷HTTP 服务强制 HTTPSmin_machines_running 1保证至少保留一台机器auto_stop_machines stop允许空闲停机以节省配额VM 规格为 1 核 1GBshared CPU对中等规模的代理流量足够起步。注意若你准备部署到自己的新应用app必须改成全局唯一名称例如omniroute-yourname否则 Fly 会拒绝创建同名应用。3. 必备工具与环境准备3.1 安装 Fly CLIWindows PowerShell 下执行官方一键安装脚本pwsh -Command iwr https://fly.io/install.ps1 -useb | iex如果安装脚本在当前环境失败也可以手动下载flyctl二进制文件并放入PATH后直接使用。3.2 登录 Fly 账号flyctl auth login该命令会打开浏览器完成 OAuth 授权并把令牌保存在本地flyctl配置中。3.3 检查登录状态flyctl auth whoami flyctl versionflyctl auth whoami应打印当前登录账号flyctl version确认 CLI 版本正常二者通过即环境就绪。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混淆避免改错应用、查错日志。4.3 创建应用如果该应用尚不存在flyctl apps create omniroute如果你已经改成别的应用名把omniroute替换成你的名字。4.4 首次部署flyctl deployflyctl会读取 fly.toml 与 Dockerfile 构建镜像并创建机器。部署前请先完成第 5、6 节的密钥配置避免首次启动落入未配置密钥 → 自动生成 → 无法持久化的隐患。5. 必配参数本项目在 Fly.io 上建议至少配置以下参数。5.1 已验证使用的参数以下参数已经在当前omniroute应用上实际部署验证API_KEY_SECRETDATA_DIRJWT_SECRETMACHINE_ID_SALTNEXT_PUBLIC_BASE_URLSTORAGE_ENCRYPTION_KEY5.2 关于INITIAL_PASSWORD当前项目没有设置INITIAL_PASSWORD因为本次部署按需求不使用它。如果不设置启动日志会提示默认密码是CHANGEME部署后应尽快在系统设置中修改登录密码。如果你希望无人值守初始化后台密码可以后续补充INITIAL_PASSWORD这一变量见第 7 节。5.3 生产环境额外必配OMNIROUTE_WS_BRIDGE_SECRET与本文档英文原版docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md一致生产环境还建议配置OMNIROUTE_WS_BRIDGE_SECRET用于 WebSocket bridge 的握手鉴权缺失时 WebSocket bridge 握手会失败。建议将其一并纳入 Fly Secrets见第 7 节的一键命令。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 挂载点一致NEXT_PUBLIC_BASE_URL用于调度器和前端回调等场景必须是你对外可访问的 HTTPS 域名。6.3 OAuth 回调 URL 配置启用 OAuth 供应商时如果你需要在 Fly.io 部署上启用基于 OAuth 的供应商如 Antigravity、Gemini、Cursor务必确认以下两点将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. 一键设置参数Fly 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说明密钥长度与用途对应API_KEY_SECRET32 字节、JWT_SECRET64 字节、MACHINE_ID_SALT32 字节、STORAGE_ENCRYPTION_KEY32 字节、OMNIROUTE_WS_BRIDGE_SECRET32 字节命令不包含INITIAL_PASSWORD适用于当前项目omnirouteLinux / macOS 下可用openssl rand -hex 32生成随机值flyctl secrets set OMNIROUTE_WS_BRIDGE_SECRET$(openssl rand -hex 32) -a omniroute如果你还要加初始密码flyctl secrets set INITIAL_PASSWORD你的强密码 -a omniroute7.1 为什么必须用 Secrets 显式配置密钥源码原理从仓库源码看启动引导逻辑位于 scripts/build/bootstrap-env.mjs 的bootstrapEnv进程启动时会按持久化的server.env→ 项目.env→ 进程环境变量Fly Secrets 注入的即为此层的优先级合并配置并对缺失的JWT_SECRET、STORAGE_ENCRYPTION_KEY、API_KEY_SECRET自动生成随机值并写入{DATA_DIR}/server.env。这意味着如果不设置任何密钥应用也能启动——但会自动生成一次性密钥只有DATA_DIR指向持久卷时这些自动生成的密钥才会被写进/data/server.env而跨机器重建存活若DATA_DIR未指向持久卷每次机器重建都会重新生成新密钥导致既有数据库加密数据无法解密bootstrap-env.mjs 中检测到已存在加密凭据而缺少STORAGE_ENCRYPTION_KEY时会直接拒绝启动。因此建议始终通过 Fly Secrets 显式、稳定地提供这些密钥而不是依赖启动时的自动生成。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先添加地址填写你 fork 时登记的 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.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/maingit 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说明运行时密钥落到了持久卷/data/storage.sqlite说明数据库写入持久卷。如果你看到的是/app/data/...说明DATA_DIR没配对需要立即修正。11.1 这两个日志对应的源码位置这两条日志不是随机出现的都能在源码里找到对应实现[bootstrap] Secrets persisted to: ...由 scripts/build/bootstrap-env.mjs 在自动生成缺失密钥并写盘时输出日志格式 Secrets persisted to: ${serverEnvPath}其中serverEnvPath join(dataDir, server.env)SQLite 数据库路径在 src/lib/db/core.ts 中由DATA_DIR直接决定SQLITE_FILE path.join(DATA_DIR, storage.sqlite)。数据目录的解析逻辑位于 src/lib/dataPaths.ts 的resolveDataDir显式设置DATA_DIR时优先使用它未设置时回落默认用户目录Linux/macOS 下为~/.omnirouteWindows 下为AppData。在 Fly 容器里默认工作目录是/app见 Dockerfile若不显式设置DATA_DIR/data数据库会落在/app/data/...即容器临时文件系统机器重建即丢失——这正是文档反复强调DATA_DIR/data必须与挂载点一致的原因。11.2 启动入口与镜像事实当前仓库 fly.toml 的进程命令node run-standalone.mjs与 Dockerfile 的CMD [node, dev/run-standalone.mjs]对应的是 scripts/dev/run-standalone.mjs它先执行bootstrapEnv()完成密钥引导再以node启动server-ws.mjs优先或server.js。镜像默认以非 root 的node用户运行并内置 healthcheck生产部署时无需额外处理权限问题。12. 常见问题12.1Secrets页面是空的通常有两种原因你还没执行flyctl secrets set你打开的是另一个应用例如oroute不是omniroute。12.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。不要直接复用旧项目的密钥。密钥泄露或跨项目复用会导致凭据安全边界失效。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相关仓库资源fly.toml部署配置全文挂载卷、进程、HTTP 服务、VM 规格、环境变量Dockerfile镜像构建与运行时入口node dev/run-standalone.mjs、EXPOSE 20128、非 root 用户scripts/dev/run-standalone.mjsstandalone 启动入口scripts/build/bootstrap-env.mjs密钥引导与server.env持久化逻辑src/lib/dataPaths.tsDATA_DIR解析与数据目录回落策略src/lib/db/core.tsSQLite 数据库路径DATA_DIR/storage.sqlitedocs/ops/FLY_IO_DEPLOYMENT_GUIDE.md英文原版部署指南含OMNIROUTE_WS_BRIDGE_SECRET与 OAuth 回调章节【免费下载链接】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),仅供参考