⚙️ 配置说明
本文档按实际使用场景说明 Metapi 的配置入口。
对大多数用户来说,日常配置优先通过管理后台完成;环境变量主要用于首次启动、部署级参数和当前没有 UI 的高级项。
概述
Metapi 当前有三类主要配置入口:
- 管理后台「设置」 — 适合日常系统设置与运行时调整
- 管理后台「通知设置」与「下游密钥」 — 适合通知渠道和项目级下游 Key 管理
- 环境变量 — 适合首次启动、部署级参数、OAuth client 覆盖、Deploy Helper token 等当前没有 UI 的项
下表可用于快速判断:
| 你要改什么 | 优先去哪里 | 说明 |
|---|---|---|
| 日常系统设置 | 管理后台「设置」 | 大部分运行时配置都在这里,保存后直接生效或按提示重启 |
| 通知渠道 | 管理后台「通知设置」 | Webhook / Bark / Server酱 / Telegram / SMTP 都有 UI |
| 下游项目级 Key | 管理后台「下游密钥」 | 不要再回到环境变量里硬塞 |
| 首次启动令牌、端口、数据目录 | .env / 容器环境变量 | 这类属于部署级初始化 |
| OAuth 客户端 ID / Secret | .env / 容器环境变量 | 当前没有 UI |
| Deploy Helper token / helper 进程参数 | .env / helper manifest | 当前没有 UI,且属于集群侧部署参数 |
| 少数高级部署级参数 | .env / 容器环境变量 | 例如日志保留、部分探测细粒度参数 |
配置入口总览
1. 管理后台「设置」
侧边栏入口:系统 → 设置
当前已经能直接在这里配置的内容包括:
| UI 项 | 对应能力 | 生效方式 |
|---|---|---|
| 管理员登录令牌 | AUTH_TOKEN 的后续修改 | 保存后即时生效 |
| 定时任务 | CHECKIN_CRON、BALANCE_REFRESH_CRON、日志清理计划 | 保存后即时生效 |
| 系统代理 | SYSTEM_PROXY_URL | 保存后即时生效 |
| 代理失败判定 | 失败关键词、空内容失败判定 | 保存后即时生效 |
| Codex 上游传输与会话并发 | WebSocket 开关、并发与队列参数 | 保存后即时生效 |
| 批量测活 | 后台模型可用性探测开关 | 保存后即时生效 |
| 下游访问令牌 | PROXY_TOKEN | 保存后即时生效 |
| 路由策略 | 成本/余额/使用率权重、默认单价、首字超时、协议回退、失败冷却上限 | 保存后即时生效 |
| 全局品牌屏蔽 | 全局品牌屏蔽 | 保存后即时生效,并触发路由重建 |
| 全局模型白名单 | 全局模型白名单 | 保存后即时生效,并触发路由重建 |
| 数据库迁移 / 运行数据库 | DB_TYPE、DB_URL、DB_SSL | 保存后下次后端重启生效 |
| 更新中心 | K3s / Helm 更新中心配置 | 保存后即时生效 |
| 会话与安全 | ADMIN_IP_ALLOWLIST | 保存后即时生效 |
TIP
AUTH_TOKEN 和 PROXY_TOKEN 并不是“只能靠环境变量改”的配置。 正常情况下,首次启动先给一个值,后续都可以在 UI 里改。
2. 管理后台「通知设置」
侧边栏入口:系统 → 通知设置
当前已经有独立页面可直接配置:
| UI 项 | 说明 | 生效方式 |
|---|---|---|
| Webhook | 企业微信 / 飞书 / 通用 Webhook | 保存后即时生效 |
| Bark | Bark 推送地址与开关 | 保存后即时生效 |
| Server酱 | SendKey 与开关 | 保存后即时生效 |
| Telegram | API Base URL、Chat ID、Topic ID、Bot Token、是否走系统代理 | 保存后即时生效 |
| SMTP | SMTP 主机、端口、账号、密码、发件/收件地址 | 保存后即时生效 |
| 告警冷静期 | NOTIFY_COOLDOWN_SEC | 保存后即时生效 |
通知设置页面已经支持:
- 直接保存
- 直接发测试通知
- 屏蔽回显已保存的敏感字段
通知配置可直接在该页面完成,无需先记环境变量名。
3. 管理后台「下游密钥」
侧边栏入口:控制台 → 下游密钥
「下游密钥」页面负责的是项目级下游 API Key,而不是全局 PROXY_TOKEN。
适合在这里配置的内容:
- Key 名称
- 过期时间
- 费用 / 请求上限
- 模型白名单
- 路由白名单
- 站点权重倍率
- 启停、重置用量、趋势与统计
这类能力可直接在页面里完成,不需要额外依赖环境变量。
首次启动时,至少准备这些环境变量
首次把服务跑起来时,建议先在环境变量里准备以下几项:
| 变量名 | 说明 | 默认值 |
|---|---|---|
AUTH_TOKEN | 初始管理员登录令牌 | change-me-admin-token |
PROXY_TOKEN | 初始下游访问令牌 | change-me-proxy-sk-token |
PORT | 服务监听端口 | 4000 |
DATA_DIR | 数据目录(SQLite 默认落这里) | ./data |
TZ | 时区 | Asia/Shanghai |
说明:
AUTH_TOKEN只是第一次登录前必须要有;登录后可以去「设置」里改。PROXY_TOKEN也只是建议先给一个初始值;后续可以在「设置」里改。PORT、DATA_DIR、TZ这类属于部署级参数,更适合留在环境变量。
环境变量配置
1. 启动与部署级
这类配置要么属于进程启动参数,要么属于当前确实没有 UI 的部署项:
| 变量名 | 说明 | 默认值 |
|---|---|---|
PORT | 服务监听端口 | 4000 |
DATA_DIR | 数据目录(SQLite 数据库存储位置) | ./data |
TZ | 时区 | Asia/Shanghai |
ACCOUNT_CREDENTIAL_SECRET | 账号凭证加密密钥(用于加密存储的上游账号密码) | 默认使用 AUTH_TOKEN |
2. OAuth 与 Provider 登录
这一节说明 OAuth client 的环境变量配置。Codex 和 Claude 保留各自的现有默认行为;Gemini CLI 和 Antigravity 不包含内置 Google OAuth client 凭据。
| 变量名 | 说明 | 默认值 |
|---|---|---|
CODEX_CLIENT_ID | 覆盖内置 Codex OAuth Client ID | 内置默认值 |
CLAUDE_CLIENT_ID | 覆盖内置 Claude OAuth Client ID | 内置默认值 |
CLAUDE_CLIENT_SECRET | 预留的 Claude OAuth Client Secret(默认留空) | 空 |
GEMINI_CLI_CLIENT_ID | Gemini CLI OAuth Client ID | 空(使用 Gemini CLI OAuth 时必填) |
GEMINI_CLI_CLIENT_SECRET | Gemini CLI OAuth Client Secret | 空(使用 Gemini CLI OAuth 时必填) |
ANTIGRAVITY_CLIENT_ID | Antigravity OAuth Client ID | 空(使用 Antigravity OAuth 时必填) |
ANTIGRAVITY_CLIENT_SECRET | Antigravity OAuth Client Secret | 空(使用 Antigravity OAuth 时必填) |
说明:
- 使用 Gemini CLI OAuth 时,必须同时提供
GEMINI_CLI_CLIENT_ID和GEMINI_CLI_CLIENT_SECRET;不使用该 provider 时可以留空。 - 使用 Antigravity OAuth 时,必须同时提供
ANTIGRAVITY_CLIENT_ID和ANTIGRAVITY_CLIENT_SECRET;不使用该 provider 时可以留空。 - 这些 Google OAuth 凭据必须通过部署 secret manager,或未跟踪的本地
.env/ 容器环境变量提供;不要把真实值写入仓库。.env.example中的字段保持为空。 - 如果你的部署环境访问 provider 受限,优先先在 UI 里配置系统代理。
- 如果 OAuth 页面运行在远程服务器上,还要考虑 SSH 隧道或手动回填 callback,详见 OAuth 管理。
3. K3s 更新中心与 Deploy Helper
这里要分清楚两层:
- 主 Metapi 后台里的日常更新中心配置:优先在 UI 里填
- 主服务访问 helper 的 token / helper 自己的监听参数:仍然是环境变量
主 Metapi 服务
| 变量名 | 说明 | 默认值 |
|---|---|---|
DEPLOY_HELPER_TOKEN | 主服务访问 Deploy Helper 的 Bearer Token | 空 |
UPDATE_CENTER_HELPER_TOKEN | DEPLOY_HELPER_TOKEN 的兼容别名,二选一即可 | 空 |
Deploy Helper 服务
| 变量名 | 说明 | 默认值 |
|---|---|---|
DEPLOY_HELPER_HOST | helper 监听地址 | 0.0.0.0 |
DEPLOY_HELPER_PORT | helper 监听端口 | 9850 |
DEPLOY_HELPER_TOKEN | helper Bearer Token,必须和主服务一致 | 空 |
更新中心里真正建议在 UI 配的字段
这些字段不建议再教用户去改 env,而是直接去:
设置 → 更新中心
helperBaseUrlnamespacereleaseNamechartRefimageRepositorygithubReleasesEnableddockerHubTagsEnableddefaultDeploySource
完整接入步骤见 K3s 更新中心(高级)。
4. 当前没有 UI 的高级部署级参数
下面这些参数目前更偏部署级,仍然建议通过环境变量维护:
| 变量名 | 说明 | 默认值 |
|---|---|---|
TOKEN_ROUTER_CACHE_TTL_MS | Token 路由缓存 TTL(毫秒) | 1500 |
PROXY_LOG_RETENTION_DAYS | 代理日志保留天数 | 30 |
PROXY_LOG_RETENTION_PRUNE_INTERVAL_MINUTES | 代理日志清理任务执行间隔(分钟) | 30 |
MODEL_AVAILABILITY_PROBE_INTERVAL_MS | 批量测活间隔(毫秒) | 1800000 |
MODEL_AVAILABILITY_PROBE_TIMEOUT_MS | 批量测活单次探测超时(毫秒) | 15000 |
MODEL_AVAILABILITY_PROBE_CONCURRENCY | 批量测活并发数 | 1 |
PROXY_SITE_CONCURRENCY_QUEUE_LIMIT | 单个进程中每个受限站点最多等待的请求数(queue cap) | 100 |
PROXY_SITE_CONCURRENCY_QUEUE_WAIT_MS | 等待站点并发名额的最长时间(毫秒) | 1500 |
PROXY_SITE_CONCURRENCY_LEASE_TTL_MS | 单个站点并发租约的最长存活时间(毫秒) | 90000 |
PROXY_SITE_CONCURRENCY_LEASE_KEEPALIVE_MS | 流式响应续租间隔(毫秒) | 15000 |
站点最大并发
在「控制台 → 站点」中可为每个站点设置 maxConcurrency。maxConcurrency=0 means unlimited:0 会以 NULL 持久化,表示该站点不限制并发。
- 限制是 process-local:每个 Metapi 进程独立计算,不会跨多副本或多机器协调;部署多个副本时,每个副本都会各自执行同样的站点上限。
- 到达上限后,请求会在 queue cap 内等待,最多等待
PROXY_SITE_CONCURRENCY_QUEUE_WAIT_MS;队列已满或等待超时会返回 HTTP503,并带有Retry-After响应头。 - Dynamic site-limit changes take effect immediately:保存站点的新限制后,本进程中的后续准入和等待队列立即按新值处理,无需重启。
- 上游流式响应会持有 streaming lease,直到流读取结束、出错、取消、客户端断开或租约到期;因此流式请求会占用名额的整个响应生命周期。
- Internal flows are excluded:仅下游代理的上游站点请求参与限制;站内管理、备份、迁移、探测及其他内部流程不占用站点并发名额。
**回滚:**将所有站点限制设为 0/NULL(set every site limit to 0/NULL)即可立即停用并发强制;migration 0029 may remain inert,无需回滚该加性迁移。
注意:
- 批量测活开关本身已经在 UI 里有了
- 这里只剩下间隔、超时、并发这些更高级的细项还没有 UI
5. 请求速率限制
请求限流分为两层:全局粗粒度保护,以及认证成功后的身份级保护。三个限流环境变量如下:
| 变量名 | 说明 | 默认值 |
|---|---|---|
REQUEST_RATE_LIMIT_MAX | 每个 TCP socket 在一个窗口内允许的全局请求数 | 12000 |
REQUEST_RATE_LIMIT_WINDOW_MS | 全局和认证限流共用的窗口长度(毫秒) | 60000 |
AUTHENTICATED_RATE_LIMIT_MAX | 每个认证身份在一个窗口内允许的请求数 | 1200 |
限流身份与覆盖范围
- 全局层使用
REQUEST_RATE_LIMIT_MAX和REQUEST_RATE_LIMIT_WINDOW_MS,按 TCP socket 的remoteAddress计数。这是有意保守的粗粒度保护:同一个 socket 共享一个桶,不按用户、Token 或 provider 细分。 - 管理员 API在管理员认证成功后,使用固定的
admin身份计数。因此当前进程内所有已认证的管理员 API 请求共享一个AUTHENTICATED_RATE_LIMIT_MAX桶。 - 下游代理在代理认证成功后按认证结果计数:托管下游密钥使用
managed:<managed-key-id>身份,各托管密钥相互独立;全局PROXY_TOKEN使用global身份,使用该全局 Token 的代理请求共享一个桶。 - Responses 原始 WebSocket升级在提取令牌和数据库认证之前,先按 TCP socket
remoteAddress进入全局粗粒度边界;认证成功后,连接创建和每个请求 frame 分别使用认证身份桶,并共享AUTHENTICATED_RATE_LIMIT_MAX上限。连接桶与 frame 桶相互独立,frame 被拒绝时返回 WebSocket429错误和重试秒数,不会继续路由或消耗托管配额。 - 认证失败的请求不会进入上述认证身份桶,但仍会受到全局层保护。
全局层直接使用 socket 地址,不使用 X-Forwarded-For 作为限流身份;管理员、托管密钥和全局代理 Token 的认证身份也不由 X-Forwarded-For 决定。反向代理即使改变该请求头,也不会为这些限流边界生成新的桶。现有的 IP 白名单和路由专属保护仍按各自既有语义工作。
限流计数器和 Responses WebSocket 的内部 HTTP fallback 上下文都保存在当前 Node.js 进程内。多进程、多容器或多副本部署时,每个实例都有独立计数,不能自动形成集群级上限;需要跨实例统一限制时,建议接入共享限流存储(例如 Redis),或在服务前使用具备共享状态的网关、WAF 或负载均衡器。
GET /api/desktop/health 是健康探测例外,不要求认证,也不参与全局限流。其他更靠近敏感操作的路由仍保留更严格的路由级 guard;例如修改管理员 Token 的路由仍限制为每个来源地址每 60 秒最多 3 次。这些更严格的限制与全局、认证边界叠加,不会因新增全局限流而取消。
全局边界超限时返回 HTTP 429,JSON 固定为 {"statusCode":429,"error":"Too many requests","retryAfter":"..."},并设置秒数形式的 Retry-After 响应头。既有路由级 guard 保持项目兼容的 {"success":false,"message":"请求过于频繁,请稍后再试"} JSON 形状,同时设置 Retry-After;两种形状都表示同一类 429 限流结果。
根插件会在注册 API 和 proxy 路由之前安装全局限流;根级 enforcement hook 在 CORS 之后、退休路由 guard 和认证之前执行。因此未来新增 provider 或在根插件之后注册的新路由会自动受到全局保护,无需为每个 provider 或路由另行配置 limiter;认证代理路由仍沿用其既有的认证身份级保护。
常见配置与入口对照
通常已经有 UI 的配置
- 管理员令牌
- 下游访问令牌
- 系统代理
- 定时任务
- 路由策略
- 批量测活开关
- 安全白名单
- 通知渠道
- 下游密钥
- 数据库运行配置
- 更新中心主体配置
通常仍需看环境变量的配置
- 端口
- 数据目录
- 时区
- 账号凭证加密密钥
- OAuth client 覆盖
- Deploy Helper token
- helper 进程自身监听参数
- 少数高级部署级性能 / 清理参数
UI 与环境变量的关系
Metapi 当前的配置关系可以概括为:
- 环境变量负责启动默认值和部署参数
- UI 负责用户日常操作和运行时调整
- UI 保存后的值会持久化到当前运行数据库
- 大多数 UI 设置会覆盖原始默认值
例外主要有两类:
- 纯部署级参数:例如端口、数据目录
- 保存后需重启的配置:例如运行数据库类型 / 连接串 / SSL
通知渠道详细说明
虽然我更推荐直接去「通知设置」页面,但为了方便查字段,这里保留一个速查表。
Webhook
| UI / 变量 | 说明 | 默认值 |
|---|---|---|
WEBHOOK_ENABLED | 启用 Webhook 通知 | true |
WEBHOOK_URL | Webhook 推送地址 | 空 |
Bark(iOS 推送)
| UI / 变量 | 说明 | 默认值 |
|---|---|---|
BARK_ENABLED | 启用 Bark 推送 | true |
BARK_URL | Bark 推送地址 | 空 |
Server酱
| UI / 变量 | 说明 | 默认值 |
|---|---|---|
SERVERCHAN_ENABLED | 启用 Server酱 通知 | true |
SERVERCHAN_KEY | Server酱 SendKey | 空 |
Telegram Bot
| UI / 变量 | 说明 | 默认值 |
|---|---|---|
TELEGRAM_ENABLED | 启用 Telegram 通知 | false |
TELEGRAM_BOT_TOKEN | Telegram Bot Token(形如 123456:abc) | 空 |
TELEGRAM_CHAT_ID | 接收消息的 Chat ID(如 -100xxxx 或 @channel) | 空 |
TELEGRAM_API_BASE_URL | Telegram Bot API 基地址;会去除首尾空白和末尾 / | https://api.telegram.org |
TELEGRAM_MESSAGE_THREAD_ID | Telegram Topic ID | 空 |
TELEGRAM_USE_SYSTEM_PROXY | Telegram 请求是否使用系统代理 | false |
这些环境变量用于提供首次启动默认值;在「通知设置」中保存的持久化配置仍然优先。
配置步骤:
- 创建 Bot:在 Telegram 中搜索 @BotFather,发送
/newbot,按提示设置名称后获取 Bot Token - 获取 Chat ID:
- 个人聊天:给 Bot 发消息后,通过
getUpdates或 @userinfobot / @getmyid_bot 查看chat.id - 群组:把 Bot 拉进群并发送消息后,通过
getUpdates查看群组 Chat ID - 频道:可直接使用
@your_channel(前提是 Bot 是频道管理员)
- 个人聊天:给 Bot 发消息后,通过
- 填入位置:优先去 通知设置 页面填写
- 大陆服务器反代:如果服务器不能直连 Telegram,可在 UI 里填写
Telegram API Base URL - 测试:保存后直接点“发送测试通知”
SMTP 邮件
| UI / 变量 | 说明 | 默认值 |
|---|---|---|
SMTP_ENABLED | 启用邮件通知 | false |
SMTP_HOST | SMTP 服务器地址 | 空 |
SMTP_PORT | SMTP 端口 | 587 |
SMTP_SECURE | 使用 SSL/TLS | false |
SMTP_USER | SMTP 用户名 | 空 |
SMTP_PASS | SMTP 密码 | 空 |
SMTP_FROM | 发件人地址 | 空 |
SMTP_TO | 收件人地址 | 空 |
告警控制
| UI / 变量 | 说明 | 默认值 |
|---|---|---|
NOTIFY_COOLDOWN_SEC | 相同告警冷静期(秒),防止同一事件重复通知 | 300 |
站点公告
管理后台新增了「站点公告」页面,用于保存和浏览 Metapi 已同步到本地的上游公告记录。
- 首次发现的上游公告会写入站内通知,并按现有通知渠道外发一次
- 后续重复同步只更新本地公告记录,不会重复外发同一条公告
- 当前支持的上游公告来源包括
new-api、done-hub与sub2api - 「清空公告」只删除 Metapi 本地保存的公告记录,不会修改上游站点数据
更新提醒
更新中心现在会在后台定时检查 GitHub Releases / Docker Hub 的可部署候选,并把结果保存为本地运行时状态。
- 首次发现新的版本候选或新的 Docker digest 时,会写入站内通知,并按现有通知渠道外发一次
- 相同候选后续重复检查只更新本地运行时状态,不会重复外发同一条提醒
- 这类提醒不会自动触发部署,只是把用户带到「设置 → 更新中心」继续手动确认和执行
- K3s 用户可以在收到提醒后直接去更新中心部署;Compose 用户也可以收到提醒,但仍按自己的升级方式处理