核心难点是证书同步而非申请:需通过DNS-01统一签发通配符证书,再用rsync+SSH安全分发至各Nginx节点,并通过nginx -s reload或HUP信号实现零中断热加载,最后借助--deploy-hook在源机自动触发全量同步与重载。

多机环境下用 Certbot 管理通配符证书,核心难点不在“申请”,而在“同步”——证书必须安全、原子、零中断地分发到所有 Nginx 节点。关键不是复制文件,而是让每台机器上的 Nginx 实时感知并加载新证书。
一、统一签发:用 DNS 验证获取通配符证书
通配符证书(*.example.com)必须通过 DNS-01 验证,不能用 HTTP-01(因为无法保证所有节点都响应 /.well-known 路径)。以 Route53 为例:
- 安装插件:
pip install certbot-dns-route53 - 配置最小权限 IAM 策略,只允许操作对应 Hosted Zone 的 TXT 记录
- 执行签发:
certbot certonly --dns-route53 -d example.com -d *.example.com --agree-tos --email admin@example.com
证书会生成在 /etc/letsencrypt/live/example.com/ 下,且后续所有续期都复用同一套 DNS 凭据和验证逻辑。
二、证书分发:推荐使用 rsync + SSH 免密同步
不依赖共享存储或 NFS(有单点故障和权限风险),用主机作为证书源,推送到各 Nginx 节点:
- 在证书源主机上生成部署密钥:
ssh-keygen -t ed25519 -f ~/.ssh/cert-deploy -N "" - 将公钥追加到每台 Nginx 节点的
~nginx/.ssh/authorized_keys(注意属主是 nginx 用户) - 编写同步脚本(如
/opt/bin/sync-certs.sh):
rsync -avz --delete /etc/letsencrypt/live/example.com/ nginx@node1:/etc/letsencrypt/live/example.com/
rsync -avz --delete /etc/letsencrypt/live/example.com/ nginx@node2:/etc/letsencrypt/live/example.com/
ssh nginx@node1 "nginx -s reload"
ssh nginx@node2 "nginx -s reload"
三、容器化部署:挂载证书卷 + 信号通知 reload
若 Nginx 运行在 Docker 中,不要把证书 COPY 进镜像。正确做法是:
- 在宿主机创建持久化目录:
mkdir -p /data/nginx/certs - 首次同步后,运行容器时挂载:
-v /data/nginx/certs:/etc/letsencrypt/live/example.com:ro - 确保容器内 nginx 用户能读取该路径(UID 匹配或加
--user参数) - 同步脚本末尾增加:
docker kill -s HUP nginx-container-name(前提是 nginx 启动时未加-g daemon off;)
HUP 信号会触发 nginx 主进程优雅重载配置,无需重启,不丢连接。
四、自动续期与触发同步:用 renew hook 替代 cron 直接 reload
直接在每台机器跑 certbot renew 会导致证书不同步。应只在一台源机运行,并通过 --deploy-hook 触发分发:
- 编辑
/etc/cron.d/certbot,仅在源机启用:0 2 * * 1 root certbot renew --deploy-hook "/opt/bin/sync-certs.sh" -
--deploy-hook只在证书实际更新后才执行,避免无效 reload - 务必先测试:
certbot renew --dry-run --deploy-hook "/opt/bin/sync-certs.sh"
这样所有节点始终使用同一份证书快照,且每次更新都是原子切换。


















