Every .md under docs/{architecture,guides,reference,frameworks,routing,
security,compression,ops,diagrams} plus docs/README.md now opens with:
---
title: "<inferred from first H1>"
version: 3.8.0
lastUpdated: 2026-05-13
---
46 files updated (no docs were skipped — none had pre-existing
frontmatter). [slug]/page.tsx already reads frontmatter.version and
frontmatter.lastUpdated via gray-matter and renders a "v3.8.0" pill
plus a "Last updated" caption, so the UI picks these up automatically.
Helper: scripts/docs/add-frontmatter.mjs — idempotent (skips files that
already start with `---`), falls back to a humanized basename when no
leading H1 exists. Excludes docs/i18n/, docs/screenshots/,
docs/superpowers/, docs/diagrams/exported/. Re-runnable safely.
Also regenerated src/app/docs/lib/docs-auto-generated.ts: 44 docs across
8 sections (Architecture / Guides / Reference / Frameworks / Routing /
Security / Compression / Ops), which now includes the 14 docs that were
missing from the v3.7 sidebar (Cloud Agents, Guardrails, Memory, Skills,
Webhooks, Evals, Authz, Agent Protocols, Repository Map, Provider
Reference, Reasoning Replay, Stealth Guide, Tunnels Guide, Electron
Guide).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
14 KiB
title, version, lastUpdated
| title | version | lastUpdated |
|---|---|---|
| OmniRoute Fly.io 部署指南 | 3.8.0 | 2026-05-13 |
OmniRoute Fly.io 部署指南
本文档记录 OmniRoute 在 Fly.io 上的实际部署方法,适用于两类场景:
- 首次把当前项目部署到 Fly.io
- 后续代码更新后继续发布
- 新项目参考同样流程部署
本文基于当前项目已经验证通过的配置整理,应用名为 omniroute。
1. 部署目标
- 平台:Fly.io
- 部署方式:本地
flyctl直接发布 - 运行方式:使用仓库内现有
Dockerfile和fly.toml - 数据持久化:Fly Volume 挂载到
/data - 访问地址:
https://omniroute.fly.dev/
2. 当前项目关键配置
当前仓库中的 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,否则数据库和密钥会写到容器临时目录
3. 必备工具
3.1 安装 Fly CLI
Windows PowerShell:
pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex"
如果安装脚本在当前环境失败,也可以手动下载 flyctl 二进制并放到 PATH 中。
3.2 登录 Fly 账号
flyctl auth login
3.3 检查登录状态
flyctl auth whoami
flyctl version
4. 首次部署当前项目
4.1 获取代码并进入目录
git clone https://github.com/diegosouzapw/OmniRoute.git
cd OmniRoute
4.2 确认应用名
打开 fly.toml,重点看这一行:
app = 'omniroute'
如果你准备部署到自己的新应用,可改成全局唯一名称,例如:
app = 'omniroute-yourname'
注意:
- 控制台里要看的是与
fly.toml里app一致的应用 - 以前如果用过别的名字,例如
oroute,不要和omniroute混淆
4.3 创建应用
如果该应用尚不存在:
flyctl apps create omniroute
如果你已经改成别的应用名,把 omniroute 替换成你的名字。
4.4 首次部署
flyctl deploy
5. 必配参数
本项目在 Fly.io 上建议至少配置以下参数。
5.1 已验证使用的参数
这些参数已经在当前 omniroute 应用上实际部署:
API_KEY_SECRETDATA_DIRJWT_SECRETMACHINE_ID_SALTNEXT_PUBLIC_BASE_URLOMNIROUTE_WS_BRIDGE_SECRET(生产环境必需 / required in production / obrigatório em produção — 用于 WebSocket 桥接鉴权 / used for WebSocket bridge authentication)STORAGE_ENCRYPTION_KEY
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 |
生产必需 (required / obrigatório) | WebSocket 桥接鉴权密钥 (WebSocket bridge auth / chave de autenticação da ponte WebSocket) |
STORAGE_ENCRYPTION_KEY |
强烈推荐 | 加密存储敏感连接信息 |
MACHINE_ID_SALT |
推荐 | 生成稳定机器标识 |
INITIAL_PASSWORD |
可选 | 首次部署时直接指定后台初始密码 |
| OAuth/API 私密凭证 | 按需 | 各类外部平台鉴权配置 |
6.2 当前项目推荐值
| 变量名 | 推荐值 |
|---|---|
DATA_DIR |
/data |
NEXT_PUBLIC_BASE_URL |
https://omniroute.fly.dev |
说明:
DATA_DIR=/data非常关键,必须与 Fly Volume 挂载点一致NEXT_PUBLIC_BASE_URL用于调度器和前端回调等场景
6.3 OAuth 回调地址配置 (OAuth callback URL / URL de callback OAuth)
如果你需要在 Fly.io 部署上启用 OAuth 登录类的 provider(例如 Antigravity、Gemini、Cursor 等),必须确保以下两点: (If you need to enable OAuth-based providers — e.g. Antigravity, Gemini, Cursor — on the Fly.io deployment, make sure of the following two points. / Se precisar habilitar providers via OAuth — p.ex. Antigravity, Gemini, Cursor — na implantação Fly.io, garanta os dois pontos abaixo.)
-
设置
NEXT_PUBLIC_BASE_URL指向你公开的 HTTPS 域名 (setNEXT_PUBLIC_BASE_URLto the public HTTPS domain / definaNEXT_PUBLIC_BASE_URLpara o domínio HTTPS público)flyctl secrets set NEXT_PUBLIC_BASE_URL=https://omniroute.fly.dev -a omniroute如果你使用了自定义域名 (if using a custom domain / se usar um domínio personalizado),请替换为对应域名 (e.g.
https://omniroute.yourdomain.com)。 -
在 provider 控制台配置回调 URL (configure the callback URL on the provider console / configure a URL de callback no painel do provider)
通常格式为 (typical format / formato típico):
<NEXT_PUBLIC_BASE_URL>/api/oauth/<provider>/callback例如 (e.g. / p.ex.):
https://omniroute.fly.dev/api/oauth/gemini/callbackhttps://omniroute.fly.dev/api/oauth/antigravity/callbackhttps://omniroute.fly.dev/api/oauth/cursor/callback
如果
NEXT_PUBLIC_BASE_URL与 provider 控制台中注册的回调 URL 不一致,OAuth 流程会在浏览器回跳阶段失败 (mismatch betweenNEXT_PUBLIC_BASE_URLand the registered callback URL will cause OAuth to fail at the browser redirect step / divergência entreNEXT_PUBLIC_BASE_URLe a URL de callback registrada quebra o OAuth no redirect do navegador)。
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 生成 (on Linux / macOS, you can also use openssl rand -hex 32 / em Linux / macOS, também é possível usar openssl rand -hex 32):
flyctl secrets set OMNIROUTE_WS_BRIDGE_SECRET=$(openssl rand -hex 32) -a omniroute
说明 (notes / observações):
OMNIROUTE_WS_BRIDGE_SECRET在生产环境必需,缺失会导致 WebSocket 桥接握手失败 (required in production; missing it breaks WebSocket bridge handshake / obrigatório em produção; sem ele o handshake da ponte WebSocket falha)
如果你还要加初始密码:
flyctl secrets set INITIAL_PASSWORD=你的强密码 -a omniroute
8. 查看当前参数
flyctl secrets list -a omniroute
如果控制台 Secrets 页面没有显示你期待的变量,先检查:
- 看的应用是不是
omniroute fly.toml的app是否和控制台应用一致
9. 后续更新发布
代码有更新后,发布步骤很简单:
git pull
flyctl deploy
如果只更新参数,不改代码:
flyctl secrets set KEY=value -a omniroute
Fly 会自动滚动更新机器。
9.1 跟踪原仓库更新并保留 fork 的 fly.toml
如果当前仓库是 fork,并且你要同步上游 https://github.com/diegosouzapw/OmniRoute 的更新,推荐按下面流程执行。
先确认远程:
git remote -v
应至少包含:
origin指向你自己的 forkupstream指向原仓库
如果没有 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
注 (note / nota):当前项目版本为
v3.8.0(current project version isv3.8.0/ a versão atual do projeto év3.8.0)。下文中的v3.4.7仅为历史示例 (thev3.4.7references below are kept as historical examples only / as referências av3.4.7abaixo são apenas exemplos históricos);实际发布时请使用:latest或当前版本标签 (e.g.:v3.8.0) (use:latestor the current version tag — e.g.:v3.8.0— for actual releases / use:latestou a tag da versão atual — p.ex.:v3.8.0— em releases reais)。
如果你想合并上游最新 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
返回成功表示 upstream/main 已经包含该版本,直接合并 upstream/main 即可。
9.2 同步上游后的标准发布顺序
同步原仓库完成后,推荐按下面顺序发布:
git fetch upstream --tagsgit merge upstream/main- 恢复 fork 的
fly.toml git push origin mainflyctl deployflyctl status -a omnirouteflyctl logs --no-tail -a omniroute
这就是当前项目升级到 v3.4.7 时使用的实际流程 (示例为历史版本,当前实际版本是 v3.8.0 / example refers to a historical version; the current actual version is v3.8.0 / o exemplo refere-se a uma versão histórica; a versão atual é v3.8.0)。
10. 发布后检查
10.1 查看应用状态
flyctl status -a omniroute
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说明运行时密钥落到了持久卷/data/storage.sqlite说明数据库写入持久卷
如果你看到的是 /app/data/...,说明 DATA_DIR 没配对,需要立即修正。
12. 常见问题
12.1 Secrets 页面是空的
通常有两种原因:
- 你还没执行
flyctl secrets set - 你打开的是另一个应用,例如
oroute,不是omniroute
12.2 flyctl deploy 报 app not found
先创建应用:
flyctl apps create omniroute
12.3 fly.toml 解析失败
重点检查:
- 注释里是否有乱码字符
- TOML 引号和缩进是否正确
12.4 数据没有持久化
检查以下两点:
fly.toml中是否存在destination = '/data'DATA_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 - 首次部署后检查日志是否写入
/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