Nginx 与 Certbot :全方位解析 HTTPS 证书获取与自动化续签
引言
在当前的网络环境中,HTTPS 已不再是“可选项”,而是保障网站安全、保护用户隐私、提升搜索引擎排名的“必需品”。Let’s Encrypt 项目的出现,极大地降低了获取和部署 SSL/TLS 证书的门槛。它提供免费、自动化、开放的证书颁发服务。
Certbot 是 Let’s Encrypt 官方推荐的客户端软件,能够极大地简化证书的申请、部署和续签过程。本文将系统性地探讨 Certbot 与 Nginx 集成的四种核心方案,并对每种方案进行详细的步骤拆解和利弊分析,帮助您根据具体场景选择最优策略。
前置条件
在开始之前,请确保您已满足以下所有条件:
- 一个完全限定的域名(FQDN):例如
yourdomain.com
。本文将以此为例。 - DNS A/AAAA 记录:您的域名(包括
www
子域名,如果需要)必须有 A 记录(IPv4)或 AAAA 记录(IPv6)指向您服务器的公网 IP 地址。 - 服务器访问权限:拥有服务器的 root 或 sudo 权限。
- Nginx 已安装并运行:服务器上已成功安装 Nginx,并已配置好基本的 HTTP 服务。
- 防火墙配置:服务器的防火墙(如 ufw, firewalld, iptables 或云服务商的安全组)必须允许公网访问 80 端口(HTTP)和 443 端口(HTTPS)。这是 ACME 协议验证所必需的。
Certbot 安装
Certbot 的安装方式有多种,但官方目前首推使用 snap
进行安装。这种方式可以确保您获得最新版本的 Certbot,并能独立于系统包管理器进行更新,避免了依赖冲突。
以 Ubuntu/Debian 系统为例:
-
安装 Snapd
sudo apt update sudo apt install snapd
-
确保 Snapd 已是最新版本
sudo snap install core; sudo snap refresh core
-
安装 Certbot
# 移除旧的 certbot-auto 和系统包安装的 certbot(如果有) sudo apt-get remove certbot # 通过 snap 安装 certbot sudo snap install --classic certbot
-
创建 Certbot 命令的软链接
sudo ln -s /snap/bin/certbot /usr/bin/certbot
至此,Certbot 已成功安装并准备就绪。
核心概念:ACME 挑战 (ACME Challenge)
要理解不同方案的区别,必须先理解 Let’s Encrypt 的验证机制。为了确认您确实拥有对域名的控制权,Let’s Encrypt 的 ACME (Automated Certificate Management Environment) 协议会发起“挑战”。Certbot 主要使用以下两种挑战类型:
- HTTP-01 挑战:Let’s Encrypt 要求 Certbot 在您的 Web 服务器上放置一个包含特定内容的文件,路径通常为
http://yourdomain.com/.well-known/acme-challenge/<TOKEN>
。然后,Let’s Encrypt 的服务器会通过公网访问这个 URL。如果能成功获取并验证文件内容,就证明您控制着该域名对应的服务器。 - DNS-01 挑战:Let’s Encrypt 要求 Certbot 在您的域名 DNS 记录中添加一个包含特定内容的 TXT 记录。然后,Let’s Encrypt 的服务器会查询该 DNS 记录。如果能成功获取并验证,就证明您控制着该域名的 DNS 解析。
接下来,我们将围绕这两种挑战类型,展开四种具体的操作方案。
方案一:Nginx 插件 (--nginx
) - 全自动模式
这是最简单、最受推荐的方案,尤其适合标准配置和初学者。Certbot 会自动检测并修改您的 Nginx 配置文件,完成证书的获取、安装和后续的自动续签配置。
工作原理
--nginx
插件会解析 Nginx 的配置文件(通常是 /etc/nginx/nginx.conf
及其 include
的文件),找到与您申请证书的域名匹配的 server
块。在验证阶段,它会临时修改该 server
块,添加一个专门用于响应 ACME 挑战的 location
规则。验证成功后,它会再次修改该 server
块,配置好 SSL 证书路径、开启 HTTPS,并通常会添加一个从 HTTP 到 HTTPS 的重定向。
操作步骤
-
运行 Certbot 命令
假设您要为yourdomain.com
和www.yourdomain.com
申请证书。sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
-
交互式配置
Certbot 会引导您完成几个步骤:- 输入您的电子邮件地址,用于接收紧急通知和证书到期提醒。
- 同意 Let’s Encrypt 的服务条款。
- 选择是否愿意与电子前哨基金会(EFF)分享您的电子邮件。
- Certbot 会显示它找到的 Nginx 配置文件中的域名,并询问您是否要为这些域名申请证书。
- 最后,它会询问是否将所有 HTTP 流量重定向到 HTTPS。强烈建议选择“Redirect”。
-
完成与验证
如果一切顺利,您会看到成功消息,告知证书已成功部署,并给出了证书文件的存储路径(通常在/etc/letsencrypt/live/yourdomain.com/
)。此时,您可以检查 Nginx 的相关配置文件(例如
/etc/nginx/sites-available/default
),会发现 Certbot 自动添加了如下内容:listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot # ... # 在原有的 server 块中可能还会添加重定向规则 if ($scheme != "https") { return 301 https://$host$request_uri; } # managed by Certbot
利弊分析
优点 (Pros) | 缺点 (Cons) |
---|---|
高度自动化:一键完成证书获取、安装和 Nginx 配置,无需手动编辑文件。 | 侵入式配置:会自动修改您的 Nginx 配置文件。对于有严格配置管理策略或使用自动化部署工具(如 Ansible)的团队来说,这可能不是理想选择。 |
用户友好:交互式引导,对新手非常友好。 | 兼容性问题:对于非标准或极其复杂的 Nginx 配置,Certbot 的解析器可能会失败或产生意想不到的修改。 |
无缝续签:自动配置的续签任务可以完美工作,无需额外干预。 | 依赖 Nginx 运行:在执行过程中,Nginx 必须正在运行且配置正确。 |
方案二:Webroot 插件 (--webroot
) - 非侵入式模式
此方案适用于不希望 Certbot 自动修改 Nginx 配置文件的用户。您需要手动配置 Nginx,但证书的获取和续签过程依然是自动化的。
工作原理
--webroot
插件执行 HTTP-01 挑战。您需要告诉 Certbot 您的网站根目录(root
指令在 Nginx 配置中的路径)。Certbot 会在该目录下创建 .well-known/acme-challenge/
文件夹并放入验证文件。只要您的 Nginx 配置能正确地服务于该目录下的静态文件,Let’s Encrypt 就能完成验证。此方案只获取证书,不安装。
操作步骤
-
确认 Nginx 配置
确保您的 Nginx 配置文件中有一个处理 HTTP 请求的server
块,并且明确指定了root
目录。一个标准的配置示例 (
/etc/nginx/sites-available/yourdomain.com
):server { listen 80; server_name yourdomain.com www.yourdomain.com; root /var/www/html; # 确保这个目录存在且 Nginx 有权限读取 index index.html index.htm; # 确保 ACME 挑战可以被访问 location ~ /.well-known/acme-challenge/ { allow all; } }
运行
sudo nginx -t
确保配置无误,然后sudo systemctl reload nginx
。 -
运行 Certbot 命令
使用certonly
子命令表示只获取证书,不进行安装。使用-w
指定 webroot 路径,-d
指定域名。sudo certbot certonly --webroot -w /var/www/html -d yourdomain.com -d www.yourdomain.com
-
手动配置 Nginx 以使用证书
证书获取成功后,您需要手动编辑 Nginx 配置文件,添加一个处理 HTTPS 的server
块。一个完整的 HTTPS 配置示例:
# HTTP server block - for redirection server { listen 80; server_name yourdomain.com www.yourdomain.com; # Redirect all HTTP traffic to HTTPS return 301 https://$host$request_uri; } # HTTPS server block server { listen 443 ssl http2; server_name yourdomain.com www.yourdomain.com; root /var/www/html; index index.html index.htm; # SSL configuration ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; # Recommended SSL settings from Certbot/Mozilla include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { try_files $uri $uri/ =404; } location ~ /.well-known/acme-challenge/ { allow all; } }
-
测试并重载 Nginx
sudo nginx -t sudo systemctl reload nginx
利弊分析
优点 (Pros) | 缺点 (Cons) |
---|---|
非侵入式:完全不修改您的 Nginx 配置文件,保持配置文件的整洁和可控性。 | 需要手动配置:首次设置时,需要手动编写 HTTPS 相关的 Nginx 配置。 |
零停机:在证书获取和续签过程中,Nginx 无需停止或重载,服务不会中断。 | 依赖 Web 服务:必须有一个正在运行的 Web 服务器来响应 HTTP-01 挑战。 |
通用性强:不仅限于 Nginx,可与任何能够提供静态文件服务的 Web 服务器(如 Apache)配合使用。 | 配置要求:Nginx 配置必须正确设置 root 目录,并允许访问 .well-known 路径。 |
方案三:Standalone 插件 (--standalone
) - 独立模式
此方案适用于服务器上没有运行 Web 服务器,或者可以临时停止现有 Web 服务器的场景。
工作原理
--standalone
插件会自己启动一个临时的、轻量级的 Web 服务器,专门监听 80 端口来响应 Let’s Encrypt 的 HTTP-01 挑战。验证完成后,这个临时服务器会自动关闭。
操作步骤
-
停止现有的 Web 服务器
由于standalone
模式需要占用 80 端口,您必须先停止正在使用该端口的 Nginx 服务。sudo systemctl stop nginx
-
运行 Certbot 命令
sudo certbot certonly --standalone -d yourdomain.com -d www.yourdomain.com
-
手动配置 Nginx
同方案二,获取证书后,您需要手动编写 Nginx 的 HTTPS 配置。 -
重新启动 Nginx
配置完成后,启动 Nginx 服务。sudo systemctl start nginx
利弊分析
优点 (Pros) | 缺点 (Cons) |
---|---|
不依赖现有 Web 服务器:即使服务器上没有安装或配置 Nginx,也能获取证书。 | 导致服务中断:在获取或续签证书期间,必须停止主 Web 服务,会造成网站短暂的停机。 |
设置简单:命令本身非常直接,无需关心 Web 服务器的内部配置。 | 续签复杂:默认的自动续签会失败,因为它无法自动停止 Nginx。必须使用 pre-hook 和 post-hook 脚本来自动化停止和启动 Nginx 的过程(详见续签部分)。 |
方案四:DNS-01 挑战 - 通配符证书与终极方案
这是最强大但也最复杂的方案。它通过修改 DNS 记录来验证域名所有权,是获取通配符证书(例如 *.yourdomain.com
)的唯一方式。
工作原理
Certbot 会生成一个特定的字符串,并要求您将这个字符串以 TXT 记录的形式添加到您的域名 DNS 设置中(记录名为 _acme-challenge.yourdomain.com
)。Let’s Encrypt 的服务器会通过 DNS 查询来验证这条记录。此方案不依赖于服务器本身是否能从公网访问,也无需开放 80/443 端口。
操作步骤 - 手动模式 (--manual
)
此方法适用于不支持 API 的 DNS 提供商,或一次性获取证书。
-
运行 Certbot 命令
# 注意:申请通配符证书时,根域名也需要一并加入 sudo certbot certonly --manual --preferred-challenges dns -d "*.yourdomain.com" -d yourdomain.com
-
按提示操作
Certbot 会暂停并显示需要添加的 TXT 记录的名称和值。Please deploy a DNS TXT record under the name _acme-challenge.yourdomain.com with the following value: <A_LONG_RANDOM_STRING> Before continuing, verify the record is deployed.
-
添加 DNS 记录
登录您的域名注册商或 DNS 服务提供商(如 Cloudflare, GoDaddy, NameSilo 等)的控制面板,为yourdomain.com
添加一条 TXT 记录。- 主机/名称 (Host/Name):
_acme-challenge
- 值/内容 (Value/Content): Certbot 提供的随机字符串
- 主机/名称 (Host/Name):
-
验证并完成
添加记录后,需要等待几分钟让 DNS 记录在全球范围内生效(DNS 传播)。您可以使用dig
命令或在线 DNS-Checker 工具来确认。dig -t txt _acme-challenge.yourdomain.com
确认记录生效后,回到 Certbot 的终端窗口,按回车键继续。Certbot 会完成验证并颁发证书。
操作步骤 - 自动模式 (使用 DNS 插件)
手动模式无法自动续签。要实现自动化,必须使用 DNS 插件,前提是您的 DNS 提供商支持 API。以 Cloudflare 为例。
-
安装 DNS 插件
sudo snap install certbot-dns-cloudflare
-
获取 API 凭证
登录 Cloudflare,进入 “My Profile” -> “API Tokens”,创建一个具有 “Zone:DNS:Edit” 权限的 API Token。 -
创建凭证文件
创建一个包含 API Token 的文件,并设置严格的权限。sudo mkdir -p /etc/letsencrypt/ sudo nano /etc/letsencrypt/cloudflare.ini
文件内容如下:
# Cloudflare API credentials used by Certbot dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
设置权限,确保只有 root 用户可读:
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
-
运行 Certbot 命令
sudo certbot certonly \ --dns-cloudflare \ --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \ -d "*.yourdomain.com" \ -d yourdomain.com
Certbot 会使用 API 自动完成 TXT 记录的添加和删除,整个过程全自动。
-
手动配置 Nginx
同方案二,获取证书后,您需要手动编写 Nginx 的 HTTPS 配置。
利弊分析
优点 (Pros) | 缺点 (Cons) |
---|---|
支持通配符证书:这是获取 *.yourdomain.com 证书的唯一方法,极大简化了多子域名的管理。 |
配置复杂:特别是自动模式,需要处理 API 凭证,设置过程比其他方案复杂。 |
不依赖服务器公网 IP:服务器可以位于内网、NAT 之后,或防火墙严格限制了 80/443 端口。 | 依赖 DNS 提供商:需要 DNS 提供商支持 API 才能实现自动化续签。手动模式无法自动续签,非常不便。 |
安全性:验证过程不暴露服务器的任何端口。 | 安全风险:将具有 DNS 修改权限的 API 凭证存储在服务器上,如果服务器被攻破,可能导致 DNS 记录被篡改,存在安全风险。 |
证书续订 (Renewal)
Certbot 在首次成功获取证书时,会自动在系统中设置一个定时任务(通过 cron job 或 systemd timer)来定期检查并续订即将到期的证书。
-
测试续订:您可以随时通过“演习”来测试续订配置是否正确,这不会影响线上证书。
sudo certbot renew --dry-run
-
不同方案的续订行为:
--nginx
和--webroot
:自动续订通常会无缝工作,因为它们所依赖的条件(Nginx 运行中或 webroot 路径可访问)在续订时通常也是满足的。--standalone
:默认的certbot renew
会失败,因为 Nginx 正占用 80 端口。必须在续订命令中加入钩子(hooks)来临时停止和重启 Nginx。
# 可以将此命令放入 cron 任务中,或直接修改 Certbot 的续订配置文件 sudo certbot renew --pre-hook "systemctl stop nginx" --post-hook "systemctl start nginx"
更好的方法是修改
/etc/letsencrypt/renewal/yourdomain.com.conf
文件,在[renewalparams]
部分添加:pre_hook = systemctl stop nginx post_hook = systemctl start nginx
- DNS 插件:自动续订会无缝工作。
- 手动 DNS:无法自动续订。您必须在证书到期前(通常是 90 天周期)重复手动操作。因此,在生产环境中,强烈不推荐使用手动 DNS 模式。
总结与推荐
方案 | 自动化程度 | 服务中断 | 通配符支持 | 配置侵入性 | 复杂度 | 推荐场景 |
---|---|---|---|---|---|---|
Nginx 插件 | 全自动 | 无 | 否 | 高 | 低 | 标准 Nginx 环境、新手用户、追求便捷的首选。 |
Webroot 插件 | 半自动 | 无 | 否 | 无 | 中 | 希望保持 Nginx 配置纯净、使用配置管理工具的专业用户。 |
Standalone 插件 | 半自动 | 是 | 否 | 无 | 中 | 无 Web 服务器或可接受短暂中断的非关键服务。 |
DNS 插件 | 全自动 | 无 | 是 | 无 | 高 | 需要通配符证书、服务器在内网或防火墙严格限制的场景。 |
最终建议:
- 对于绝大多数标准网站,Nginx 插件 (
--nginx
) 是最快、最省心的选择。 - 对于重视配置控制的开发者和系统管理员,Webroot 插件 (
--webroot
) 是最佳实践。 - 当你需要为大量动态子域名提供 HTTPS 时,DNS 插件是唯一的、也是最强大的解决方案。
- 尽量避免使用 Standalone 插件 和 手动 DNS 模式,除非是在非常特殊的、非生产的环境中。
通过理解每种方案的内在逻辑和权衡其利弊,您可以为您的 Nginx 服务器选择最合适、最可靠的 HTTPS 部署策略,从而构建一个更安全的网络服务。