lego 高级配置指南七大 LEGO_ 环境变量详解CA 证书信任、CNAME、调试日志【免费下载链接】legoLets Encrypt/ACME client and library written in Go项目地址: https://gitcode.com/gh_mirrors/le/lego导读lego 是使用 Go 编写的 Lets Encrypt/ACME 客户端与库。除了命令行参数与配置文件外lego 还提供一组以LEGO_为前缀的环境变量用于调整 TLS 证书信任链、DNS-01 挑战中的 CNAME 跟随行为以及各层 HTTP 客户端的调试输出。本文以官方文档 docs/content/advanced/options.md 为主体结合仓库源码逐项剖析这 7 个变量的作用原理、生效时机与适用场景。读完本文你将掌握如何让 lego 信任私有 ACME 服务器证书如 Pebble 测试环境、如何关闭 CNAME 跟随以及如何在排查故障时安全地开启分级调试日志。环境变量总览环境变量作用域核心作用LEGO_CA_CERTIFICATESCA 客户端指定 PEM 格式的 CA 证书路径用于信任非系统根证书签发的 ACME 服务器LEGO_CA_SYSTEM_CERT_POOLCA 客户端是否在自定义证书池基础上合并系统证书池副本LEGO_CA_SERVER_NAMECA 客户端指定用于 TLS ServerName 校验的 CA 服务器名LEGO_DISABLE_CNAME_SUPPORTDNS-01 挑战禁用 dns-01 挑战中的 CNAME 跟随LEGO_DEBUG_CLIENT_VERBOSE_ERRORDNS 客户端在错误信息中附加请求方法Method与 URLLEGO_DEBUG_DNS_API_HTTP_CLIENTDNS 客户端在日志中完整转储 DNS 提供方 API 的请求与响应含脱敏LEGO_DEBUG_ACME_HTTP_CLIENTACME 客户端开启到 ACME 服务器调用的重试日志与调试输出这些变量均通过os.Getenv/os.LookupEnv在程序启动、创建客户端时读取因此必须在 lego 进程启动前设置或在以库形式使用时于NewClient之前设置运行中修改不会生效。一、自定义 CA 证书信任LEGO_CA_CERTIFICATES用途与原理LEGO_CA_CERTIFICATES用于指定一个或多个 PEM 编码 CA 证书文件的路径。当 ACME 服务器的 HTTPS 证书不是由系统信任根列表中的 CA 签发时例如自建 ACME 服务器、内网 CA、或 Pebble 测试环境lego 会使用这里提供的证书来认证 ACME 服务器从而避免 TLS 校验失败。多个文件路径以路径分隔符连接Unix/Linux/macOS 使用:Windows 使用;# Unix 系统 LEGO_CA_CERTIFICATES/foo/cert1.pem:/foo/cert2.pem源码级实现在 lego/client_config.go 中定义了变量名常量initCertPool函数lego/client_config.go负责读取并构建证书池若LEGO_CA_CERTIFICATES未设置initCertPool直接返回nilHTTP 客户端使用系统默认的 TLS 校验行为设置后按os.PathListSeparator拆分路径列表逐个os.ReadFile读取并用certPool.AppendCertsFromPEM解析任一文件读取或解析失败都会panic提示create certificates pool: ...以便尽早暴露配置错误构建出的*x509.CertPool被注入到默认 HTTP 客户端的tls.Config.RootCAs见 createDefaultHTTPClient该客户端是 lego 与 ACME 服务器通信的基础。典型应用连接 Pebble 测试服务器仓库的 e2e 测试大量使用该变量指向 Pebble 的迷你 CA 证书。例如 e2e/challenges_test.goLEGO_CA_CERTIFICATES./fixtures/certs/pebble.minica.pem在 e2e/accounts_test.go 中以程序方式设置并随后清理err : os.Setenv(LEGO_CA_CERTIFICATES, ./fixtures/certs/pebble.minica.pem) defer func() { _ os.Unsetenv(LEGO_CA_CERTIFICATES) }()pebble.minica.pem位于 e2e/fixtures/certs/即 Pebble 测试 CA 的根证书。这意味着你完全可以在本地用 Pebble 构建一套完全离线的 ACME 测试环境而无需向真实 CA 发起请求。二、合并系统证书池LEGO_CA_SYSTEM_CERT_POOLLEGO_CA_SYSTEM_CERT_POOL用于决定自定义证书池是否以系统证书池的副本为基础。默认情况下不设置或值为假lego 会通过x509.NewCertPool()创建一个空证书池只信任LEGO_CA_CERTIFICATES指定的证书设置为真值后会先通过x509.SystemCertPool()获取系统证书池副本再追加自定义证书。LEGO_CA_SYSTEM_CERT_POOLtrue源码级实现与注意点参见 initCertPool 与 newCertPool真值解析使用strconv.ParseBool支持1、t、T、TRUE、true、True等真值写法代码注释明确指出LEGO_CA_SYSTEM_CERT_POOL需要LEGO_CA_CERTIFICATES已设置才起作用——因为customCACertsPath 时函数提前返回nilx509.SystemCertPool()失败时例如某些精简容器环境无系统证书目录会回退到空池保证程序不中断。建议如果只是追加信任一个私有 CA同时希望保留对公共 CA如 Lets Encrypt的信任应设置为true如果希望构建仅信任指定证书的“封闭”环境如安全测试保持默认即可。三、指定 CA 服务器名LEGO_CA_SERVER_NAMELEGO_CA_SERVER_NAME用于指定 ACME 服务器 HTTPS 证书校验时的 ServerName。当 ACME 服务器的证书不是由系统信任根签发、且主机名与证书 CN/SAN 不完全匹配时可通过该变量覆盖 TLS 握手时发送的 SNI 与证书校验目标主机名。LEGO_CA_SERVER_NAMEfoo源码级实现在 createDefaultHTTPClient 中该值直接注入TLSClientConfig: tls.Config{ ServerName: os.Getenv(caServerNameEnvVar), RootCAs: initCertPool(), },注意ServerName为空时tls.Config会退化为使用连接对端地址推断 SNI 的默认行为一旦设置则严格以此值进行证书主机名校验。它通常与LEGO_CA_CERTIFICATES配合使用用于内网测试服务器证书主机名与访问地址不一致的场景。四、关闭 DNS-01 的 CNAME 跟随LEGO_DISABLE_CNAME_SUPPORT默认行为默认情况下lego 在 dns-01 挑战中会自动跟随 CNAME当_acme-challenge.example.com以 CNAME 指向其他域时lego 会沿 CNAME 链继续查询并把 TXT 记录写到最终的权威域名下。这一特性常用于 DNS 托管在第三方、需要把验证记录“转发”到另一个域名系统的场景Lets Encrypt 官方也推荐这种做法。设置该变量可关闭此行为LEGO_DISABLE_CNAME_SUPPORTtrue源码级实现在 challenge/dns01/dns_challenge.go 的GetChallengeInfo中ok, _ : strconv.ParseBool(os.Getenv(LEGO_DISABLE_CNAME_SUPPORT)) return ChallengeInfo{ Value: value, FQDN: getChallengeFQDN(ctx, fqdn, false), EffectiveFQDN: getChallengeFQDN(ctx, fqdn, !ok), Prefix: challengeLabel, }FQDN始终是不跟随 CNAME 的原始域名EffectiveFQDN是实际用于创建 TXT 记录的域名默认!ok为真会调用lookupCNAME沿 CNAME 链解析关闭后与FQDN一致。CNAME 跟随的具体实现位于 challenge/dns01/client_cname.go 的lookupCNAME通过循环最多 50 次查询dns.TypeCNAME记录逐跳追踪并打印dns01: Found CNAME entry.日志直到不再有 CNAME 为止防止无限循环。对应测试见 challenge/dns01/dns_challenge_test.go 中的t.Setenv(LEGO_DISABLE_CNAME_SUPPORT, true)。适用场景你的 DNS 提供商 API 无法在 CNAME 目标域上创建记录而希望 lego 直接把 TXT 写到原始域出于安全/合规考虑不希望验证记录被转发到第三方 DNS 系统排查 CNAME 解析导致的“记录已创建但验证失败”类问题可临时开启以对照验证。五、丰富 DNS 客户端错误信息LEGO_DEBUG_CLIENT_VERBOSE_ERRORLEGO_DEBUG_CLIENT_VERBOSE_ERROR用于让部分 DNS 客户端在返回错误时附带更详细的信息在错误消息中追加发起请求的[request: METHOD URL]便于快速定位是哪个 API 调用失败。LEGO_DEBUG_CLIENT_VERBOSE_ERRORtrue源码级实现该变量由 internal/errutils/client.go 中定义并在四类错误中使用strconv.ParseBool(os.Getenv(...))判断ok为真时拼接请求方法与方法HTTPDoErrorunable to communicate with the API server: [request: ...] error: ...client.goReadResponseErrorunable to read response body: [request: ...] [status code: N] error: ...client.goUnmarshalErrorunable to unmarshal response: [request: ...] [status code: N] body: ...client.goUnexpectedStatusCodeErrorunexpected status code: [request: ...] [status code: N] body: ...client.go这些错误类型被各 DNS 提供方客户端复用属于低敏感度的调试选项——仅暴露请求方法与 URL不涉及请求体或凭据可放心在排查网络/认证失败时开启。六、转储 DNS 提供方 API 请求响应LEGO_DEBUG_DNS_API_HTTP_CLIENT⚠️ 警告此选项会在日志中暴露凭据请勿在生产环境或无法确保日志不被第三方/日志采集工具读取的环境中使用⚠️LEGO_DEBUG_DNS_API_HTTP_CLIENT用于调试 lego 与 DNS 提供方 API 之间的 HTTP 交互开启后会把完整的请求与响应转储到标准输出stdout便于核对请求 URL、请求头、请求体与响应内容定位“记录已创建但格式不对”“鉴权失败”“区域 ID 错误”等问题。LEGO_DEBUG_DNS_API_HTTP_CLIENTtrue注意并非所有 DNS 提供方都支持此选项。只有在其实现中调用了clientdebug.Wrap的提供方才支持。从源码检索看abion、allinkl、alwaysdata、anexia、artfiles、arvancloud、auroradns、autodns、axelname、azion、azuredns、beget、binarylane、bindman、bluecat、bluecatv2、bookmyname、bunny、checkdomain等大量提供方均已接入见各providers/dns/name/name.go中的clientdebug.Wrap(...)调用但使用该选项前建议先确认目标提供方实现。源码级实现与脱敏机制核心实现位于 providers/dns/internal/clientdebug/client.goWrapclient.go通过os.LookupEnv(LEGO_DEBUG_DNS_API_HTTP_CLIENT)检测开关并用strconv.ParseBool解析只有为真时才用DumpTransport包装原始 TransportDumpTransport.RoundTripclient.go通过httputil.DumpRequestOut/httputil.DumpResponse抓取完整请求与响应输出[HTTP Request]与[HTTP Response]两个块输出前会经过redact脱敏client.go默认正则会把Authorization、Token、X-Token、Auth-Token、X-Auth-Token、Api-Key、X-Api-Key、X-Api-Secret等敏感请求头的值替换为***提供方还可通过WithEnvKeys/WithValues注册额外的脱敏替换项把对应环境变量的值也替换为***。即便如此官方文档仍明确警告该选项可能暴露凭据——脱敏无法覆盖请求体body中出现的 API Key/Secret例如部分提供方把密钥放在 JSON 请求体中所以务必只在隔离的测试环境使用并确保日志不会被第三方工具采集。七、调试 ACME 服务器调用LEGO_DEBUG_ACME_HTTP_CLIENTLEGO_DEBUG_ACME_HTTP_CLIENT用于调试 lego 与 ACME 服务器之间的通信。它的作用分为两层启用重试日志lego 的 ACME 调用经过hashicorp/go-retryablehttp包装最多重试 5 次默认关闭该库的日志输出设置本变量后会将重试日志接到 lego 默认 logger 上从而在日志中看到每次失败重试的细节。配合 e2e 测试在 e2e/challenges_test.go、e2e/eab/eab_test.go 等测试中均以LEGO_DEBUG_ACME_HTTP_CLIENT1的方式开启用于观察测试中对 Pebble 服务器的调用过程。LEGO_DEBUG_ACME_HTTP_CLIENTtrue源码级实现见 cmd/internal/retryable.go 的NewRetryableClientretryClient : retryablehttp.NewClient() retryClient.RetryMax 5 retryClient.HTTPClient client retryClient.CheckRetry checkRetry retryClient.Logger nil if _, v : os.LookupEnv(LEGO_DEBUG_ACME_HTTP_CLIENT); v { retryClient.Logger log.Default() }注意这里用的是os.LookupEnv的存在性判断只要该环境变量被设置无论值是否为true/1就会启用重试日志。checkRetryretryable.go还负责把 ACME 的BadNonce等错误识别为NonceError并触发 nonce 重试因此开启后日志中的重试记录能直观反映 nonce 过期、5xx 等瞬时故障。与上一个变量的区别LEGO_DEBUG_DNS_API_HTTP_CLIENT转储到 DNS 提供方 API第三方 REST/XML API的请求与响应属于“外联调试”LEGO_DEBUG_ACME_HTTP_CLIENT开启到 ACME 服务器调用的重试日志不转储完整报文属于“ACME 协议层调试”。故障排查时可先开 ACME 层观察挑战流程与 nonce 重试再针对具体 DNS 提供方开启 API 转储核对请求内容。八、实战排查组合使用示例以下组合可用于本地验证 lego 对接一个使用自签/私有 CA 证书的 ACME 测试服务器如 Pebble# 1) 信任测试 CA并保留系统证书池 export LEGO_CA_CERTIFICATES/path/to/pebble.minica.pem export LEGO_CA_SYSTEM_CERT_POOLtrue # 2) 如需覆盖服务器证书的主机名 # export LEGO_CA_SERVER_NAMEmy-acme.local # 3) 关闭 CNAME 跟随按需 # export LEGO_DISABLE_CNAME_SUPPORTtrue # 4) 分级调试先开错误细节再开 API 转储仅测试环境 export LEGO_DEBUG_CLIENT_VERBOSE_ERRORtrue export LEGO_DEBUG_ACME_HTTP_CLIENTtrue # export LEGO_DEBUG_DNS_API_HTTP_CLIENTtrue lego --email testexample.com --domains example.com --dns provider run排查顺序建议先通过LEGO_DEBUG_ACME_HTTP_CLIENT观察挑战是否被受理再通过LEGO_DEBUG_CLIENT_VERBOSE_ERROR获取失败请求的 Method/URL最后在安全环境开启LEGO_DEBUG_DNS_API_HTTP_CLIENT核对发送给 DNS 提供方的报文细节。总结lego 的这 7 个LEGO_环境变量分别覆盖了三个层面信任链配置LEGO_CA_CERTIFICATES、LEGO_CA_SYSTEM_CERT_POOL、LEGO_CA_SERVER_NAME、DNS-01 行为控制LEGO_DISABLE_CNAME_SUPPORT以及分层调试输出LEGO_DEBUG_CLIENT_VERBOSE_ERROR、LEGO_DEBUG_DNS_API_HTTP_CLIENT、LEGO_DEBUG_ACME_HTTP_CLIENT。它们的实现与单元/e2e 测试散见于 lego/client_config.go、challenge/dns01/dns_challenge.go、internal/errutils/client.go、providers/dns/internal/clientdebug/client.go 与 cmd/internal/retryable.go 中。把握这些开关的作用域与生效时机即可在私有 CA、CNAME 委派、网络故障等场景下精准配置 lego并安全地获取诊断信息。【免费下载链接】legoLets Encrypt/ACME client and library written in Go项目地址: https://gitcode.com/gh_mirrors/le/lego创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
