Traefik ACME 证书解析器配置完全指南:自动签发、三大 Challenge 与 Let‘s Encrypt 实战 Traefik ACME 证书解析器配置完全指南自动签发、三大 Challenge 与 Lets Encrypt 实战【免费下载链接】traefikThe Cloud Native Application Proxy项目地址: https://gitcode.com/GitHub_Trending/tr/traefik本篇指南围绕 TraefikThe Cloud Native Application Proxy静态配置中的certificatesResolvers模块展开系统讲解如何基于 ACMEAutomatic Certificate Management Environment自动证书管理环境协议对接 Lets Encrypt 等 CA实现 TLS 证书的自动申请与自动续期。你将掌握最小可用配置的四种写法File YAML/TOML、CLI、Helm、全部配置项的含义与默认值、DNS-01 / HTTP-01 / TLS-ALPN-01 三种挑战Challenge方式的适用场景与配置方法以及通配符域名、External Account Binding外部账户绑定、Kubernetes 环境下的多实例注意事项等实战要点。ACME 证书解析器在 Traefik 中的位置Traefik 将「证书申请与续期」的能力建模为证书解析器Certificate Resolver在静态配置中以certificatesResolvers为根字段声明每个 resolver 独立命名、独立工作。在本仓库的源码中静态配置结构体定义于 pkg/config/static/static_config.goConfiguration包含CertificatesResolvers map[string]CertificateResolver即一个静态配置中可同时声明多个不同名称的证书解析器而 ACME 类型的解析器其全部字段定义在 pkg/provider/acme/provider.go 的Configuration结构体中。ACME 解析器的核心工作方式是Traefik 不再需要手工准备并部署证书而是由路由规则Router在匹配到域名后自动向 ACME 服务器申请覆盖该域名的证书在证书到期前 Traefik 又会自动续期。整个逻辑的实现主体是internal/pkg/provider/acme目录本仓库对应 pkg/provider/acme内部依托 ACME 客户端库 lego 完成与 CA 服务器的注册、挑战和签发交互。最小可用配置一种能力四种写法一个完整的 ACME 配置通常需要两样前提暴露:80供 HTTP-01 使用与:443HTTPS 流量的入口点EntryPoint以及一个名为acme的 resolver 子配置块。官方参考文档位于 docs/content/reference/install-configuration/tls/certificate-resolvers/acme.md以下四种形态语义完全等价。File (YAML)entryPoints: web: address: :80 websecure: address: :443 certificatesResolvers: myresolver: acme: email: your-emailexample.com storage: acme.json httpChallenge: # used during the challenge entryPoint: webFile (TOML)[entryPoints] [entryPoints.web] address :80 [entryPoints.websecure] address :443 [certificatesResolvers.myresolver.acme] email your-emailexample.com storage acme.json [certificatesResolvers.myresolver.acme.httpChallenge] # used during the challenge entryPoint webCLI 参数--entryPoints.web.address:80 --entryPoints.websecure.address:443 # ... --certificatesresolvers.myresolver.acme.emailyour-emailexample.com --certificatesresolvers.myresolver.acme.storageacme.json # used during the challenge --certificatesresolvers.myresolver.acme.httpchallenge.entrypointwebHelm Chart Values# Traefik entryPoints configuration for HTTP and HTTPS. entryPoints: web: address: :80 websecure: address: :443 certificatesResolvers: myresolver: acme: email: your-emailexample.com storage: /data/acme.json # Path to store the certificate information. httpChallenge: # Entry point to use during the ACME HTTP-01 challenge. entryPoint: web需要澄清的是解析器名myresolver只是演示用名称可自由命名真正关键的是其后紧接的acme类型标识。路由Router随后通过其 TLS 配置如tls.certResolver: myresolver指名要使用哪一个解析器Traefik 便会依据该路由匹配到的域名发起证书申请见下文「域名推导」一节。仓库的样例静态配置 traefik.sample.yml 与 traefik.sample.toml 也包含完整的certificatesResolvers区块供直接参考修改集成测试场景则可见 integration/fixtures/acme 下的大量配置样例如acme_base.toml、acme_domains.toml、acme_multiple_resolvers.toml。配置项全解析下表完整列出了 ACME 证书解析器certificatesResolvers.名称.acme下的全部配置项。标注为 Yes 的为必填项未标注的均带默认值字段说明默认值必填acme.email注册 ACME 账户时使用的邮箱地址。是acme.caServer使用的 CA 服务器地址。https://acme-v02.api.letsencrypt.org/directory否acme.preferredChain首选证书链。若 CA 提供多条证书链优先选用 issuer 匹配该 Subject Common Name 的链无匹配时使用默认提供的链。否acme.keyType证书私钥类型。RSA4096否acme.disableCommonName是否在 CSR 中禁用 Common Name。false否acme.profile使用的证书 profile。否acme.caCertificatesPEM 编码的 CA 证书路径列表用于认证「其 HTTPS 证书并非由系统级可信根列表签发」的 ACME 服务器。[]否acme.caSystemCertPool证书池是否使用系统证书池的副本。false否acme.caServerName认证自定义 ACME 服务器时可指定的 CA 服务器名。否acme.emailAddressesCSR 中要使用的邮箱地址列表。[]否acme.eab是否启用 External Account Binding外部账户绑定。-否acme.eab.kid外部 CA 提供的 Key identifier。否acme.eab.hmacEncoded外部 CA 提供的 HMAC 密钥需为 Base64 URL 编码且无填充的格式。否acme.certificatesDuration证书时长小时专门用于决定续期时间点。2160即 90 天否acme.clientTimeout与 ACME 服务器通信所用 HTTP Client 的超时时间。2m否acme.clientResponseHeaderTimeout与 ACME 服务器通信所用 HTTP Client 的响应头超时时间。30s否acme.certificateTimeoutfinalization最终签发请求中获取证书的超时时间当 ACME 服务器签发缓慢时可调大。30s否acme.dnsChallenge启用 DNS-01 挑战。详见下文 dnsChallenge 章节。-否acme.dnsChallenge.provider使用的 DNS 服务商。否acme.dnsChallenge.resolvers用于解析 FQDN 权威服务器的 DNS 服务器列表。[]否acme.dnsChallenge.propagation.delayBeforeChecks默认 provider 会先验证 TXT DNS 挑战记录再交给 ACME 验证若该值大于零则此检查会延迟所配置的秒数。内网屏蔽外部 DNS 查询时很有用。0s否acme.dnsChallenge.propagation.disableChecks在通知 ACME 挑战就绪前禁用 TXT 记录传播检查。注意禁用检查可能导致挑战失败。false否acme.dnsChallenge.propagation.requireAllRNS要求 TXT 挑战记录已传播到所有递归名称服务器。若已禁用权威服务器检查disableANSChecks建议改为检查所有递归服务器。false否acme.dnsChallenge.propagation.disableANSChecks禁用针对权威名称服务器的 TXT 传播检查将跳过对权威SOA名称服务器的传播检查。仅当权威服务器不可达时才应使用。false否acme.httpChallenge启用 HTTP-01 挑战。详见下文 httpChallenge 章节。-否acme.httpChallenge.entryPoint用于 HTTP-01 挑战的入口点必须能被 Lets Encrypt 通过 80 端口访问到。是acme.httpChallenge.delay挑战创建与验证之间的延迟小于等于零表示无延迟。0否acme.tlsChallenge启用 TLS-ALPN-01 挑战。Traefik 必须能被 Lets Encrypt 通过 443 端口访问到。详见下文 tlsChallenge 章节。-否acme.tlsChallenge.delay挑战创建与验证之间的延迟小于等于零表示无延迟。0否acme.storage证书存储用的文件路径。acme.json是关键默认值的源码依据上表多列默认值并非凭空而来而是定义在 ACME provider 的SetDefaults方法中见 pkg/provider/acme/provider.gocaServer默认为 lego 常量lego.DirectoryURLLetsEncrypt即 Lets Encrypt 生产环境的 ACME v2 目录https://acme-v02.api.letsencrypt.org/directorystorage默认为acme.jsonkeyType默认为RSA4096从源码的注释可见其允许取值还包括EC256、EC384、RSA2048、RSA8192certificatesDuration默认为3 * 30 * 24小时即 90 天clientTimeout默认2mclientResponseHeaderTimeout与certificateTimeout默认30s。同时Init()方法pkg/provider/acme/provider.go对配置做了运行时校验storage为空、certificatesDuration小于 1 小时、clientTimeout小于clientResponseHeaderTimeout时都会直接报错退出这解释了为什么email与storage会被标注为必填——它们是 ACME 账户注册与证书落盘的前提。自定义 CA 与超时字段的底层实现当配置了caCertificates/caServerName时Traefik 会通过lego.CreateCertPool构建包含自定义根证书的证书池并构建带RootCAs与ServerName的tls.Config见 pkg/provider/acme/provider.go。若没有配置这些字段Traefik 会回退读取LEGO_CA_SYSTEM_CERT_POOL、LEGO_CA_CERTIFICATES、LEGO_CA_SERVER_NAME环境变量与 lego 保持兼容。而clientTimeout、clientResponseHeaderTimeout分别映射到 HTTP Client 的整体Timeout与传输层的ResponseHeaderTimeoutcertificateTimeout则写入 lego 客户端配置的config.Certificate.Timeoutpkg/provider/acme/provider.go。自动续期机制与证书时长控制Traefik 会自动跟踪其签发的每张证书的到期时间。默认情况下 Traefik 管理的是 90 天有效期的证书并在证书到期前30 天开始续期。若你使用的证书解析器签发的是自定义时长的证书则可通过certificatesDuration单位小时来调整这一节奏。值得注意的是Traefik 目前不会检查某张证书是否仍在被使用——即使某证书已不再被任何路由引用它仍可能被续期官方文档也以 note 形式特别提示了这一点。源码级续期节奏其实是分档的从源码getCertificateRenewDurationspkg/provider/acme/provider.go可以看到续期策略并非简单「提前 30 天」而是依据certificatesDuration时长自动分档证书时长certificatesDuration提前续期窗口RenewPeriod续期检查间隔RenewInterval≥ 365 天1 年4 个月1 周≥ 90 天30 天1 天≥ 30 天10 天12 小时≥ 6 天2 天2 小时≥ 1 天6 小时10 分钟其余20 分钟1 分钟在 pkg/provider/acme/provider.go 的Provide方法中Traefik 先按该续期窗口执行一次renewCertificates随后启动一个周期为renewInterval的定时器循环执行续期检查直至进程退出。对应的单元测试见Test_getCertificateRenewDurationspkg/provider/acme/provider_test.go。证书与账户的持久化storage指向的文件默认acme.json是整个 ACME 体系的「状态文件」负责持久化账户注册信息与已签发证书。源码层面对应Store接口的GetAccount、SaveAccount、GetCertificates、SaveCertificates等方法见 pkg/provider/acme/store.go文件型实现见 pkg/provider/acme/local_store.go。正因证书会落盘持久化配置在容器场景下必须为其配置持久卷Helm 示例中即写作/data/acme.json否则每次重建都会重新走签发流程。另外Init()中还有一个细节若检测到已存账户的注册 URI 与当前caServer的主机名不一致例如从 Lets Encrypt 切换到其他 CATraefik 会提示 Account URI does not match the current CAServer 并重置账户以保证注册信息与当前 CA 对齐pkg/provider/acme/provider.go。三种 ACME 挑战方式ChallengeACME 协议要求证明「你确实拥有该域名」这一证明过程即「挑战」。Traefik 支持三种挑战方式只能三选一同一 resolver 内同时配置多个会被视为配置不当且选型会直接影响你能签出的证书类型与所需的网络拓扑。dnsChallenge基于 DNS 记录验证DNS-01 挑战通过在域名下写入一条_acme-challengeTXT 记录来证明域名所有权适合需要签发通配符证书、或 80/443 端口无法对外暴露的场景。certificatesResolvers: myresolver: acme: # ... dnsChallenge: provider: cloudflare # 你使用的 DNS 服务商 resolvers: - 1.1.1.1:53 - 8.8.8.8:53 propagation: delayBeforeChecks: 5sTraefik 内部通过 lego 对接 ACME 协议因此所支持的 DNS 服务商列表与各服务商所需设置的环境变量均以 lego 的 DNS 服务商文档为准配置provider名即可环境变量用于存放各服务商的 API 凭据。CNAME 与多账户技巧CNAME 记录是被支持、甚至被鼓励的用法。若个别场景需要关闭 CNAME 支持可设置如下环境变量LEGO_DISABLE_CNAME_SUPPORTtrue当你有多个域名分属不同 DNS 账户例如example.org属于账户 fooexample.com属于账户 bar而 Traefik 一次只能配置一个 DNS 挑战 provider 时可以通过 CNAME 把挑战委托出去为example.org创建一条名为_acme-challenge.example.org、指向challenge.example.com的 CNAME这样就能用 bar 账户为example.org签发证书。传播检查相关参数默认provider会在通知 ACME 验证之前先自行校验 TXT 记录是否已生效。官方文档与实现都提示过几个相关调优点对应源码中 pkg/provider/acme/provider.go 的Propagation结构体propagation.delayBeforeChecks延迟单位秒执行预检查当内部网络屏蔽了外部 DNS 查询时特别有用值必须大于 0propagation.disableChecks完全跳过传播检查再通知 ACME「挑战就绪」——注意禁用检查可能直接导致挑战失败不推荐propagation.disableANSChecks仅跳过针对权威SOA名称服务器的传播检查适用于权威服务器不可达的场景propagation.requireAllRNS要求 TXT 记录已传播到所有递归名称服务器若已关闭权威服务器检查建议开启此项改查递归服务器。dnsChallenge.resolvers则用于指定 Traefik 在解析权威服务器时使用的自定义 DNS 服务器支持带端口写法源码中会构造一个使用这些递归名称服务器的dns01客户端pkg/provider/acme/provider.go。此外从配置结构体可见delayBeforeCheck与disablePropagationCheck两个顶层字段已被标记为 Deprecatedpkg/provider/acme/provider.go新配置请统一使用propagation下的对应字段。tlsChallenge基于 TLS-ALPN-01 扩展验证TLS-ALPN-01 挑战要求 Traefik 通过443 端口对 Lets Encrypt 可达CA 会向该端口发起 TLS 握手并通过 ALPN 协议扩展名acme-tls/1完成验证。certificatesResolvers: myresolver: acme: # ... tlsChallenge: {}TOML 写法[certificatesResolvers.myresolver.acme] # ... [certificatesResolvers.myresolver.acme.tlsChallenge]CLI 写法# ... --certificatesresolvers.myresolver.acme.tlschallengetruehttpChallenge基于 HTTP 资源验证HTTP-01 挑战要求 Lets Encrypt 通过80 端口访问 Traefik 上的一个 well-known 路径/.well-known/acme-challenge/...。此时必须把httpchallenge.entrypoint指向监听 80 端口的入口点且该入口点必须能从公网直接访问不能被防火墙挡掉。entryPoints: web: address: :80 websecure: address: :443 certificatesResolvers: myresolver: acme: # ... httpChallenge: entryPoint: webTOML 写法[entryPoints] [entryPoints.web] address :80 [entryPoints.websecure] address :443 [certificatesResolvers.myresolver.acme] # ... [certificatesResolvers.myresolver.acme.httpChallenge] entryPoint webCLI 写法--entryPoints.web.address:80 --entryPoints.websecure.address:443 # ... --certificatesresolvers.myresolver.acme.httpchallenge.entrypointweb需要特别说明的是HTTP 到 HTTPS 的重定向与 HTTP-01 挑战完全兼容——Traefik 在挑战期间会直接在本机应答 well-known 路径的请求不会因路由层面配置了 80→443 重定向而影响验证。httpChallenge.delay则与tlsChallenge.delay一样用于控制「创建挑战」到「开始验证」之间的等待时长源码中分别通过http01.SetDelay与tlsalpn01.SetDelay注入pkg/provider/acme/provider.go。域名推导规则与通配符证书证书解析器并不是「盲签」它会依据路由推断需要签发证书的域名集合规则如下若路由如 Kubernetes IngressRoute设置了tls.domains选项则解析器取tls.domains中main字段指定的域名作为主域名否则解析器从路由 rule 中的任意Host()或HostSNI()匹配器推导域名。你可以为每个主域名main配置多个 SAN备用域名即sans列表域名集合确定后每个域名与每个 SAN 都会触发一次独立的证书签发请求且每个域名都必须有指向 Traefik 的 A/AAAA 记录。在动态配置层面证书的申请链路由路由的tls.certResolver与tls.domains联动触发具体可进一步参考路由配置文档目录下的 TLS 相关说明如 docs/content/reference/routing-configuration/http/tls 下各页面。源码侧存在域名去重与收敛逻辑deleteUnnecessaryDomainspkg/provider/acme/provider.go重复出现的域名只会被处理一次已被某个通配符域名覆盖的域名也不会重复签发源码会打印 Warn 日志说明原因。通配符Wildcard域名的限制ACME v2 支持通配符证书但有两个硬性约束必须知晓通配符证书只能通过 DNS-01 挑战签发——因为通配符域名无法通过 HTTP-01 / TLS-ALPN-01 完成所有权证明无法签发双通配符证书例如*.*.local.com是不允许的。最常用的场景是「根域名 通配符子域」同时申请example.com与*.example.com此时根域名要作为 SAN 一并写入因此会触发2 次 DNS-01 挑战两个域名生成的 TXT 记录内容恰好相同这在 DNS RFC 上合规但所有 DNS 服务商都会按 TTL 缓存记录若 TTL 大于挑战超时时间可能导致第二次挑战失败。Traefik 使用的 ACME 客户端库 lego 对部分而非全部DNS 服务商做了该问题的规避其官方文档的 provider 支持表格中标明了各家是否支持「通配符与其根域名同时签发」配置前建议先核对。External Account BindingEAB外部账户绑定部分 CA如某些面向企业的 ACME 服务、ZeroSSL 等要求账户注册时携带 EAB 凭据。启用方式是在acme块下配置eab包含两个字段kid外部 CA 下发的 Key identifierhmacEncoded外部 CA 下发的 HMAC 密钥必须是Base64 URL 编码且无填充的格式。certificatesResolvers: myresolver: acme: # ... eab: kid: abc-keyID-xyz hmacEncoded: abc-hmac-xyzTOML 写法[certificatesResolvers.myresolver.acme] # ... [certificatesResolvers.myresolver.acme.eab] kid abc-keyID-xyz hmacEncoded abc-hmac-xyzCLI 写法# ... --certificatesresolvers.myresolver.acme.eab.kidabc-keyID-xyz --certificatesresolvers.myresolver.acme.eab.hmacencodedabc-hmac-xyz在源码层面对应EAB结构体pkg/provider/acme/provider.go其字段带有loggable:false标记意味着这两项敏感信息会被日志脱敏不会明文打印注册时若检测到EAB配置Traefik 会以TermsOfServiceAgreed: true并携带 kid/HMAC 调用RegisterWithExternalAccountBinding完成带 EAB 的账户注册pkg/provider/acme/provider.go。在 Kubernetes 中使用 Lets Encrypt 的注意事项Traefik 是无状态应用——它只从运行环境派生配置因此正常情况下可以多实例并行以获得高可用这也是 Kubernetes 生态中的常见模式。但当引入 Lets Encrypt 后情况发生了变化。单实例使用 Traefik Proxy Lets Encrypt 没有任何问题但单实例本身是单点故障。多实例≥2同时开启 Lets Encrypt 则不可行因为 ACME 挑战请求与后续响应无法保证落到同一个 Traefik 实例上。早期 v1.x 曾借助 KV store 尝试实现多实例协调但由于性能不理想该特性在 v2.0 起已被移除。因此官方给出的两个 Kubernetes 提供商的文档中都包含相关注意章节多实例部署前务必阅读 Kubernetes Ingress Provider 与 Kubernetes CRD Provider 两页若你在 Kubernetes 中需要Lets Encrypt 的高可用官方推荐的两条路线为使用具备分布式 Lets Encrypt 能力的企业版方案或继续使用 Traefik Proxy但引入证书控制器例如 Cert-Manager来统一管理证书——Cert-Manager 会把签出的证书写入命名空间内的 Secret供 ingress 对象的 TLS 配置以 Secret 方式引用。Lets Encrypt 不可达时的回退行为Fallback网络故障、CA 服务不可达等情况在实际运维中无法完全避免。官方文档明确给出当 Lets Encrypt 不可达时Traefik 对证书的选择顺序之前已生成的 ACME 证书指宕机前签发的证书已过期的 ACME 证书用户手工提供的证书。同时有一个重要提醒对于新增的子域名如果其首次申请恰逢 Lets Encrypt 不可达那么在 Traefik 重启之前该域名将一直使用 Traefik 内置的默认自签证书提供服务——换言之新域名的正式证书要等到 Traefik 重启并成功完成签发后才生效。写在最后从解析器到一条完整链路把以上所有模块串起来一次「自动 HTTPS」的完整链路是静态配置声明certificatesResolvers含某一种挑战方式与storage→ 动态路由在匹配到Host()/HostSNI()或tls.domains后引用该 resolver → Traefik 首次为新域名发起注册与挑战验证 → 挑战成功则签发证书并写入storage文件 → Traefik 依据certificatesDuration推算的续期窗口在后台定期检查并自动续期 → 网络抖动导致 CA 不可达时按「历史证书 → 过期证书 → 手工证书」的顺序回退兜底。理解这条链路便能从配置层面从容应对证书签发失败、通配符申请、多实例 HA 与自定义 CA 等几乎所有生产场景。【免费下载链接】traefikThe Cloud Native Application Proxy项目地址: https://gitcode.com/GitHub_Trending/tr/traefik创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考