Let's Encrypt 证书自动续期:从手动 DNS 切到 webroot 的踩坑记录
上一篇写了怎么用 DNS 验证拿免费证书。但那种方式有个硬伤:手动验证的证书不会自动续期,90 天到期前必须手动重跑一次,否则网站证书过期、浏览器报警。
备案通过后域名可以正常访问了,正好把它切换成 webroot(HTTP-01)自动续期。记录一下过程和踩到的坑。
为什么要切
| 方式 | 能否自动续期 | 适用场景 |
|---|---|---|
| 手动 DNS-01 | ❌ 需人工 | 域名未备案、80 端口被拦、无法 HTTP 验证时 |
| webroot HTTP-01 | ✅ certbot timer 自动续 | 域名可正常访问 https 后 |
切换步骤
1. 确认 webroot 路径可达
证书验证文件会放在网站根目录,先确认 .well-known/acme-challenge/ 能被公网访问:
mkdir -p /var/www/example.com/.well-known/acme-challenge
echo test-ok > /var/www/example.com/.well-known/acme-challenge/testfile
curl -I https://www.example.com/.well-known/acme-challenge/testfile
如果 80 端口配了 301 跳 HTTPS,也没关系:Let's Encrypt 会跟随重定向到 HTTPS 校验。
2. 用 webroot 重新签发,覆盖旧证书
certbot certonly --webroot -w /var/www/example.com \
-d www.example.com -d example.com \
--cert-name www.example.com \
--force-renewal --non-interactive --agree-tos -m you@example.com \
--deploy-hook "systemctl reload nginx"
关键是 --cert-name 与旧证书一致 + --force-renewal,这样会重写 renewal 配置里的验证方式,而不是新开一套。
3. 确认 renewal 配置已改
grep -E "authenticator|webroot_path" /etc/letsencrypt/renewal/www.example.com.conf
# authenticator = webroot
# webroot_path = /var/www/example.com,
4. 验证自动续期
certbot renew --dry-run
systemctl list-timers certbot.timer
看到模拟续期成功、certbot.timer 有下次执行时间,就说明 90 天到期会自动续,不用再管。
踩坑:certbot 卡住 + 锁文件
测试时遇到:
Another instance of Certbot is already running.
原因是之前一条命令在 SSH 会话被中断后,certbot 进程还活着,一直占着 /var/lib/letsencrypt/.certbot.lock。处理:
ps aux | grep certbot # 找到残留进程
kill -9 <pid>
rm -f /var/lib/letsencrypt/.certbot.lock
然后重跑 dry-run 即可。别直接删锁不杀进程,否则可能出现两个进程同时写证书目录。
小结
证书自动续期就三步:确认 webroot 可达 → 用 webroot 重新签发一次 → 跑 dry-run 验证。切完之后,HTTPS 这块基本可以几年不用管了。
需要处理服务器 HTTPS/证书/续期问题的,可以找我。