
内容声明
本文仅用于技术分享和学习交流,内容不包含任何广告、推广、引流、付费课程或外链信息。所有示例和配置均为技术实践,欢迎参考和自定义。
Certbot 是一个 ACME (Automated Certificate Management Environment,自动证书管理环境) 客户端。他可以申请、部署、续约和撤销 HTTPS 证书。
Certbot 通常用于申请 Let's Encrypt 证书。他支持以下验证方式:
standalonewebroot本文以 Debian 系统为例,介绍 Certbot 的安装、申请、续约和自动化管理方法。
开始申请证书前,需要确认以下条件:
A 记录已指向服务器的公网 IPv4 地址。AAAA 记录时,该记录必须指向正确的 IPv6 地址。sudo 权限。可以使用以下命令检查 DNS 解析:
dig +short A example.com
dig +short AAAA example.com更新 Debian 软件包索引:
sudo apt update安装 Certbot:
sudo apt install certbot检查安装结果:
certbot --version输出会包含当前安装的 Certbot 版本。
使用 Nginx 时,安装 Nginx 插件:
sudo apt install python3-certbot-nginx使用 Apache 时,安装 Apache 插件:
sudo apt install python3-certbot-apache查看已经安装的 Certbot 插件:
sudo certbot pluginsstandalone 模式会启动一个临时 HTTP 服务。该服务默认监听 TCP 80 端口。
申请单个域名证书:
sudo certbot certonly \
--standalone \
-d example.com申请包含多个域名的证书:
sudo certbot certonly \
--standalone \
-d example.com \
-d www.example.com该模式不会修改 Nginx 或 Apache 配置。申请成功后,需要手动配置 Web 服务。
使用该模式前,需要确认 TCP 80 端口处于空闲状态:
sudo ss -ltnp | grep ':80'Nginx、Apache 或 Docker 容器可能占用该端口。
webroot 模式通过现有 Web 服务提供验证文件。他不需要停止 Nginx 或 Apache。
指定网站根目录并申请证书:
sudo certbot certonly \
--webroot \
-w /var/www/html \
-d example.com外部网络必须能够访问 /.well-known/acme-challenge/ 路径。
Nginx 插件可以申请证书,并自动修改 Nginx 配置:
sudo certbot --nginx \
-d example.com \
-d www.example.com使用前需要安装 python3-certbot-nginx,并确保 Nginx 配置检查通过。
通配符证书必须使用 DNS 验证:
sudo certbot certonly \
--manual \
--preferred-challenges dns \
-d example.com \
-d '*.example.com'Certbot 会要求用户创建 DNS TXT 记录。手动 DNS 验证不适合无人值守续约。
Certbot 默认将证书保存在以下目录:
/etc/letsencrypt/live/example.com/Nginx 通常使用以下两个文件:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;完整的 HTTPS 配置示例:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/html;
}检查并重载 Nginx:
sudo nginx -t
sudo systemctl reload nginx不要将 privkey.pem 提交到 Git 仓库,也不要向其他用户开放读取权限。
查看证书主题、签发机构和有效期:
sudo openssl x509 \
-in /etc/letsencrypt/live/example.com/cert.pem \
-noout \
-subject \
-issuer \
-dates测试 HTTPS 连接:
curl -I https://example.com检查 Nginx 配置:
sudo nginx -t列出 Certbot 管理的证书:
sudo certbot certificates示例输出:
Certificate Name: example.com
Domains: example.com www.example.com
Expiry Date: 2026-09-20 08:00:00+00:00
Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/example.com/privkey.pemCertificate Name 是 Certbot 内部使用的证书名称。续约、撤销和删除证书时,可以通过 --cert-name 指定该名称。
Certbot 的常用目录如下:
目录 | 用途 |
|---|---|
| 当前有效证书的软链接 |
| 证书的历史版本 |
| 每张证书的续约配置 |
| 自动续约 Hook 脚本 |
| Certbot 日志 |
| Certbot 工作数据 |
Web 服务应引用 /etc/letsencrypt/live/ 中的文件。
不要直接修改 live 或 archive 目录中的文件。
使用 Let's Encrypt 测试环境模拟续约:
sudo certbot renew --dry-run测试成功时,会出现类似输出:
Congratulations, all simulated renewals succeeded--dry-run 不会替换当前使用的正式证书。
检查全部证书并续约符合条件的证书:
sudo certbot renewCertbot 4.0.0 及以上版本会根据证书总有效期计算续约时间。
当证书剩余有效期少于总有效期的三分之一时,Certbot 会尝试续约。有效期不超过 10 天的证书使用二分之一作为阈值。
certbot renew 可以频繁执行。尚未进入续约期的证书会被跳过。
只检查指定证书:
sudo certbot renew \
--cert-name example.com强制续约指定证书:
sudo certbot renew \
--cert-name example.com \
--force-renewal强制续约会申请新的正式证书。频繁执行可能触发证书颁发机构的速率限制。
Certbot 2.3.0 及以上版本可以使用 reconfigure 修改续约参数:
sudo certbot reconfigure \
--cert-name example.com \
--webroot-path /srv/www/example.comCertbot 会先通过测试环境验证新配置。验证成功后,新配置会用于后续续约。
不建议直接编辑以下文件:
/etc/letsencrypt/renewal/example.com.conf错误配置可能导致自动续约失败。
Hook (钩子) 可以在续约流程的不同阶段执行命令。
Hook | 执行时间 | 常见用途 |
|---|---|---|
| 开始续约尝试前 | 停止占用 TCP 80 的服务 |
| 完成续约尝试后 | 恢复此前停止的服务 |
| 证书成功签发或续约后 | 重载 Web 服务或部署证书 |
pre-hook 和 post-hook 只会在 Certbot 实际尝试续约时执行。
post-hook 不代表续约成功。需要在成功后执行的操作,应使用 deploy-hook。
standalone 模式需要释放 TCP 80 端口时,可以停止并恢复 Nginx:
sudo certbot renew \
--pre-hook "systemctl stop nginx" \
--post-hook "systemctl start nginx"如果 Nginx 由 Docker Compose 管理,可以执行:
sudo certbot renew \
--pre-hook "docker compose -f /srv/web/compose.yaml stop nginx" \
--post-hook "docker compose -f /srv/web/compose.yaml start nginx"docker compose stop nginx 会停止现有容器,但不会删除容器。
docker compose start nginx 会重新启动该容器。
定时任务的工作目录并不固定。因此,Hook 中应通过 -f 指定 Compose 文件的绝对路径。
证书成功续约后,可以重载 Nginx:
sudo certbot renew \
--deploy-hook "systemctl reload nginx"Certbot 会自动执行以下目录中的可执行文件:
/etc/letsencrypt/renewal-hooks/pre/
/etc/letsencrypt/renewal-hooks/deploy/
/etc/letsencrypt/renewal-hooks/post/Hook 脚本统一使用 .sh 后缀。该后缀可以明确表示文件类型,也便于编辑器识别 Shell 语法。
脚本名称中的 10- 和 90- 用于控制执行顺序。Certbot 会按照文件名的字节顺序,执行同一个 Hook 目录中的脚本。
例如,以下脚本的执行顺序为:
10-stop-nginx.sh
20-stop-other-service.sh
90-write-log.shpre、deploy 和 post 是相互独立的目录。文件名排序只影响同一个目录中的执行顺序。
创建 standalone 模式的 Docker Compose 停止脚本:
sudo nano \
/etc/letsencrypt/renewal-hooks/pre/10-stop-nginx.sh写入以下内容:
#!/bin/sh
set -eu
/usr/bin/docker compose \
-f /srv/web/compose.yaml \
stop nginx创建恢复脚本:
sudo nano \
/etc/letsencrypt/renewal-hooks/post/90-start-nginx.sh写入以下内容:
#!/bin/sh
set -eu
/usr/bin/docker compose \
-f /srv/web/compose.yaml \
start nginx授予脚本执行权限:
sudo chmod +x \
/etc/letsencrypt/renewal-hooks/pre/10-stop-nginx.sh \
/etc/letsencrypt/renewal-hooks/post/90-start-nginx.sh检查脚本权限:
sudo ls -l \
/etc/letsencrypt/renewal-hooks/pre/ \
/etc/letsencrypt/renewal-hooks/post/确认 Docker 的实际路径:
command -v docker如果输出路径不是 /usr/bin/docker,需要同步修改脚本。
普通 --dry-run 不会执行 deploy-hook。
测试续约和 deploy-hook:
sudo certbot renew \
--dry-run \
--run-deploy-hooks测试成功时,Certbot 会使用当前正式证书执行 deploy-hook。他不会部署测试环境生成的临时证书。
通过 Debian 软件包安装 Certbot 后,系统通常会创建 systemd 定时器。
查看定时器状态:
sudo systemctl status certbot.timer查看下次执行时间:
sudo systemctl list-timers --all | grep certbot启用并立即启动定时器:
sudo systemctl enable --now certbot.timer正常运行时,状态通常为:
Active: active (waiting)waiting 表示定时器正在等待下一次触发。
定时器会触发以下服务:
certbot.servicecertbot.service 通常是一次性任务。任务执行完成后,显示 inactive (dead) 属于正常情况。
查看 certbot.service 日志:
sudo journalctl \
--unit certbot.service \
--lines 50 \
--no-pager查看最近一次启动后的日志:
sudo journalctl \
--unit certbot.service \
--boot \
--no-pager查看 Certbot 文件日志:
sudo tail -n 100 \
/var/log/letsencrypt/letsencrypt.log实时查看日志:
sudo tail -f \
/var/log/letsencrypt/letsencrypt.log撤销操作会通知证书颁发机构停止信任该证书。
按证书名称撤销:
sudo certbot revoke \
--cert-name example.com也可以使用证书文件:
sudo certbot revoke \
--cert-path /etc/letsencrypt/live/example.com/cert.pem私钥泄露时,可以指定撤销原因:
sudo certbot revoke \
--cert-name example.com \
--reason keycompromise撤销后,如果保留续约配置,Certbot 仍可能再次尝试续约。无需继续使用时,应同时删除该证书。
先查看证书名称:
sudo certbot certificates删除证书前,需要移除 Nginx、Apache 或其他服务中的证书路径引用。
确认服务配置不再引用该证书后,执行:
sudo certbot delete \
--cert-name example.com不要直接删除 /etc/letsencrypt/ 中的证书文件。
删除操作不会自动撤销证书。私钥未泄露时,通常不需要专门撤销。
错误示例:
Could not bind TCP port 80 because it is already in use查看端口占用情况:
sudo ss -ltnp | grep ':80'也可以使用:
sudo lsof -iTCP:80 -sTCP:LISTEN停止对应服务后,重新测试续约:
sudo certbot renew --dry-run查看容器端口映射:
docker compose ps查看全部运行中的容器:
docker ps \
--format 'table {{.Names}}\t{{.Ports}}'停止指定 Compose 服务:
docker compose \
-f /srv/web/compose.yaml \
stop nginx重新启动指定服务:
docker compose \
-f /srv/web/compose.yaml \
start nginxstart 只能启动已经存在且处于停止状态的容器。
如果容器已经通过 docker compose down 删除,需要重新创建:
docker compose \
-f /srv/web/compose.yaml \
up -d nginxstandalone 模式配合自动续约时,应配置 pre-hook 和 post-hook。否则,systemd 定时续约可能因端口冲突而失败。
检查 IPv4 解析:
dig +short A example.com检查 IPv6 解析:
dig +short AAAA example.com检查 HTTP 是否可以访问:
curl -I http://example.com如果存在错误的 AAAA 记录,Let's Encrypt 可能访问错误的 IPv6 地址。此时需要修正或删除该记录。
还需要检查以下项目:
创建测试文件:
sudo mkdir -p \
/var/www/html/.well-known/acme-challenge
echo 'certbot-test' | sudo tee \
/var/www/html/.well-known/acme-challenge/test从外部访问:
curl \
http://example.com/.well-known/acme-challenge/test预期输出:
certbot-test测试完成后删除文件:
sudo rm \
/var/www/html/.well-known/acme-challenge/test如果返回 403 或 404,需要检查 Nginx 的 root、alias、try_files 和隐藏文件拦截规则。
查看详细错误日志:
sudo certbot renew --dry-run -vwebroot 模式。这两种方式通常不需要停止 Web 服务。standalone 模式适合没有 Web 服务的服务器。该模式也适合可以短暂停止反向代理的场景。.sh 后缀,并通过数字前缀控制执行顺序。certbot.timer,并执行测试: sudo certbot renew --dry-run版权声明
本文为原创文章,作者保留版权。转载请保留本文完整内容,并以超链接形式注明作者及原文出处。
作者: 除除
原文: https://blog.mazey.net/6504.html
<!-- ID: 20260899-debian-certbot -->
(完)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。