
解读文件:gateway/server.impl.ts
第一阶段:配置 & 认证(Config + Auth)
整体大纲如下:
startGatewayServer() //L572-822 — startGatewayServer 第一阶段主体
│
|-server-startup-config.ts — loadGatewayStartupConfigSnapshot + prepareGatewayStartupConfig + createRuntimeSecretsActivator
├─ bootstrapGatewayNetworkRuntime() // L619-620 网络栈初始化
│ └─server-network-runtime.ts — bootstrapGatewayNetworkRuntime(undici 代理初始化)
├─ createGatewayStartupTrace() // L643, 启动性能打点器
│
├─ loadGatewayStartupConfigSnapshot() // L652 ① 读取配置文件快照
│ └─ 返回 { snapshot, sourceConfig, pluginMetadataSnapshot }
│
├─ applyConfigOverrides(configSnapshot) // ② 应用命令行覆盖
│
├─ prepareGatewayStartupConfig() // L712-719 ③ 认证准备
│ ├─ resolveGatewayAuth() → //L1049-1056解析 auth mode(token/device/tailscale)
| |- auth.ts — resolveGatewayAuth + 认证授权核心逻辑
| |-auth-resolve.ts — auth mode 解析(token/password/tailscale/trusted-proxy)
│ ├─ 如果缺 token → 自动生成 + 持久化
| |-startup-auth.ts — ensureGatewayStartupAuth(token 自动生成逻辑)
│ └─ activateRuntimeSecrets → // L695-702激活加密凭据
│
├─ isDiagnosticsEnabled() // L763 isDiagnosticsEnabled ④ 诊断开关
├─ setGatewaySigusr1RestartPolicy() // L771 ⑤ SIGUSR1 重启策略
├─ setPreRestartDeferralCheck() // L773-782⑥ 重启前检查(队列/连接/任务)
L575 — Promise<GatewayServer>
返回Promise<GatewayServer>,Promise<T> 是 JavaScript/TypeScript 的异步容器类型。Promise<GatewayServer> 表示这个函数不直接返回GatewayServer 对象,而是返回一个"承诺"——异步操作完成后会给你一个 GatewayServer。调用方需要 await 或 .then() 才能拿到实际值。
// 调用方必须 await,才能拿到实际值。如:
const server: GatewayServer = await startGatewayServer(18789);
在源代码里的签名是:
编辑
L576 — normalizeStateDirEnv(process.env)
读取线程里的环境变量,用来设置启动时默认路径下的环境变量,规范化 STATE_DIR / OPENCLAW_STATE_DIR 等路径相关的环境变量,确保后续代码读取到的路径是标准化过的。
L577-589 — 数据库包导入
import 数据库相关的包,并行导入了三个模块:
openclaw-database-preflight.js(数据库预检)
openclaw-agent-db.js(agent 数据库)
openclaw-state-db.js(状态数据库)
L590-596 — 数据库 schema 预检
预检openclaw启动相关的数据库schema,preflightOpenClawDatabaseSchemas用实际运行环境变量和两个数据库支持的 schema 版本来做预检。
L597-610 — 不兼容 schema 抛异常
如果数据库schema里有不兼容的,把所有不兼容的schema记录异常日志,抛出OpenClawDatabaseSchemaPreflightError。
L611-618 — 不确定的 schema
如果有不确定的schema,提示,无法进入数据库中进行检测,仍然使用这个真实的连接继续;对databaseSchemas.indeterminate 只打 warn 日志,不阻断启动。
L618-619 — 网络栈初始化
初始化 gateway 的网络运行时
L622-623 — 最小测试 Gateway
是否需要进行gateway最小测试,如果是测试运行环境,且OPENCLAW_TEST_MINIMAL_GATEWAY=1时,进行最小测试,否则不进行;
L635-642 — 重启日志跟踪恢复
编辑
先尝试从环境变量恢复重启 trace,如果 resumeGatewayRestartTraceFromEnv 返回 false(表示环境变量中找不到恢复信息),再 fallback 到 handoff 文件。如果从 env 恢复失败,才走 handoff
L643 — 启动性能打点
启动性能打点器;
L644-660 — 懒加载链路
懒加载配置模块-> 懒加载启动插件模块 -> await 配置模块(此时才真正加载)
-> 启动前加载环境变量 -> 启动配置文件加载,读取配置文件快照 ;
顺序如下:
编辑
L662 — auth 参数结构化复制
如果参数中有认证的参数,就把这些参数复制一份,结构化,用来重写认证参数。structuredClone做深拷贝,防止意外修改原始参数。
L666-675 — Control UI Seed
如果需要进行gateway最小测试,读取配置文件快照,seededAllowedOrigins参数值设为false。否则,把配置文件快照、配置参数、运行时的参数(绑定 的ip,port)传给maybeSeedControlUiAllowedOriginsAtStartup这个方法,这个方法的作用是,建一个种子;
minimalTestGateway为 true 时直接跳过 seed,seededAllowedOrigins 设为 false;否则调用 maybeSeedControlUiAllowedOriginsAtStartup 真实创建 seed。
L676-682 — startupConfigSnapshot 合并
如果种子允许初始化,那么startupConfigSnapshot的值就包含配置文件快照、种子的配置参数,否则只包含配置文件快照;seed 成功后,用 seed 产出的 config 覆盖快照中的 runtimeConfig 和 config。
L684-693 — emitSecretsStateEvent
把加密事件对象放入消息队列中,加密事件对象包含有:code, message, sessionKey, contextKey;闭包函数,封装了code、message、sessionKey、contextKey,调用 enqueueSystemEvent 放入消息队列。
L694 — 「真正启动配置文件模块」
L694,真正启动配置文件模块;你说的是createRuntimeSecretsActivator 的调用。严格来说这不是"启动配置文件模块",而是创建运行时 secrets 激活器——用于激活加密凭据。配置模块在 L644 已经 await 加载过了。
L695-702 — 创建 secrets 激活器
创建运行时 secrets 激活器,用于激活加密凭据。createRuntimeSecretsActivator接收日志、状态事件发射器、channel 抑制参数等,返回 activateRuntimeSecrets 函数(此时只是创建,还未调用)。
L709-721 — 认证准备
认证服务启动。传入快照、auth/tailscale 覆盖参数、secrets 激活器、日志、measure 等。
L712-718,认证准备。
需要准备:配置文件快照、启动之后认证参数会被覆盖、tailscaleOverride、激活运行时加密、日志、measure对象;传入快照、auth/tailscale 覆盖参数、secrets 激活器、日志、measure 等。
L727-749 — resolvedStartupAuthOverride 过滤
如果认证参数需要重写,把实体用来做网关实体认证GatewayAuthConfig,实体是几组key-value对,key包括:mode, token, password, allowTailscale, rateLimite, trustedProxy,用这些key的值来进行认证。同时对每个key进行处理,根据startupAuthOverride[key], key的值,isSecretRef(), 这几个参数值、函数来过滤认证不通过的key-value。如果K-V认证通过,认证value,如果value也认证通过,把value的值复制一份,结构化之后作为gateway的配置参数;核心逻辑:
遍历 ["mode", "token", "password", "allowTailscale", "rateLimit", "trustedProxy"]
跳过 undefined 值
跳过 token/password 中值为 SecretRef 的情况(secret ref 单独处理)
通过的 key-value 用 structuredClone 深拷贝后组装进 resolvedStartupAuthOverride
L750-759 — startupAuthSecretRefOverride
通过token和password来认证。。专门处理 token 和 password 的 isSecretRef 情况,将它们分离到 startupAuthSecretRefOverride,后面会走 secret 解密链路。
L760-762 — 合并 generatedToken
如果认证服务生成了token,就把生成的token和resolvedStartupAuthOverride(L727)的配置合并。否则就只用resolvedStartupAuthOverride,来重加载并覆盖认证配置信息;有动态生成的 token 就合并进去,否则直接用过滤后的覆盖配置。
L763-770 — 诊断开关
是否开启诊断。isDiagnosticsEnabled(cfgAtStart)判断是否开启,开启则调 startDiagnosticHeartbeat。
L771 — 重启策略
设置gateway重启策略;
L773-782 — 重启前检查
重启前检查(队列/连接/任务)检查总队列数+总pending回复数+活跃的嵌入式 run
+活跃的定时任务数+活跃的exec会话数+活跃的gateway工作数+活跃的task数(初始是0);
编辑
L783-785 — seededControlUiAllowedOrigins
ui control的种子是否允许初始化;这是一个只读取值,如果 seed 成功了,取出 allowedOrigins;否则为undefined。这不是"设置"而是"读取"。
L786-823 — applyFixedGatewayOverlays
设置网关认证配置参数。函数将reloadAuthOverride、startupTailscaleOverride 和 seededControlUiAllowedOrigins 作为固定覆盖层 merge 到运行时 config 中:
夜雨聆风