NGINX 原生支持 ACME 协议:ngx_http_acme_module 全面指南

TL;DR
NGINX 推出基于 Rust 的预览模块 ngx_http_acme_module,支持在 NGINX 配置中直接请求、安装与续期 ACME(如 Let’s Encrypt)证书。当前支持 HTTP-01 验证,减少对 Certbot 的依赖,便于自动化 HTTPS 部署与运维。


一、概述:为什么要把 ACME 放进 NGINX 配置层

随着网站 HTTPS 的普及,证书管理已成为运维的基础技能。ACME(Automated Certificate Management Environment, RFC 8555)将证书签发与续期自动化,Let’s Encrypt 借此大幅降低了证书成本与复杂度。NGINX 将 ACME 功能以 ngx_http_acme_module 的形式“原生”集成,意味着你可以直接在 NGINX 配置层完成证书生命周期管理,而非依赖系统级别的外部工具(如 Certbot、acme.sh 等)。

主要好处:

  • 🍄
    在 NGINX 配置层自动化证书签发与续期,减少脚本与 Cron 的复杂度。
  • 🍄
    降低对外部工具(Certbot、acme.sh)的依赖,缩小攻击面与运维边界。
  • 🍄
    原生实现提升平台可移植性——不同 Linux 发行版或容器环境中更加一致。
  • 🍄
    结合 NGINX 的运行时变量(如 $acme_certificate),可以实现动态证书注入与缓存管理。

二、核心概念速览

ACME 是什么?
ACME 是一套标准协议,用于自动化证书的申请、验证、签发与续期。主要挑战类型包括 HTTP-01、DNS-01、TLS-ALPN(ACMEv2 扩展支持通配符与更多验证方式)。

NGINX 预览版支持:
当前 ngx_http_acme_module 预览实现仅支持 HTTP-01 挑战(即通过 HTTP 服务响应 CA 的验证请求),未来计划支持 TLS-ALPN 与 DNS-01。

关键 NGINX 变量与指令:

  • 🍄
    acme_issuer <name>:声明证书颁发器(CA)的 directory URI 与状态路径。
  • 🍄
    acme_shared_zone:可选的共享内存区域,用于存放证书、私钥与挑战状态。
  • 🍄
    acme_certificate <issuer>:在 server 块中启用自动签发/续期。
  • 🍄
    运行时变量:$acme_certificate, $acme_certificate_key(用于 ssl_certificate / ssl_certificate_key)。

三、配置详解与示例

下面给出从声明 issuer,到挑战配置,再到自动签发的完整示例与运维建议——可复制到 NGINX 配置中进行测试。

1. 声明 ACME 发行器

acme_issuer letsencrypt {
    uri         https://acme-v02.api.letsencrypt.org/directory;
    # contact   admin@example.test;
    state_path  /var/cache/nginx/acme-letsencrypt;
    accept_terms_of_service;
}

建议: state_path 目录应设置严格权限(例如 chown root:nginxchmod 700),并纳入备份与灾备策略。

2. 分配共享内存

acme_shared_zone zone=acme_shared:1M;

默认 256K,生产环境建议根据证书数量和并发挑战量适当放大(示例中用 1M)。

3. 配置 HTTP-01 挑战的监听

server {
    listen 80;
    server_name example.com www.example.com;

    location / {
        # 保持简单返回,模块会接管特定 challenge 路径
        return 404;
    }
}

注意: HTTP-01 必须在端口 80 上被访问到;如果使用负载均衡或 CDN,请确保挑战请求能直接到达 NGINX 实例或将挑战路径(.well-known/acme-challenge/)正确路由至后端。

4. 在 HTTPS server 中启用自动证书(acme_certificate)

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    acme_certificate letsencrypt;

    ssl_certificate       $acme_certificate;
    ssl_certificate_key   $acme_certificate_key;
    ssl_certificate_cache max=10;
}

兼容性说明: 预览版对 server_name 的形式有限制:通配符和正则表达式可能不受支持,请使用明确或子域名列表。


四、典型迁移场景与实践建议(从 Certbot 到 NGINX 原生 ACME)

许多团队已有 Certbot / acme.sh 的既有流水线。迁移到 NGINX 原生 ACME 的流程建议如下:

  1. 并行运行与验证:在测试环境或小流量域名上并行启用 ngx_http_acme_module,观察签发与续期日志。
  2. 证书证明与回滚机制:保留现有 Certbot 的证书作为回滚方案,确保在模块异常时可快速切换。
  3. 日志与监控:为模块生命周期事件(签发成功/失败、挑战失败、过期提醒)配置告警。
  4. 备份 state_path:定期备份 NGINX 的 state_path(加密存储),以避免密钥丢失。
  5. CDN / 负载均衡注意事项:如果使用 CDN(如 Cloudflare)或全局负载均衡器,请确认挑战路径不会被缓存或拦截,或使用 DNS-01(未来支持)替代 HTTP-01。

(以上实践建议包含百度与 Google 常见长尾搜索意图词:如“Certbot 迁移 NGINX 原生 ACME”、“在 NGINX 中自动续期 TLS 证书 实践”等)


五、安全、权限与合规建议

  • 🍄
    最小权限与目录保护: state_path 与任何证书临时文件应仅对 NGINX 进程可读写,禁止对外开放。
  • 🍄
    密钥生命周期管理: 定期审计私钥访问记录,必要时采用硬件安全模块(HSM)或受管的密钥管理服务。
  • 🍄
    透明度与合规: 对于合规要求严格的行业(金融、医疗),评估是否需要额外的证书策略(例如更短生命周期或多重签发流程)。
  • 🍄
    运维知识共享: 在团队文档中记录自动签发失败的常见原因、恢复步骤与联系人,提升组织的经验共享(Experience / E)。

六、常见问题(FAQ

Q1:当前支持通配符证书吗?
A:预览版主要支持 HTTP-01 验证,通配符证书通常需要 DNS-01 验证,因此当前预览版不支持通配符。请关注后续版本更新与 GitHub Issue 跟踪。

Q2:如何保障挑战请求能到达 NGINX?
A:确保端口 80 对外可访问或在负载均衡器/CDN中为 .well-known/acme-challenge/ 路径做直通规则;避免缓存与重写拦截挑战请求。

Q3:模块会在内存中存储私钥吗?是否安全?
A:模块使用 acme_shared_zone 存储证书与挑战数据;请通过文件权限、进程隔离与备份策略保证安全性。

Q4:如何迁移现有 Certbot 证书到 NGINX 模块?
A:先并行测试,验证模块签发流程;制定回滚计划与证书备份;迁移完成后移除旧脚本并持续监控。

Q5:若签发失败,如何排查?
A:检查 NGINX 日志(error.log)、挑战路径访问日志、ACME CA 返回的错误信息,确认端口 80 路由、DNS 解析与 server_name 配置正确。