前言:为什么需要自动续期SSL证书
Let’s Encrypt 是目前最受欢迎的免费 SSL 证书颁发机构,但其证书有效期仅为 90 天。这意味着每三个月你都必须手动续期一次——如果你的站点配置了 Nginx、Apache 或其他 Web 服务器,忘记续期会导致浏览器显示”不安全”警告,直接影响用户体验和 SEO 排名。
好消息是,Let’s Encrypt 官方推荐的 Certbot 客户端内置了自动续期机制。本文将从零开始,带你完成从 Certbot 安装、首次证书签发,到自动化续期、续期后服务重载的完整配置。
第一步:安装 Certbot
Certbot 是 Let’s Encrypt 官方推荐的 ACME 客户端。根据你的操作系统选择对应的安装方式:
Ubuntu / Debian
$ sudo apt update
$ sudo apt install certbot python3-certbot-nginx # 如果使用 Nginx
$ sudo apt install certbot python3-certbot-apache # 如果使用 Apache
安装完成后验证版本:
$ certbot --version
certbot 2.11.0
CentOS / Rocky Linux / AlmaLinux
$ sudo dnf install epel-release
$ sudo dnf install certbot python3-certbot-nginx
第二步:首次签发 SSL 证书
Certbot 提供多种插件来签发证书。最常用的两种方式:
方式 A:使用 Nginx 插件(推荐,全自动)
如果 Nginx 配置文件已经指向你的域名,使用 Nginx 插件可以一键完成:
$ sudo certbot --nginx -d example.com -d www.example.com
Certbot 会自动:
- 验证域名所有权(通过 HTTP-01 挑战)
- 修改 Nginx 配置,添加 SSL 相关指令
- 配置 301 HTTP → HTTPS 重定向(可选)
实际输出示例:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for example.com and www.example.com
Performing the following challenges:
http-01 challenge for example.com
http-01 challenge for www.example.com
Waiting for verification...
Cleaning up challenges
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
Deploying certificate
Successfully deployed certificate for example.com
Successfully deployed certificate for www.example.com
Congratulations! You have successfully enabled HTTPS!
方式 B:使用 Webroot 插件(手动配置)
如果不想让 Certbot 修改 Nginx 配置,或者使用自定义 Web 服务器:
$ sudo certbot certonly --webroot -w /var/www/example.com -d example.com -d www.example.com
这种方式仅在 Nginx 中手动添加一个 location 块指向验证目录(通常不需要手动操作,Certbot 会自动在 /.well-known/acme-challenge/ 下放置验证文件)。
第三步:验证证书文件
签发成功后,证书文件存储在 /etc/letsencrypt/live/your-domain/ 目录下:
$ sudo ls -la /etc/letsencrypt/live/example.com/
lrwxrwxrwx 1 root root 39 May 22 09:00 cert.pem -> ../../archive/example.com/cert1.pem
lrwxrwxrwx 1 root root 40 May 22 09:00 chain.pem -> ../../archive/example.com/chain1.pem
lrwxrwxrwx 1 root root 44 May 22 09:00 fullchain.pem -> ../../archive/example.com/fullchain1.pem
lrwxrwxrwx 1 root root 42 May 22 09:00 privkey.pem -> ../../archive/example.com/privkey1.pem
各文件用途:
- cert.pem:服务端证书(仅证书本身)
- chain.pem:中间证书链
- fullchain.pem:服务端证书 + 中间证书链(Nginx 常用此文件)
- privkey.pem:私钥文件(⚠️ 绝对不要公开)
Nginx 配置中的典型引用方式:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
第四步:测试自动续期
Certbot 安装时会自动添加一个 systemd timer 或 cron 任务,每天检查两次证书是否即将到期(到期前 30 天内会触发续期)。
首先,用 dry-run 模式测试续期流程是否正常:
$ sudo certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Processing /etc/letsencrypt/renewal/example.com.conf
Account registered.
Simulating renewal of an existing certificate for example.com and www.example.com
Waiting for verification...
Cleaning up challenges
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
如果输出 all simulated renewals succeeded,说明续期机制一切正常。
查看系统自带的续期定时器:
$ sudo systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled)
Active: active (waiting) since Thu 2026-05-21 09:00:00 UTC; 1 day ago
Trigger: Sat 2026-05-23 03:49:39 UTC; 18h left
Triggers: ● certbot.service
如果系统中没有自动创建 systemd timer(例如某些旧版本),可以手动添加 cron 任务:
$ sudo crontab -e
# 每天凌晨 3:00 检查续期,如果成功则重载 Nginx
0 3 * * * /usr/bin/certbot renew --quiet && systemctl reload nginx
第五步:配置续期后服务重载
证书更新后,Web 服务器需要重新加载才能使用新证书。Certbot 的 renew 钩子可以自动完成:
方式 1:通过 deploy hook(推荐)
在 /etc/letsencrypt/renewal-hooks/deploy/ 目录下创建一个脚本:
$ sudo tee /etc/letsencrypt/renewal-hooks/deploy/restart-nginx.sh << 'EOF'
#!/bin/bash
systemctl reload nginx || true
EOF
$ sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/restart-nginx.sh
这个脚本只会在证书 成功更新后 执行,不会在 dry-run 或续期失败时触发。
方式 2:使用 –post-hook 参数
也可以将重载命令直接写入续期命令:
$ sudo certbot renew --post-hook "systemctl reload nginx"
但 deploy hook 更加规范,因为它是 Certbot 原生支持的钩子系统,且按字母顺序执行所有 deploy 目录下的脚本。
第六步:验证自动续期是否生效
手动强制过期检查来验证整个自动续期链条:
$ sudo certbot renew --force-renewal --deploy-hook "systemctl reload nginx"
这条命令会强制续期所有证书(即使距到期还有 90 天),续期后立即重载 Nginx。查看日志确认:
$ sudo tail -20 /var/log/letsencrypt/letsencrypt.log
2026-05-22 09:15:42,123:DEBUG:certbot.renewal:Certificate renewed
2026-05-22 09:15:42,125:DEBUG:certbot.renewal:Running deploy hooks
2026-05-22 09:15:42,130:INFO:certbot.renewal:Deploy hook 'restart-nginx.sh' ran successfully
最后,检查证书到期时间:
$ sudo openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/cert.pem
notAfter=Aug 20 09:15:42 2026 GMT
到期时间向后推移了 90 天,证明续期成功。
第七步:多域名与泛域名证书
多域名证书
一张证书可以包含多个域名,签发时用 -d 参数指定:
$ sudo certbot --nginx -d example.com -d www.example.com -d blog.example.com -d api.example.com
泛域名证书(Wildcard Certificate)
如果要保护 *.example.com 下的所有子域名,需要使用 DNS-01 挑战(因为 HTTP-01 无法验证通配符域名):
$ sudo certbot certonly --manual --preferred-challenges dns -d *.example.com -d example.com
Certbot 会提示你在 DNS 管理面板中添加一条 TXT 记录:
_acme-challenge.example.com TXT "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
添加完成后等待 1-2 分钟让 DNS 传播,然后回车确认。
泛域名证书的续期同样需要 DNS 验证——考虑使用支持 DNS API 插件(如 Cloudflare、Aliyun DNS、DNSPod)实现全自动续期:
$ sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.cloudflare/credentials.ini -d *.example.com -d example.com
常见问题 FAQ
Q1: Let’s Encrypt 续期失败,提示 “No valid IP addresses” 怎么办?
- 确认域名 A 记录正确指向服务器 IP:
dig +short example.com - 确认服务器 80 端口可访问:
curl -I http://example.com/.well-known/acme-challenge/test,如果返回 404 而不是连接失败,说明端口通 - 检查防火墙是否放行 80 端口:
sudo ufw status确认80/tcp状态为ALLOW - 如果使用 CDN(Cloudflare 等),将域名切换为 DNS Only(灰色云朵)模式,或使用 DNS-01 挑战
Q2: Certbot 续期时提示 “The certificate will expire soon”,但自动续期没触发?
sudo systemctl status certbot.timer
sudo systemctl list-timers | grep certbot
如果 timer 停用,手动启用:sudo systemctl enable --now certbot.timer。如果 timer 正常但依然不续期,运行 sudo certbot renew --dry-run 查看具体错误。
如果使用的是 cron 而非 systemd,确保 crontab 中指定了绝对路径:/usr/bin/certbot,因为 cron 的环境变量有限。
Q3: 如何迁移 Let’s Encrypt 证书到新服务器?
- 在旧服务器上打包整个
/etc/letsencrypt目录:sudo tar czf letsencrypt-backup.tar.gz /etc/letsencrypt - 将文件复制到新服务器相同路径
- 在新服务器上重载 Nginx:
sudo systemctl reload nginx - 在新服务器上运行
sudo certbot renew --dry-run确认自动续期正常
注意:迁移后记得在新服务器上重新安装 Certbot 并确认 systemd timer 已启用。
总结
Let’s Encrypt SSL 证书的自动续期配置并不复杂:安装 Certbot → 签发证书 → 验证自动续期 → 配置 deploy hook。一旦配置完成,你基本上可以忘记证书这回事——Certbot 的 systemd timer 会每天检查两次,在到期前 30 天自动续期,deploy hook 会重载 Web 服务器。
如果你的站点已经配置了 Let’s Encrypt 但还没验证自动续期是否正常工作,建议马上运行 sudo certbot renew --dry-run 确认。还有什么比 HTTPS 证书突然过期更让人崩溃的呢?