在 Nginx 上安装 SSL 证书 — 分步指南

Nginx 是全球最受欢迎的网页服务器之一,但在其上安装 SSL 证书与 Apache 差异显著。本指南涵盖从 CA 购买的商业 SSL 证书 (DV/OV) 和通过 Certbot 的免费 Let's Encrypt 证书 — 包括 HTTP 到 HTTPS 重定向和自动续期。

先决条件:安装了 Nginx 的 Ubuntu 20.04/22.04 VPS、DNS A 记录已指向此服务器 IP 的域名,以及 root 或 sudo 访问权限。

第 1 部分 — 开始前:您需要什么

安装 SSL 前验证以下项目:

第 2 部分 — 在 Nginx 上安装商业 SSL 证书

从 CA(如 RapidSSL、DigiCert)购买 SSL 后,您将通过电子邮件收到证书文件。按照以下步骤操作:

2.1 上传和存储证书文件

# 为 SSL 文件创建安全目录
sudo mkdir -p /etc/nginx/ssl/example.com

# 复制您的证书和密钥文件
sudo cp your_domain.crt /etc/nginx/ssl/example.com/fullchain.pem
sudo cp your_private.key /etc/nginx/ssl/example.com/privkey.pem

# 如果 CA 提供了中间证书,将它们捆绑在一起
cat your_domain.crt intermediate.crt > /etc/nginx/ssl/example.com/fullchain.pem

# 保护权限
sudo chmod 600 /etc/nginx/ssl/example.com/privkey.pem
sudo chmod 644 /etc/nginx/ssl/example.com/fullchain.pem

2.2 配置 Nginx 服务器块

sudo nano /etc/nginx/sites-available/example.com
server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate     /etc/nginx/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;

    # 仅使用安全的 SSL 协议
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    root /var/www/example.com;
    index index.html index.php;

    location / {
        try_files $uri $uri/ =404;
    }
}

# 重定向 HTTP → HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}
# 启用站点
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

# 重新加载前测试配置
sudo nginx -t

# 如果测试通过,重新加载
sudo systemctl reload nginx

第 3 部分 — 使用 Certbot 在 Nginx 上安装 Let's Encrypt

Let's Encrypt 提供免费的、生产级 SSL。Certbot 自动处理一切 — 从请求证书到更新您的服务器块。

3.1 安装 Certbot

sudo apt update
sudo apt install certbot python3-certbot-nginx -y

3.2 自动获取证书

# Certbot 将自动编辑您的 Nginx 配置并设置重定向
sudo certbot --nginx -d example.com -d www.example.com

Certbot 要求您提供电子邮件地址和同意条款,然后执行 ACME 挑战以验证域名所有权。成功后,它会更新您的 Nginx 配置以立即提供 HTTPS。

提示:--nginx 插件会自动编辑您的服务器块、设置 SSL 路径并添加 HTTP 到 HTTPS 重定向 — 无需手动配置。

第 4 部分 — 手动设置 HTTP→HTTPS 重定向

如果您想自己控制重定向而不让 Certbot 修改您的配置,请添加以下服务器块:

server {
    listen 80;
    server_name example.com www.example.com;
    # 301 = 永久重定向(对 SEO 有利)
    return 301 https://$host$request_uri;
}

⚠️ 避免重定向循环:切勿将 return 301 放在 listen 443 服务器块内。始终将端口 80 和端口 443 保持在单独的服务器块中。

第 5 部分 — 使用 openssl 验证 SSL

安装后,确认 SSL 正常工作:

# 检查提供的证书
openssl s_client -connect example.com:443 -servername example.com

# 检查过期日期
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

# 使用 curl 进行快速 HTTP 测试
curl -I https://example.com

确认响应显示 HTTP/2 200 且没有证书错误。若要获得完整的安全等级,请通过 SSL Labs (ssllabs.com/ssltest) 运行您的域名。

第 6 部分 — 为 Let's Encrypt 启用自动续期

Let's Encrypt 证书每 90 天过期一次。Certbot 自动安装 systemd 计时器或 cron 任务。验证它是否有效:

