ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OmniRoute 基于 Fly.io 的生产部署完全指南:flyctl 直发、持久化挂载与密钥管理

OmniRoute 基于 Fly.io 的生产部署完全指南:flyctl 直发、持久化挂载与密钥管理 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/OmniRouteOmniRoute 是一个统一的 AI 网关项目通过单一端点聚合数百家模型服务商。本文基于仓库中 docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md 这份经过实际部署验证的指南完整讲解如何在 Fly.io 上完成首次部署、配置密钥、执行滚动更新以及 fork 场景下同步上游代码并保留本地fly.toml的发布工作流。读完本文你将掌握从flyctl安装到生产环境成功标志核验的完整可复现流程。1. 部署目标与总体流程本文档描述的部署方式基于一套已在当前项目上验证可用的配置平台Fly.io部署方式本地flyctl直接发布非 CI/CD运行时直接复用仓库自带的Dockerfile与fly.toml数据持久化Fly Volume 挂载到容器内/data目录访问地址https://omniroute.fly.dev/整个流程覆盖三种场景当前项目首次部署、后续代码更新发布以及新项目复用同一套部署工作流。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 应用flyctl的部署、密钥、日志等命令都要与它保持一致destination /data决定持久化卷的挂载目录是数据不丢失的关键[processes]中的node run-standalone.mjs是容器启动入口对应仓库中的 scripts/dev/run-standalone.mjs。从源码看该脚本会先执行bootstrapEnv()完成环境引导再优先选择 WS 感知的server-ws.mjs否则回退server.js启动 Next.js standalone 服务并透传信号实现优雅退出internal_port 20128与 Dockerfile 中的EXPOSE 20128、ENV PORT20128一致HOST/HOSTNAME/BIND0.0.0.0则保证在 Fly 运行时网络中绑定所有接口使平台健康检查可达。仓库中 fly.toml 比文档示例还多出几项值得注意的配置卷自动扩容auto_extend_size_threshold 80、auto_extend_size_increment 1GB、auto_extend_size_limit 10GB当 Volume 使用率达到 80% 时自动增加 1GB上限 10GBHTTP 服务行为force_https true、auto_stop_machines stop、auto_start_machines true、min_machines_running 1空闲机器可自动停止以节省费用访问时自动唤醒VM 规格memory 1gb、cpu_kind shared、cpus 1。另一个必须注意的前提本项目的DATA_DIR必须显式设置为/data否则数据库与密钥会被写入容器的临时目录容器重建即丢失。源码层面可以验证这一点在 src/lib/db/core.ts 中DATA_DIR由resolveWritableDataDir解析数据库路径由path.join(DATA_DIR, storage.sqlite)计算并在初始化时打印解析后的绝对路径因此DATA_DIR直接决定storage.sqlite落在哪里。3. 前置条件安装与登录 Fly CLI3.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 version4. 当前项目首次部署4.1 克隆代码并进入目录git clone 你的 OmniRoute 仓库地址 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 deploy5. 必需参数生产环境至少应配置这些当前项目建议在 Fly.io 上至少配置以下参数。其中已验证参数是在当前omniroute应用的真实部署中实际使用过的API_KEY_SECRETDATA_DIRJWT_SECRETMACHINE_ID_SALTNEXT_PUBLIC_BASE_URLOMNIROUTE_WS_BRIDGE_SECRET生产环境必须——用于 WebSocket bridge 认证STORAGE_ENCRYPTION_KEY这些变量并非凭空定义在 src/lib/env/runtimeEnv.ts 的webRuntimeEnvSchema中DATA_DIR、JWT_SECRET、API_KEY_SECRET、INITIAL_PASSWORD、NEXT_PUBLIC_BASE_URL等都被声明为运行时环境变量并经过 zod 校验例如NEXT_PUBLIC_BASE_URL必须以http://或https://开头启动时若校验失败会输出明确的错误信息。各密钥在源码中的实际作用API_KEY_SECRET用于 API Key 的生成与校验相关逻辑见 src/lib/services/apiKey.tsSTORAGE_ENCRYPTION_KEY用于对敏感连接信息做静态加密。见 src/lib/db/encryption.ts——如果未设置该变量加密模块会进入passthrough 模式明文存储并在日志中提示一旦换掉密钥历史已加密数据将无法解密日志会给出 Check your STORAGE_ENCRYPTION_KEY — generate one with: openssl rand -base64 32 的提示因此首次部署就应固定一个强密钥并妥善保管MACHINE_ID_SALT用于生成稳定的机器标识。见 src/shared/utils/machineId.tsconst saltValue salt || process.env.MACHINE_ID_SALT || endpoint-proxy-salt不设置时会退回到仓库内置的默认盐值OMNIROUTE_WS_BRIDGE_SECRET用于 WebSocket bridge 握手认证。见 src/server/authz/policies/management.ts其校验逻辑会读取请求头x-omniroute-ws-bridge-secret并与OMNIROUTE_WS_BRIDGE_SECRET比对缺失时按空字符串处理握手会失败。5.1 关于INITIAL_PASSWORD当前项目的部署没有设置INITIAL_PASSWORD因为该部署场景不需要。如果不设置启动日志会提示默认密码为CHANGEME部署完成后应尽快在系统设置中修改登录密码。仓库源码印证了这一点在 src/lib/auth/managementPassword.ts 中CHANGEME 被列入INSECURE_DEFAULT_PASSWORDS黑名单集合检测到使用该默认值时日志会发出安全警告[AUTH][SECURITY] Management password is set to the well-known default CHANGEME同时 src/lib/db/settings.ts 中当设置了INITIAL_PASSWORD时系统会认为这是 headless 部署而跳过初始化向导。若希望无人值守地初始化后端密码可后续补上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 挂载点一致NEXT_PUBLIC_BASE_URL会被调度器、前端回调等场景使用。6.3 OAuth 回调地址配置如果要在 Fly.io 部署上启用基于 OAuth 的提供商如 Antigravity、Gemini、Cursor 等必须保证两点1. 将NEXT_PUBLIC_BASE_URL设置为你的公开 HTTPS 域名flyctl secrets set NEXT_PUBLIC_BASE_URLhttps://omniroute.fly.dev -a omniroute使用自定义域名时替换为对应域名例如https://omniroute.yourdomain.com。2. 在提供商控制台配置回调地址所有 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不包含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 32生成随机值flyctl secrets set OMNIROUTE_WS_BRIDGE_SECRET$(openssl rand -hex 32) -a omnirouteSTORAGE_ENCRYPTION_KEY的生成方式在仓库日志提示中同样推荐openssl rand -base64 32这类随机源见 src/lib/db/encryption.ts切勿使用弱口令。注意OMNIROUTE_WS_BRIDGE_SECRET生产环境必须设置缺失会导致 WebSocket bridge 握手失败。如需同时设置初始密码flyctl secrets set INITIAL_PASSWORDyour-strong-password -a omniroute8. 查看当前参数flyctl secrets list -a omniroute如果控制台的 Secrets 页面没有显示预期的变量请检查当前查看的确实是omniroute应用fly.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下文中的v3.4.7仅为历史示例实际发布请使用:latest或当前版本标签如:v3.8.0。若希望合并上游最新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这一步能保证你的应用名、卷挂载、区域等 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说明运行时密钥已写入持久化卷/data/storage.sqlite说明数据库已写入持久化卷。数据库路径的生成逻辑与源码一致在 src/lib/db/core.ts 中SQLITE_FILE path.join(DATA_DIR, storage.sqlite)并在数据库初始化时打印解析后的DATA_DIR与SQLITE_FILE。如果日志中出现的是/app/data/...路径说明DATA_DIR配置错误必须立即修正。这通常是因为 Dockerfile 内置了默认值ENV DATA_DIR/app/data而 Fly 部署下必须用DATA_DIR/data覆盖它才能落到 Volume 挂载点。12. 常见问题12.1 Secrets 页面为空通常有两种原因尚未执行过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。生产环境强烈建议尽快修改后端密码或补设INITIAL_PASSWORD仓库的安全代码会对这一默认值发出明确警告。13. 复用于新项目若按本文档部署一个新项目只需要改动这些项修改fly.toml中的app值修改NEXT_PUBLIC_BASE_URL保持DATA_DIR/data不变重新生成API_KEY_SECRET、JWT_SECRET、MACHINE_ID_SALT和STORAGE_ENCRYPTION_KEY首次部署后确认日志写入/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 omnirouteflyctl deployflyctl logs --no-tail -a omniroute相关参考fly.toml应用名、区域、卷挂载、进程与 HTTP 服务配置DockerfilePORT20128、DATA_DIR/app/data默认值、健康检查与非 root 运行scripts/dev/run-standalone.mjs容器启动入口环境引导与 WS 包装器选择src/lib/env/runtimeEnv.ts运行时环境变量 schema 与校验src/lib/db/core.tsDATA_DIR解析与storage.sqlite路径生成src/lib/db/encryption.tsSTORAGE_ENCRYPTION_KEY加密与 passthrough 模式src/lib/auth/managementPassword.tsINITIAL_PASSWORD与默认密码告警src/server/authz/policies/management.tsOMNIROUTE_WS_BRIDGE_SECRET握手校验【免费下载链接】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),仅供参考
返回列表