Certbot + Nginx 签发 Let's Encrypt SSL 证书全过程记录

日期: 2026-08-11
服务器: 阿里云 CentOS
Nginx: 源码编译安装(v1.30.2),路径 /usr/local/nginx/
域名: domain-a.cn(已备案)、domain-b.com(备案中)


一、环境背景


二、完整过程与错误记录

错误 1:nginx 插件缺失

现象:

Discovered plugins: PluginsRegistry(PluginEntryPoint#manual, PluginEntryPoint#null,
PluginEntryPoint#standalone, PluginEntryPoint#webroot)
No candidate plugin
Selected authenticator None and installer None

原因: yum 安装的 certbot 没有附带 nginx 插件。

解决:

sudo yum install -y epel-release
sudo yum install -y python3-certbot-nginx

错误 2:pip 安装 certbot 时 cryptography 编译失败

现象:

Command "python setup.py egg_info" failed with error code 1
in /tmp/pip-build-ffjky510/cryptography/

原因: 缺少编译依赖,且 pip/setuptools 版本过旧(CentOS 7 Python 3.6)。

解决:

sudo yum install -y gcc openssl-devel libffi-devel python3-devel
sudo pip3 install --upgrade pip setuptools wheel
sudo pip3 install certbot certbot-nginx

备注:最终未采用 pip 方式,改用 yum 安装 EPEL 源的 python3-certbot-nginx 包。


错误 3:snap 安装 certbot 失败

现象:

error: too early for operation, device not yet seeded or device model not acknowledged

原因: CentOS 上 snapd 初始化未完成。

尝试:

sudo systemctl restart snapd
sudo systemctl restart snapd.seeded
sleep 5
snap changes

备注:snap 在 CentOS 上兼容性不佳,最终放弃 snap,回退到 yum 安装方式。


错误 4:certbot 找不到 nginx 二进制

现象:

NoInstallationError("Could not find a usable 'nginx' binary. Ensure nginx exists,
the binary is executable, and your PATH is set correctly.")

原因: Nginx 源码编译安装在 /usr/local/nginx/sbin/nginx,不在系统 PATH 中。

解决:

sudo ln -sf /usr/local/nginx/sbin/nginx /usr/sbin/nginx

错误 5:certbot 找不到 nginx 配置文件

现象:

nginx: [emerg] open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)
nginx: configuration file /etc/nginx/nginx.conf test failed

原因: certbot 默认在 /etc/nginx/ 下查找配置,而实际配置在 /usr/local/nginx/conf/

解决:

sudo ln -sf /usr/local/nginx/conf /etc/nginx

错误 6:ACME 验证返回 403(nginx 配置拦截)

现象:

Detail: xx.xx.xx.xx: Invalid response from
http://domain-b.com/.well-known/acme-challenge/xxx: 403

原因: nginx vhost 配置中有以下安全规则:

location ~ /\. {
    deny all;
}

该正则 ~ /\. 匹配所有 / 后以 . 开头的路径,包括 /.well-known/acme-challenge/,导致验证请求被 403 拒绝。

解决:

# 删除拦截规则
sed -i '/location ~ \/\\\. {/,/}/d' /usr/local/nginx/conf/vhost/voxtalkbox.conf

# 重载 nginx
/usr/local/nginx/sbin/nginx -t && /usr/local/nginx/sbin/nginx -s reload

签发完成后,改用排除 .well-known 的写法加回去:

location ~ /\.(?!well-known) {
    deny all;
    access_log off;
    log_not_found off;
}

错误 7:ACME 验证仍然 403(域名未备案)

现象: 删除 nginx 拦截规则后,domain-b.com 仍然返回 403。

原因: 域名 domain-b.com 尚未完成 ICP 备案,阿里云会拦截未备案域名通过 80/443 端口的 HTTP 请求。Let's Encrypt 的 HTTP-01 验证无法通过。

解决:


成功:domain-a.cn 证书签发

domain-a.cn 已完成备案,80 端口可正常访问,直接执行:

certbot --nginx -d domain-a.cn -d www.domain-a.cn

输出:

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/domain-a.cn/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/domain-a.cn/privkey.pem
This certificate expires on 2026-11-09.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Successfully deployed certificate for domain-a.cn to /usr/local/nginx/conf/vhost/domain-a.cn.conf
Successfully deployed certificate for www.domain-a.cn to /usr/local/nginx/conf/vhost/domain-a.cn.conf

重载 nginx 生效:

/usr/local/nginx/sbin/nginx -t && /usr/local/nginx/sbin/nginx -s reload

三、自动续期配置

Certbot 已自动配置定时续期任务。由于 nginx 为源码编译安装,需确保续期后自动重载 nginx:

# 验证自动续期
certbot renew --dry-run

# 添加续期后重载 nginx 的 hook
# 编辑 /etc/letsencrypt/renewal/domain-a.cn.conf,在 [renewalparams] 下添加:
# renew_hook = /usr/local/nginx/sbin/nginx -s reload

四、新增二级域名签发证书

方式一:扩展现有证书(推荐)

certbot --nginx -d domain-a.cn -d www.domain-a.cn -d 新域名.domain-a.cn

选择 expand (E),将新域名加入已有证书。

方式二:单独签发

certbot --nginx -d 新域名.domain-a.cn

前提条件:


五、关键经验总结

序号问题根因解决方案
1nginx 插件缺失yum 未装插件yum install python3-certbot-nginx
2cryptography 编译失败缺编译依赖装 gcc/openssl-devel/libffi-devel/python3-devel
3snap 初始化失败CentOS snapd 兼容性差放弃 snap,用 yum
4找不到 nginx 二进制源码安装不在 PATHln -sf /usr/local/nginx/sbin/nginx /usr/sbin/nginx
5找不到 nginx 配置配置路径非标准ln -sf /usr/local/nginx/conf /etc/nginx
6ACME 验证 403location ~ /\. 拦截 .well-known删除或改用 ~ /\.(?!well-known)
7ACME 验证仍 403域名未备案,云厂商拦截等 DNS-01 验证或等备案通过