# 进行空运行以测试续期而不实际续期
sudo certbot renew --dry-run

# 检查 Certbot 注册的计时器
systemctl list-timers | grep certbot

最佳实践:添加部署挂钩,以便在每次续期后重新加载 Nginx:sudo certbot renew --deploy-hook "systemctl reload nginx"

使用 Certbot 安装 Let's Encrypt — 详细演练

如果您想确切了解 Certbot 的工作原理,或在自动流程中遇到问题,下面的步骤解释了从开始到在 Nginx 上获得工作证书的一切。Let's Encrypt 是一个免费的、受所有主流浏览器信任的证书,非常适合需要 HTTPS 而无需付费的普通网站。

步骤 1 — 准备基本的端口 80 服务器块

在运行 Certbot 之前,您需要一个在端口 80 上应答且 server_name 与您的域名匹配的服务器块,因为 Certbot 使用 HTTP-01 挑战在端口 80 上将验证文件放入您的网络根目录。

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
# 测试配置并重新加载,使 Nginx 提供此 server_name
sudo nginx -t && sudo systemctl reload nginx

步骤 2 — 在自动模式下运行 Certbot

--nginx 插件读取您的 Nginx 配置,找到其 server_name 与域名匹配的服务器块,并将其重新编写为自动提供 HTTPS:

sudo certbot --nginx -d example.com -d www.example.com \
  --agree-tos -m [email protected] --redirect

步骤 3 — Webroot 模式(当您自己管理配置时)

如果您想保持对 Nginx 配置的完全控制,请使用 webroot 模式,以便 Certbot 仅获取证书而不会触及您的配置:

sudo certbot certonly --webroot -w /var/www/example.com \
  -d example.com -d www.example.com

证书文件将位于 /etc/letsencrypt/live/example.com/,包含 fullchain.pem(证书 + 链)和 privkey.pem(私钥),您可以在服务器块中直接引用这些文件。

提示:与需要端口 80 空闲的 standalone 模式不同,webroot 模式不需要在发布期间停止 Nginx — 非常适合已在运行的生产服务器。

在 Nginx 上详细安装购买的 SSL(完整链)

来自 CA 的商业 SSL (DV/OV/EV) 通常以多个文件的形式提供:域名证书 (.crt)、中间/链证书 (.ca-bundle 或 chain.crt) 和用您的 CSR 生成的私钥 (.key)。在 Nginx 上最重要的是您必须将域名证书和中间证书合并到一个完整链文件中 — 否则您会收到不完整的链。

按正确顺序构建完整链

顺序很重要:域名证书必须首先出现,然后是中间证书(绝不包括根 CA):

# 顺序:域名证书第一,然后是中间证书
cat your_domain.crt intermediate.ca-bundle > fullchain.pem

# 移到位置并锁定权限
sudo mv fullchain.pem /etc/nginx/ssl/example.com/fullchain.pem
sudo cp your_private.key /etc/nginx/ssl/example.com/privkey.pem
sudo chmod 600 /etc/nginx/ssl/example.com/privkey.pem

在服务器块中引用它

将 ssl_certificate 指向完整链文件,将 ssl_certificate_key 指向私钥,并使用推荐的安全值:

server {
    listen 443 ssl;
    http2 on;
    server_name example.com www.example.com;

    ssl_certificate     /etc/nginx/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;

    root /var/www/example.com;
    index index.html index.php;
}

⚠️ 不要在完整链文件中包含根 CA:某些 CA 也提供根证书,但浏览器的信任存储中已经有根证书。添加根只会导致握手变得复杂。仅包含域名证书加上中间证书。

在 Nginx 上强制 HTTPS(使用 return 301)和启用 HSTS

安装 SSL 后,关键步骤是强制每个访问者使用 HTTPS。分两层进行:首先使用 return 301 重定向所有端口 80 请求,然后启用 HSTS(HTTP 严格传输安全),以便浏览器记住仅使用 HTTPS — 即使用户输入 http://。

使用 return 301 重定向 HTTP→HTTPS

# 仅针对端口 80 的单独服务器块
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

