生产环境Certbot泛域名证书全自动续期完整配置指南(Cloudflare DNS验证)

前言:在生产环境中,使用Let's Encrypt免费证书是主流选择,但90%的运维同学都踩过同一个坑:证书能手动申请、能自动续期,但续期后Nginx不加载新证书,最终导致业务访问异常。

核心问题根本不是Certbot没续期成功,而是 没有给自动续期流程永久绑定「证书同步+服务重载」的钩子脚本。本文基于生产环境实战经验,提供一套完整、可落地、零故障的全自动续期方案,覆盖CentOS/Ubuntu双系统,彻底解决证书过期问题。

注:本文以 Cloudflare 作为 DNS 验证服务商示例,核心原理与操作逻辑完全通用,其他支持 ACME DNS-01 验证的域名商(如阿里云、腾讯云、DNSPod 等),仅需替换对应 DNS 插件与凭证配置,即可复用整套全自动续期方案。

一、前置准备:Cloudflare端API令牌创建(DNS验证前提)

使用Cloudflare DNS验证的优势是无需暴露80/443端口,支持泛域名证书,适合生产环境内网/非Web服务器场景。

  1. 登录Cloudflare后台,进入「我的个人资料」→ 左侧「API令牌」→ 「创建令牌」

  2. 选择「创建自定义令牌」,按以下规则配置:

    配置项 配置内容
    令牌名称 Certbot-生产服务器-API令牌(可自定义)
    权限 区域 - DNS - 编辑(Edit)
    区域资源 包括 - 特定区域 - 你的主域名(如example.com
    客户端IP筛选 等于 - 你的生产服务器公网IP(可选,提升安全性)
    令牌有效期 建议永久有效(按需调整)
  3. 点击「继续以显示摘要」→ 「创建令牌」,复制生成的令牌(仅显示1次,务必保存)

二、服务器端环境准备(CentOS/Ubuntu双版本)

核心说明

推荐使用Snap版Certbot,官方维护、版本最新、兼容性最好,避免系统自带yum/apt源的旧版本出现功能缺失、兼容性问题。

版本1:CentOS/RHEL 7/8/9 系列
bash 复制代码
# 1. 安装EPEL源(CentOS安装Snap的前置依赖)
sudo yum install epel-release -y

# 2. 安装Snapd
sudo yum install snapd -y

# 3. 启动Snapd服务并设置开机自启
sudo systemctl enable --now snapd.socket

# 4. 创建软链接,让snap命令全局可用
sudo ln -s /var/lib/snapd/snap /snap

# 5. 验证Snap安装(可选)
snap version
版本2:Ubuntu/Debian 系列
bash 复制代码
# 1. 更新系统源
sudo apt update -y

# 2. 安装Snapd(Ubuntu默认自带,无则执行)
sudo apt install snapd -y

# 3. 验证Snap安装(可选)
snap version

通用步骤:安装Certbot及Cloudflare DNS插件

bash 复制代码
# 1. 更新Snap核心组件,避免版本兼容问题
sudo snap install core && sudo snap refresh core

# 2. 卸载系统旧版Certbot(如有,避免冲突)
# CentOS执行:
sudo yum remove certbot -y
# Ubuntu执行:
sudo apt remove certbot -y

# 3. 安装Snap版Certbot并创建全局软链接
sudo snap install --classic certbot && sudo ln -s /snap/bin/certbot /usr/bin/certbot

# 4. 授权Certbot信任插件的root操作(解决插件权限报错)
sudo snap set certbot trust-plugin-with-root=ok

# 5. 安装Cloudflare DNS插件并创建全局软链接
sudo snap install certbot-dns-cloudflare && sudo ln -s /snap/bin/certbot-dns-cloudflare /usr/bin/certbot-dns-cloudflare

三、Cloudflare API凭证配置

bash 复制代码
# 1. 创建Certbot专属配置目录
sudo mkdir -p /etc/certbot

# 2. 编辑凭证文件
sudo nano /etc/certbot/cloudflare.ini

在编辑器中粘贴以下内容,替换为你自己的API令牌:

ini 复制代码
dns_cloudflare_api_token = 你刚刚在Cloudflare创建的API令牌

保存退出:按Ctrl+O → 回车确认 → 按Ctrl+X

bash 复制代码
# 3. 锁死文件权限(仅root可读,防止令牌泄露,Certbot强制要求)
sudo chmod 600 /etc/certbot/cloudflare.ini

四、申请泛域名SSL证书

执行以下命令,替换域名和邮箱为你的真实信息,全程无需手动干预,自动完成DNS验证和证书签发:

bash 复制代码
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/certbot/cloudflare.ini \
--dns-cloudflare-propagation-seconds 60 \
-d "example.com" -d "*.example.com" \
--email 你的运维邮箱@xxx.com \
--agree-tos --non-interactive
  • 参数说明:
    • --dns-cloudflare-propagation-seconds 60:给DNS记录传播预留60秒,避免验证失败
    • --non-interactive:非交互式执行,适合自动化脚本
    • 邮箱用于接收证书到期提醒,务必填写真实邮箱

执行成功后,证书会默认保存在/etc/letsencrypt/live/example.com/目录下。

五、Nginx证书替换与服务配置验证

1. 进入Nginx证书存放目录(按你的实际路径调整)

bash 复制代码
cd /etc/nginx/ssl/

2. 备份旧证书(出错可回滚,生产环境必做)

bash 复制代码
sudo cp example.com_certificate.pem example.com_certificate.pem.old
sudo cp example.com_private.key example.com_private.key.old

3. 复制新生成的证书替换旧文件

bash 复制代码
sudo cp /etc/letsencrypt/live/example.com/fullchain.pem /etc/nginx/ssl/example.com_certificate.pem
sudo cp /etc/letsencrypt/live/example.com/privkey.pem /etc/nginx/ssl/example.com_private.key

4. 验证Nginx配置语法(关键!防止配置错误导致服务崩溃)

bash 复制代码
sudo nginx -t

5. 重载Nginx加载新证书(温和重载,不中断业务,生产环境禁止用restart)

bash 复制代码
sudo systemctl reload nginx

6. 验证Nginx运行状态(可选)

bash 复制代码
sudo systemctl status nginx

六、核心重点:全自动续期钩子永久绑定(绝对不能漏的关键步骤)

踩坑预警

90%的证书故障都源于此:很多同学会用 sudo certbot renew --deploy-hook xxx.sh 测试钩子脚本,但这个参数是临时生效 ,仅对当前这一次renew命令有效,Certbot自带的定时自动续期不会执行这个脚本!

必须用 certbot reconfigure 命令,将钩子脚本永久写入证书的续期配置文件,才能实现真正的全自动续期。


步骤1:创建续期钩子脚本

bash 复制代码
sudo nano /usr/local/bin/certbot_example_renew.sh

在编辑器中粘贴以下内容,无需修改核心逻辑,仅需调整证书路径和Nginx重载命令适配你的环境:

bash 复制代码
#!/bin/bash
# 复制续期后的新证书到Nginx目录
sudo cp /etc/letsencrypt/live/example.com/fullchain.pem /etc/nginx/ssl/example.com_certificate.pem
sudo cp /etc/letsencrypt/live/example.com/privkey.pem /etc/nginx/ssl/example.com_private.key

# 温和重载Nginx,不中断业务
sudo nginx -s reload

保存退出:按Ctrl+O → 回车确认 → 按Ctrl+X

步骤2:给脚本添加执行权限

bash 复制代码
sudo chmod +x /usr/local/bin/certbot_example_renew.sh

步骤3:永久绑定钩子,后续自动续期会自动执行脚本(核心中的核心)

bash 复制代码
sudo certbot reconfigure --cert-name example.com --deploy-hook /usr/local/bin/certbot_example_renew.sh

执行后会出现交互提示:

复制代码
You are attempting to set a --deploy-hook. Would you like Certbot to run deploy hooks when it performs a dry run with the new settings?
(R)un deploy hooks/(D)o not run deploy hooks:

输入R回车,会立刻执行一次钩子脚本做验证,同时将配置永久写入文件。

步骤4:只读验证:确认绑定成功(无任何修改,生产环境安全)

不同版本的Certbot会自动兼容deploy_hookrenew_hook两个参数,两个命令都执行,确保能搜到配置:

bash 复制代码
# 验证deploy_hook配置
sudo grep -i "deploy_hook" /etc/letsencrypt/renewal/example.com.conf

# 验证renew_hook配置(Snap版Certbot会自动转换为此参数)
sudo grep -i "renew_hook" /etc/letsencrypt/renewal/example.com.conf

✅ 成功标准:执行后输出deploy_hook = 你的脚本完整路径renew_hook = 你的脚本完整路径,说明永久绑定成功。

七、全流程有效性验证

1. 模拟续期验证(零风险,不实际修改证书)

bash 复制代码
sudo certbot renew --dry-run

✅ 成功标准:输出中出现Running deploy-hook command: /usr/local/bin/certbot_example_renew.shRunning renew-hook command: /usr/local/bin/certbot_example_renew.sh,说明自动续期时会自动执行脚本。

2. OpenSSL验证证书有效期(最直观)

bash 复制代码
sudo openssl x509 -in /etc/nginx/ssl/example.com_certificate.pem -noout -dates

✅ 成功标准:输出notBeforenotAfter,显示证书的最新有效期。

3. 浏览器验证

强制刷新浏览器(Ctrl+F5)或用无痕模式访问你的域名,查看证书有效期,确认已更新为最新签发的证书。

八、生产环境避坑指南

  1. 临时钩子≠永久配置--deploy-hook跟在renew后是临时生效,只有跟在reconfigure后才是永久写入配置,这是最核心的坑。
  2. 版本兼容问题 :Snap版Certbot会自动将--deploy-hook转换为renew_hook写入配置文件,两个参数效果完全一致,无需纠结名称,只要grep能搜到就代表生效。
  3. 脚本权限问题 :钩子脚本必须添加x执行权限,路径必须用绝对路径,否则自动续期时会执行失败。
  4. Nginx重载规范 :生产环境必须用reload重载,禁止用restartreload是温和加载新配置,不会中断现有连接,restart会重启服务,导致业务中断。
  5. 缓存问题:验证证书时,浏览器/CDN会缓存旧证书,务必用强制刷新或无痕模式验证,避免误判。
  6. 权限最小化:Cloudflare API令牌仅开放指定域名的DNS编辑权限,不要用全局API密钥,降低泄露风险。

九、后续复查计划

Let's Encrypt证书有效期为90天,Certbot默认会在证书剩余30天时触发自动续期,推荐两个复查时间点,按需选择:

  1. 常规复查:证书到期前30天(如6月15日到期,5月15日复查),确认自动续期已执行,证书已同步。
  2. 保守复查:证书到期前10天(如6月15日到期,6月6日复查),距离到期有充足的缓冲时间,即使出现异常也有足够时间处理,零业务风险。

复查仅需执行本文「第七部分」的3条验证命令,1分钟即可完成。

结尾

按照本文流程配置完成后,你的生产环境证书就实现了真正的「全自动签发-续期-同步-重载」全流程闭环,无需任何人工干预,彻底杜绝证书过期导致的业务故障。

相关推荐
驾驭人生2 小时前
ASP.NET Core 实现 SSE 服务器推送|生产级实战教程(含跨域 / Nginx / 前端完整代码)
服务器·前端·nginx
SeSs IZED3 小时前
【Nginx 】Nginx 部署前端 vue 项目
前端·vue.js·nginx
爬山算法10 小时前
MongoDB(75)如何配置TLS/SSL加密?
数据库·mongodb·ssl
wuyikeer11 小时前
Nginx反向代理出现502 Bad Gateway问题的解决方案
运维·nginx·gateway
LSL666_11 小时前
nginx——方向代理和负载均衡
运维·nginx·负载均衡·反向代理
语戚11 小时前
Nginx vs Ribbon:负载均衡的两种核心范式(反向代理 vs 客户端负载)
java·nginx·spring·spring cloud·面试·ribbon·负载均衡
芳草萋萋鹦鹉洲哦1 天前
【windows】nginx如何注册为开机自启的服务(WinSW实现)
运维·windows·nginx
LSL666_1 天前
云服务上安装nginx
java·运维·nginx
小哈里1 天前
【证书】2026上海市人工智能训练师—高级/三级考试介绍与复习(SAIA版)&&(零基础速通必过版)
人工智能·ai·大模型·证书·人工智能训练师