# Let’s Encrypt 证书怎样设置自动续期|防止证书失效(完整配置教程)
## 前言介绍
Let’s Encrypt 提供的免费 SSL 证书有效期只有90天,这意味着每隔三个月,你的网站证书就会过期。如果不手动续期,用户访问你的网站时浏览器会显示“不安全”警告,严重影响网站信誉和用户体验。手动续期不仅麻烦,还容易忘记,一旦证书失效,网站可能直接无法通过 HTTPS 访问。本教程将详细讲解如何配置自动续期任务,让服务器在证书即将到期时自动完成续期,彻底解决证书过期问题。无论你是使用 Apache、Nginx 还是其他 Web 服务器,只要安装了 Certbot 工具,都能按照本教程完成配置。
## 前置准备
在开始配置自动续期之前,请确保你已经满足以下条件:
1. **已安装 Certbot 客户端**:Certbot 是 Let’s Encrypt 官方推荐的证书管理工具。如果尚未安装,请根据你的操作系统执行安装命令:
- Ubuntu/Debian:`sudo apt update && sudo apt install certbot`
- CentOS/RHEL:`sudo yum install epel-release && sudo yum install certbot`
- 其他系统请参考 Certbot 官方文档。
2. **已成功申请过 Let’s Encrypt 证书**:本教程假设你已经通过 Certbot 获取过证书,例如使用 `sudo certbot --apache` 或 `sudo certbot --nginx` 命令完成过首次申请。如果还没有证书,请先执行申请命令,本教程重点在于续期配置。
3. **具有 sudo 或 root 权限**:自动续期需要修改系统计划任务和证书文件,普通用户无法操作。
4. **域名解析正常**:你的域名必须正确解析到服务器 IP,且 80 和 443 端口开放,因为续期时 Certbot 需要验证域名所有权。
5. **Web 服务器正常运行**:Apache 或 Nginx 等服务必须处于运行状态,否则续期验证可能失败。
## 分步操作步骤
### 步骤1:测试手动续期是否正常工作
在配置自动续期之前,先手动执行一次续期命令,确保 Certbot 能够成功续期现有证书。这可以提前发现潜在问题,避免自动任务执行时出错。
1. 打开终端,登录到你的服务器(通过 SSH 或直接在服务器控制台操作)。
2. 执行以下命令测试续期:
```
sudo certbot renew --dry-run
```
`--dry-run` 参数表示模拟续期,不会实际修改证书,只会测试验证流程是否通畅。
3. 观察命令输出结果。如果看到类似以下内容,说明续期验证成功:
```
Congratulations, all renewals succeeded. The following certs have been renewed:
/etc/letsencrypt/live/yourdomain.com/fullchain.pem (success)
```
如果出现错误,请根据错误信息排查。常见错误包括:
- 端口被占用:确保 80 和 443 端口没有被防火墙或其它程序阻止。
- 域名解析失败:检查 DNS 设置是否正确。
- 权限不足:使用 sudo 重新执行命令。
4. 如果 `--dry-run` 成功,再执行真实续期命令确认一次:
```
sudo certbot renew
```
这个命令会检查所有证书,如果距离过期时间不足30天,则会自动续期;如果证书还很新,会提示“not due for renewal”。这一步只是为了确认命令能正常运行,不强制要求续期成功。
### 步骤2:配置系统计划任务(cron)自动执行续期
手动续期成功后,接下来通过 Linux 的 cron 定时任务让系统定期自动执行续期。推荐每天执行两次,因为 Let’s Encrypt 证书有30天的续期窗口,频繁检查可以确保证书在过期前被及时更新。
1. 打开 cron 任务编辑器:
```
sudo crontab -e
```
如果是第一次使用,系统会提示选择编辑器,选择 nano 或 vim 均可。建议选择 nano,操作更直观。
2. 在文件末尾添加以下一行内容(注意不要遗漏任何空格或符号):
```
0 0,12 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
```
如果你使用的是 Apache,将 `nginx` 替换为 `apache2` 或 `httpd`,具体取决于你的系统服务名称:
- Ubuntu/Debian 的 Apache:`systemctl reload apache2`
- CentOS/RHEL 的 Apache:`systemctl reload httpd`
如果你的 Web 服务器是其他类型(如 Caddy、Traefik),请将 `systemctl reload nginx` 替换为对应的重载命令。
命令参数说明:
- `0 0,12 * * *`:表示每天0点和12点各执行一次。`0`代表分钟,`0,12`代表小时(0点和12点),`* * *`代表每天、每月、每周。
- `/usr/bin/certbot renew`:调用 Certbot 执行续期。建议使用绝对路径,避免环境变量问题。可以通过 `which certbot` 命令查看你的 Certbot 安装路径。
- `--quiet`:静默模式,不输出任何信息,避免 cron 发送大量邮件。
- `--post-hook "systemctl reload nginx"`:续期成功后,自动重载 Web 服务器使新证书生效。`--post-hook` 只在证书真正被续期时执行,如果证书未到期则不执行。
3. 保存并退出编辑器(nano 按 `Ctrl+X`,然后按 `Y` 确认,再按 `Enter`)。
4. 验证 cron 任务是否添加成功:
```
sudo crontab -l
```
输出中应该包含你刚才添加的那一行。
### 步骤3:验证 cron 任务能正确执行
添加 cron 任务后,建议手动模拟一次执行,确认命令在 cron 环境下可以正常运行。
1. 创建一个测试脚本,模拟 cron 执行环境:
```
sudo bash -c "cd /root && /usr/bin/certbot renew --quiet --post-hook 'systemctl reload nginx'"
```
注意:这里没有使用 `--dry-run`,因为我们要测试真实续期。如果证书距离过期超过30天,Certbot 会跳过续期,不会报错。
2. 检查 Web 服务器是否正常运行:
```
sudo systemctl status nginx
```
或者检查 Apache:
```
sudo systemctl status apache2
```
确保服务状态显示为 `active (running)`。
3. 如果上述命令执行后没有报错,说明 cron 任务配置正确。如果出现错误,请检查:
- Certbot 路径是否正确(使用 `which certbot` 确认)。
- Web 服务器服务名称是否正确(使用 `systemctl list-units --type=service | grep -E 'nginx|apache|httpd'` 查看确切名称)。
- 是否有权限问题(确保 cron 以 root 身份运行,我们使用 `sudo crontab -e` 已经保证了这一点)。
### 步骤4:配置日志记录(可选但推荐)
为了后续排查问题,建议为自动续期配置日志记录,这样即使 cron 静默运行,你也能通过日志了解续期情况。
1. 创建一个日志目录(如果不存在):
```
sudo mkdir -p /var/log/certbot
```
2. 修改 cron 任务,将输出重定向到日志文件。重新编辑 cron:
```
sudo crontab -e
```
3. 将原来的行替换为以下内容(以 Nginx 为例):
```
0 0,12 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx" >> /var/log/certbot/renew.log 2>&1
```
`>> /var/log/certbot/renew.log 2>&1` 表示将标准输出和错误输出都追加到日志文件中。
4. 保存并退出。以后你可以随时查看日志:
```
sudo tail -f /var/log/certbot/renew.log
```
使用 `tail -f` 可以实时查看最新日志。如果 cron 执行过,日志中会显示类似:
```
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/yourdomain.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certificate not yet due for renewal
```
或者续期成功时的信息。
### 步骤5:测试自动续期的实际效果
为了确保一切万无一失,你可以手动触发一次续期(即使证书未到期),确认 cron 任务能完整执行。
1. 强制续期(即使证书未到期):
```
sudo certbot renew --force-renewal --post-hook "systemctl reload nginx"
```
`--force-renewal` 会忽略证书有效期,强制重新申请证书。注意:Let’s Encrypt 有每周5次重复申请的速率限制,不要频繁使用此命令,仅用于测试。
2. 检查证书是否更新:
```
sudo openssl x509 -in /etc/letsencrypt/live/yourdomain.com/fullchain.pem -noout -dates
```
输出中的 `notAfter` 日期应该更新为当前时间加90天。
3. 访问你的网站,确认 HTTPS 正常工作。在浏览器地址栏点击锁图标,查看证书有效期是否已更新。
4. 测试完成后,下一次 cron 任务就会按照正常频率执行,无需再做额外操作。
### 步骤6:处理多域名和通配符证书的特殊情况
如果你的证书包含多个域名(SAN 证书)或使用了通配符域名(如 `*.yourdomain.com`),续期方式略有不同。
1. **多域名证书**:Certbot 自动续期默认会处理所有已申请的证书,无需额外配置。你可以在 `/etc/letsencrypt/renewal/` 目录下查看每个证书的配置文件,确认域名列表是否正确。
2. **通配符证书**:通配符证书需要使用 DNS 验证方式(`--manual --preferred-challenges dns`),自动续期也需要支持 DNS API 的插件,如 `certbot-dns-cloudflare`、`certbot-dns-route53` 等。如果你使用的是 DNS 验证,请确保:
- 已安装对应的 DNS 插件(例如 `sudo apt install python3-certbot-dns-cloudflare`)。
- 已配置 API 凭证文件(如 Cloudflare 的 `/root/.secrets/cloudflare.ini`)。
- 在 cron 任务中添加 `--dns-cloudflare --dns-cloudflare-credentials /root/.secrets/cloudflare.ini` 等参数。
例如:
```
0 0,12 * * * /usr/bin/certbot renew --quiet --dns-cloudflare --dns-cloudflare-credentials /root/.secrets/cloudflare.ini --post-hook "systemctl reload nginx" >> /var/log/certbot/renew.log 2>&1
```
注意:通配符证书的续期必须使用 DNS 验证,HTTP 验证无法续期通配符证书。
## 常见问题
**问题1:cron 任务执行了,但证书没有续期,日志显示“Certificate not yet due for renewal”**
这是正常现象。Certbot 只在证书距离过期不足30天时才会续期,如果证书还很新,它会跳过。你可以通过 `sudo certbot certificates` 命令查看所有证书的过期时间,确认是否在30天窗口内。
**问题2:自动续期后网站仍然显示旧证书**
可能原因:Web 服务器没有重载。检查 cron 任务中的 `--post-hook` 参数是否正确,服务名称是否匹配。你可以手动执行 `sudo systemctl reload nginx`(或对应服务),然后刷新网站查看。如果问题依旧,尝试完全重启 Web 服务器:`sudo systemctl restart nginx`。
**问题3:cron 任务没有执行,或者执行报错**
排查步骤:
- 检查 cron 服务是否运行:`sudo systemctl status cron`(Ubuntu/Debian)或 `sudo systemctl status crond`(CentOS/RHEL)。如果未运行,执行 `sudo systemctl start cron` 并设置开机自启。
- 查看 cron 日志:`sudo grep certbot /var/log/syslog`(Ubuntu)或 `sudo grep certbot /var/log/cron`(CentOS)。
- 确认 cron 任务语法正确:使用 `sudo crontab -l` 查看,确保没有多余空格或语法错误。
- 检查 Certbot 路径:使用 `which certbot` 确认路径,并在 cron 中使用绝对路径。
**问题4:续期时提示“Failed to connect to host”或“Connection refused”**
说明 Certbot 无法访问 Let’s Encrypt 的验证服务器。检查:
- 服务器网络是否正常:`ping api.letsencrypt.org`。
- 防火墙是否阻止了 80 或 443 端口:`sudo ufw status` 或 `sudo iptables -L`。
- 如果服务器在中国大陆,可能需要配置代理,因为 Let’s Encrypt 的服务器可能被屏蔽。可以在 cron 命令前添加环境变量:`http_proxy=http://你的代理:端口 https_proxy=http://你的代理:端口 /usr/bin/certbot renew ...`
**问题5:使用 DNS 验证的通配符证书续期失败**
常见原因:
- DNS API 凭证文件权限不正确:凭证文件(如 `cloudflare.ini`)必须设置为仅 root 可读:`sudo chmod 600 /root/.secrets/cloudflare.ini`。
- API 密钥过期或无效:登录 DNS 服务商后台检查 API 令牌是否有效。
- DNS 插件未安装:确认已安装对应的 Python 包,例如 `python3-certbot-dns-cloudflare`。
**问题6:如何手动触发一次 cron 任务立即执行?**
你可以直接运行 cron 任务中的命令(不带 cron 时间部分):
```
sudo /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
```
或者如果你想测试 cron 环境,可以使用 `run-parts` 或直接执行 `sudo bash -c "crontab -l | tail -1 | bash"`(谨慎使用,会执行所有 cron 任务)。
## 收尾总结
通过本教程,你已经完成了 Let’s Encrypt 证书自动续期的完整配置。核心步骤包括:测试手动续期、添加 cron 计划任务、验证执行效果、配置日志记录,以及处理多域名和通配符证书的特殊情况。现在,你的服务器每天会自动检查两次证书状态,在证书过期前自动续期并重载 Web 服务,无需任何人工干预。
建议你在配置完成后,每周查看一次日志文件(`/var/log/certbot/renew.log`),确保持续正常运行。如果更换了 Web 服务器或域名,记得同步更新 cron 任务中的 `--post-hook` 参数。另外,Let’s Encrypt 偶尔会更新验证策略,建议关注官方公告,必要时调整配置。
自动续期一旦稳定运行,你就可以彻底告别证书过期的烦恼,专注于网站内容和业务本身。