在 listen-443 块中启用 HSTS

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    # 强制 HTTPS 一年,包括子域名
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # ... ssl_certificate 和其他值如上所示 ...
}

⚠️ 小心启用 HSTS:一旦浏览器收到 HSTS 头,它就会在 max-age 期间"锁定"到 HTTPS。如果您的 SSL 过期或您在该窗口期间删除 HTTPS,站点将无法访问。从短 max-age 开始(例如 max-age=300),然后扩展到一年,并且在每个子域名都支持 HTTPS 之前不要添加 preload。

测试、续期和常见问题

安装后,彻底测试链和连接,设置续期,并了解如何修复 Nginx 上最常出现的问题。

测试链和过期日期

# 验证链是否完整(没有"无法获得本地发行者")
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | grep -i "verify"

# 检查过期日期
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

让 Let's Encrypt 自动续期

# 进行空运行以测试续期并在成功时自动重新加载 Nginx
sudo certbot renew --dry-run
sudo certbot renew --deploy-hook "systemctl reload nginx"

常见问题和修复方法

症状 原因 + 修复
链不完整 / 无法获得本地发行者 中间证书从 ssl_certificate 中缺失 — 将域名证书 + 中间证书绑定到 fullchain.pem,然后重新加载。
无法访问 https / 连接被拒绝 防火墙中未打开端口 443 — 运行 ufw allow 443 并确认 listen 443 ssl; 在服务器块中。
混合内容(无绿色挂锁) 页面通过 http:// 加载资源 — 将图像/CSS/JS 链接更改为 https:// 或相对路径。
重定向循环 (ERR_TOO_MANY_REDIRECTS) return 301 位于 listen 443 块内 — 仅将其移到端口 80 块。

Nginx 上的 SSL — 设置检查清单

  1. 确认 DNS A 记录指向您的服务器 IP。
  2. 在 UFW 中打开端口 80 和 443。
  3. 使用正确的权限 (600/644) 存储证书和密钥文件。
  4. 在服务器块中设置 ssl_certificate 和 ssl_certificate_key。
  5. 为 HTTP 重定向添加一个单独的端口 80 服务器块。
  6. 始终在重新加载前运行 nginx -t。
  7. 使用 openssl s_client 或 SSL Labs 测试。
  8. 对于 Let's Encrypt:设置一个 --deploy-hook 以在续期后自动重新加载 Nginx。

常见问题 (FAQ)

免费的 Let's Encrypt 与 Nginx 上购买的 SSL 有何不同?

Nginx 设置几乎相同 — 两者都使用 ssl_certificate 和 ssl_certificate_key。区别在于 Let's Encrypt 是免费的,发布有效期为 90 天且具有自动续期的 DV 证书,而购买的 SSL 提供有效期为一年且具有 CA 保证的 DV/OV/EV 选项。AsiaGB DV 证书起价为 1,000 泰铢/年,免费的 Let's Encrypt 也可在我们的服务器上使用。

安装后浏览器为什么仍然警告链不完整?

因为 Nginx 的 ssl_certificate 必须指向一个结合了域名证书和中间证书的文件(完整链)— 不像 Apache 可以引用单独的链文件。运行 cat your_domain.crt intermediate.crt > fullchain.pem,将 ssl_certificate 指向该文件,然后重新加载 Nginx。

更改证书后我需要重新启动或重新加载 Nginx 吗?

sudo systemctl reload nginx 就足够了 — 无需重新启动。重新加载会加载新配置和证书,而不会中断活跃连接,您应该始终在重新加载前运行 sudo nginx -t 来检查语法。

我如何避免忘记证书每 90 天过期一次?

Certbot 在安装时自动安装 systemd 计时器;使用 systemctl list-timers | grep certbot 检查它,并添加 --deploy-hook "systemctl reload nginx" 使得 Nginx 在续期后立即加载新证书。对于购买的一年期 SSL,AsiaGB 会提前发送过期提醒。

为您的网站购买 SSL 证书

AsiaGB 提供 RapidSSL、GeoTrust 和 DigiCert 证书,起价为 1,000 泰铢/年。受全球 CA 信任,易于安装,并享有专家支持。

查看 SSL 计划