Caddy 的配置系统是管理 Caddy 如何加载、存储、验证和应用配置的核心机制。该系统是 Caddy 运行时行为的基础,它支持在不重启的情况下动态更改配置,并实现了配置表示与操作功能之间的清晰分离。
有关与此配置系统交互的 Admin API 的信息,请参阅 Admin API。
Caddy 的配置系统围绕基于 JSON 的 Config 结构体构建,该结构体管理着整个服务器的生命周期。该系统通过适配器支持多种输入格式,其中 Caddyfile 是最常见的人类可读格式,会被转换为 JSON。
核心配置函数
Load() - 加载并应用带有安全检查的配置Run() - 直接运行配置,不进行加载验证changeConfig() - 通过 Admin API 处理运行时配置更新unsyncedDecodeAndRun() - 低级别配置加载来源: caddy.go68-92 caddy.go100-140 caddyconfig/httpcaddyfile/httptype.go57-87
Caddy 配置的根基是 Config 结构体。该结构体充当了定义 Caddy 如何运行的所有配置元素的层级容器。
Config 结构体字段有特定用途
| 字段 | 类型 | 目的 |
|---|---|---|
管理员 | *AdminConfig | Admin API 端点配置 |
日志记录 | *Logging | 全局日志设置 |
StorageRaw | json.RawMessage | 存储模块配置(证书等) |
AppsRaw | ModuleMap | 应用程序配置的原始 JSON |
apps | map[string]App | 运行时应用程序实例 |
storage | certmagic.Storage | 已提供的存储实现 |
cancelFunc | context.CancelFunc | 配置生命周期的清理函数 |
AppsRaw 字段包含在 provision 过程中加载到 apps 字段的模块配置。每个应用程序提供特定的服务,如 HTTP 处理或 TLS 管理。
来源: caddy.go68-92 admin.go63-118 modules.go122-128
当加载新配置时,Caddy 会遵循一系列步骤,从当前配置安全地过渡到新配置。此过程可确保配置的正确性,并最大程度地减少对运行中服务的影响。
配置加载遵循以下函数调用
StrictUnmarshalJSON(): 将 JSON 解析到带有验证的 Config 结构体NewContext(): 创建模块生命周期管理上下文LoadModule(): 使用反射从 AppsRaw 加载每个模块Provision() 然后 Validate()App.Start(): 启动每个已提供的应用程序unsyncedStop(): 清理旧的配置来源: caddy.go100-140 caddy.go318-384 caddy.go400-453 caddy.go460-556
配置系统与 Caddy 的模块系统紧密集成。当加载配置时,每个模块都会经历一个准备使用其生命周期。
在 Context.LoadModuleByID() 中的模块加载过程
GetModule(moduleName): 从全局注册表中查找 ModuleInfomodInfo.New(): 使用构造函数创建新实例StrictUnmarshalJSON(): 将配置解组到模块实例Provision(ctx): 授予模块访问资源和其他模块的权限Validate(): 检查配置的正确性ctx.moduleInstances 以进行清理跟踪模块生命周期接口
Provisioner: 设置阶段,可以访问 ContextValidator: 配置验证阶段CleanerUpper: 上下文取消时的清理来源: context.go345-413 modules.go288-316 caddy.go460-556
Caddy 提供两种主要方式来访问和修改配置
当请求配置更改时,Caddy 会遵循此流程
如果新配置与当前配置相同,Caddy 将避免重新加载的开销。否则,它将尝试加载新配置,同时保留旧配置以防失败。
来源: caddy.go142-262 admin.go217-281
虽然 Caddy 的原生配置格式是 JSON,但它通过适配器支持其他格式。最常见的适配器是 Caddyfile 格式,它提供了更友好的语法。
在 ServerType.Setup() 中的 Caddyfile 适配器过程
caddyfile.ServerBlock parsing: 将令牌解析为服务器块结构registeredDirectives 映射调用已注册的指令函数buildTLSApp(): 从 TLS 指令构建 TLS 应用程序配置buildPKIApp(): 构建 PKI 应用程序配置caddyhttp.Server 实例AppsRaw 填充后转换为 caddy.Config主要功能
ServerType.Setup(): 主要的 Caddyfile 适配入口点RegisterDirective(): 注册指令解析函数Helper.NewRoute(): 从指令结果创建 HTTP 路由buildSubroute(): 将多个指令合并为路由处理器来源: caddyconfig/httpcaddyfile/httptype.go57-363 caddyconfig/httpcaddyfile/directives.go109-138 caddyconfig/httpcaddyfile/directives.go276-302
Caddy 可以将配置自动持久化到磁盘。这确保了如果 Caddy 重新启动,它可以恢复其上次运行的配置。
持久化机制
persist_config 选项禁用来源: caddy.go359-381
配置系统支持影响Caddy整体行为的全局选项。这些选项可以在Caddyfile的全局选项块中设置,也可以直接在JSON配置中设置。
全局选项通过ServerType.evaluateGlobalOptionsBlock()进行处理,并通过RegisterGlobalOption()进行注册。可用选项
| 选项 | 解析函数 | 目的 |
|---|---|---|
debug | parseOptTrue | 启用调试日志 |
http_port | parseOptHTTPPort | 默认HTTP端口 |
https_port | parseOptHTTPSPort | 默认HTTPS端口 |
storage | parseOptStorage | 存储模块配置 |
admin | parseOptAdmin | Admin API设置 |
auto_https | parseOptAutoHTTPS | 自动HTTPS行为 |
log | parseLogOptions | 全局日志配置 |
order | parseOptOrder | 指令执行顺序 |
全局选项存储在options映射中,并在ServerType.Setup()期间使用,以配置生成的caddy.Config结构。
来源: caddyconfig/httpcaddyfile/options.go32-68 caddyconfig/httpcaddyfile/httptype.go369-453
Caddy提供了多种加载配置的方式
Run()或Load()并传入配置动态配置加载机制允许Caddy定期从外部源拉取配置,从而实现基础设施即代码和集中式配置管理场景。
来源: caddy.go100-140 caddy.go586-652
Caddy的配置系统为管理服务器配置提供了一个强大的基础。其主要特点包括:
该系统实现了Caddy在运行时无需中断即可重新配置自身的能力,使其在生产部署中兼具灵活性和可靠性。