引言

在当前的网络环境中,HTTPS 已不再是“可选项”,而是保障网站安全、保护用户隐私、提升搜索引擎排名的“必需品”。Let’s Encrypt 项目的出现,极大地降低了获取和部署 SSL/TLS 证书的门槛。它提供免费、自动化、开放的证书颁发服务。

Certbot 是 Let’s Encrypt 官方推荐的客户端软件,能够极大地简化证书的申请、部署和续签过程。本文将系统性地探讨 Certbot 与 Nginx 集成的四种核心方案,并对每种方案进行详细的步骤拆解和利弊分析,帮助您根据具体场景选择最优策略。

前置条件

在开始之前,请确保您已满足以下所有条件:

  1. 一个完全限定的域名(FQDN):例如 yourdomain.com。本文将以此为例。
  2. DNS A/AAAA 记录:您的域名(包括 www 子域名,如果需要)必须有 A 记录(IPv4)或 AAAA 记录(IPv6)指向您服务器的公网 IP 地址。
  3. 服务器访问权限:拥有服务器的 root 或 sudo 权限。
  4. Nginx 已安装并运行:服务器上已成功安装 Nginx,并已配置好基本的 HTTP 服务。
  5. 防火墙配置:服务器的防火墙(如 ufw, firewalld, iptables 或云服务商的安全组)必须允许公网访问 80 端口(HTTP)和 443 端口(HTTPS)。这是 ACME 协议验证所必需的。

Certbot 安装

Certbot 的安装方式有多种,但官方目前首推使用 snap 进行安装。这种方式可以确保您获得最新版本的 Certbot,并能独立于系统包管理器进行更新,避免了依赖冲突。

以 Ubuntu/Debian 系统为例:

  1. 安装 Snapd

    sudo apt update
    sudo apt install snapd
    
  2. 确保 Snapd 已是最新版本

    sudo snap install core; sudo snap refresh core
    
  3. 安装 Certbot

    # 移除旧的 certbot-auto 和系统包安装的 certbot(如果有)
    sudo apt-get remove certbot
    
    # 通过 snap 安装 certbot
    sudo snap install --classic certbot
    
  4. 创建 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 的重定向。

操作步骤

  1. 运行 Certbot 命令
    假设您要为 yourdomain.comwww.yourdomain.com 申请证书。

    sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
    
  2. 交互式配置
    Certbot 会引导您完成几个步骤:

    • 输入您的电子邮件地址,用于接收紧急通知和证书到期提醒。
    • 同意 Let’s Encrypt 的服务条款。
    • 选择是否愿意与电子前哨基金会(EFF)分享您的电子邮件。
    • Certbot 会显示它找到的 Nginx 配置文件中的域名,并询问您是否要为这些域名申请证书。
    • 最后,它会询问是否将所有 HTTP 流量重定向到 HTTPS。强烈建议选择“Redirect”。
  3. 完成与验证
    如果一切顺利,您会看到成功消息,告知证书已成功部署,并给出了证书文件的存储路径(通常在 /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 就能完成验证。此方案只获取证书,不安装。

操作步骤

  1. 确认 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

  2. 运行 Certbot 命令
    使用 certonly 子命令表示只获取证书,不进行安装。使用 -w 指定 webroot 路径,-d 指定域名。

    sudo certbot certonly --webroot -w /var/www/html -d yourdomain.com -d www.yourdomain.com
    
  3. 手动配置 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;
        }
    }
    
  4. 测试并重载 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 挑战。验证完成后,这个临时服务器会自动关闭。

操作步骤

  1. 停止现有的 Web 服务器
    由于 standalone 模式需要占用 80 端口,您必须先停止正在使用该端口的 Nginx 服务。

    sudo systemctl stop nginx
    
  2. 运行 Certbot 命令

    sudo certbot certonly --standalone -d yourdomain.com -d www.yourdomain.com
    
  3. 手动配置 Nginx
    同方案二,获取证书后,您需要手动编写 Nginx 的 HTTPS 配置。

  4. 重新启动 Nginx
    配置完成后,启动 Nginx 服务。

    sudo systemctl start nginx
    

利弊分析

优点 (Pros) 缺点 (Cons)
不依赖现有 Web 服务器:即使服务器上没有安装或配置 Nginx,也能获取证书。 导致服务中断:在获取或续签证书期间,必须停止主 Web 服务,会造成网站短暂的停机。
设置简单:命令本身非常直接,无需关心 Web 服务器的内部配置。 续签复杂:默认的自动续签会失败,因为它无法自动停止 Nginx。必须使用 pre-hookpost-hook 脚本来自动化停止和启动 Nginx 的过程(详见续签部分)。

方案四:DNS-01 挑战 - 通配符证书与终极方案

这是最强大但也最复杂的方案。它通过修改 DNS 记录来验证域名所有权,是获取通配符证书(例如 *.yourdomain.com)的唯一方式。

工作原理

Certbot 会生成一个特定的字符串,并要求您将这个字符串以 TXT 记录的形式添加到您的域名 DNS 设置中(记录名为 _acme-challenge.yourdomain.com)。Let’s Encrypt 的服务器会通过 DNS 查询来验证这条记录。此方案不依赖于服务器本身是否能从公网访问,也无需开放 80/443 端口。

操作步骤 - 手动模式 (--manual)

此方法适用于不支持 API 的 DNS 提供商,或一次性获取证书。

  1. 运行 Certbot 命令

    # 注意:申请通配符证书时,根域名也需要一并加入
    sudo certbot certonly --manual --preferred-challenges dns -d "*.yourdomain.com" -d yourdomain.com
    
  2. 按提示操作
    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.
    
  3. 添加 DNS 记录
    登录您的域名注册商或 DNS 服务提供商(如 Cloudflare, GoDaddy, NameSilo 等)的控制面板,为 yourdomain.com 添加一条 TXT 记录。

    • 主机/名称 (Host/Name): _acme-challenge
    • 值/内容 (Value/Content): Certbot 提供的随机字符串
  4. 验证并完成
    添加记录后,需要等待几分钟让 DNS 记录在全球范围内生效(DNS 传播)。您可以使用 dig 命令或在线 DNS-Checker 工具来确认。

    dig -t txt _acme-challenge.yourdomain.com
    

    确认记录生效后,回到 Certbot 的终端窗口,按回车键继续。Certbot 会完成验证并颁发证书。

操作步骤 - 自动模式 (使用 DNS 插件)

手动模式无法自动续签。要实现自动化,必须使用 DNS 插件,前提是您的 DNS 提供商支持 API。以 Cloudflare 为例。

  1. 安装 DNS 插件

    sudo snap install certbot-dns-cloudflare
    
  2. 获取 API 凭证
    登录 Cloudflare,进入 “My Profile” -> “API Tokens”,创建一个具有 “Zone:DNS:Edit” 权限的 API Token。

  3. 创建凭证文件
    创建一个包含 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
    
  4. 运行 Certbot 命令

    sudo certbot certonly \
      --dns-cloudflare \
      --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
      -d "*.yourdomain.com" \
      -d yourdomain.com
    

    Certbot 会使用 API 自动完成 TXT 记录的添加和删除,整个过程全自动。

  5. 手动配置 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 部署策略,从而构建一个更安全的网络服务。