本指南带你完成在 Nginx 上安装 SSL 证书的全过程——从上传文件到优化 TLS 设置和排查常见错误。适用于来自 GetHTTPS、Certbot 或任何其他来源的证书。
如果你还没有证书,5 分钟内免费获取一个。
前提条件
- Nginx 已安装并在 HTTP(端口 80)上提供网站服务
- Root/sudo 访问权限
- 证书文件 — 你需要两个:
fullchain.pem— 你的证书 + 中间证书链(合并)privkey.pem— 你的私钥
哪个文件是哪个? GetHTTPS 给你四个文件。Nginx 需要
fullchain.pem(不是cert.pem)和privkey.pem。单独使用cert.pem会导致”证书链不完整”错误,因为浏览器无法验证信任路径。证书格式详解 →
第一步:上传证书文件到服务器
将文件复制到安全目录:
# Create directory
sudo mkdir -p /etc/ssl/gethttps
# Copy files (from your local machine to the server)
sudo cp fullchain.pem /etc/ssl/gethttps/
sudo cp privkey.pem /etc/ssl/gethttps/
# Restrict private key permissions — only root should read it
sudo chmod 600 /etc/ssl/gethttps/privkey.pem
sudo chmod 644 /etc/ssl/gethttps/fullchain.pem
sudo chown root:root /etc/ssl/gethttps/*
如果通过 SCP 传输:
scp fullchain.pem privkey.pem user@your-server:/tmp/
# Then on the server:
sudo mv /tmp/fullchain.pem /tmp/privkey.pem /etc/ssl/gethttps/
第二步:配置 HTTPS server 块
编辑你网站的 Nginx 配置。文件通常位于:
/etc/nginx/sites-available/yourdomain.conf(Debian/Ubuntu)/etc/nginx/conf.d/yourdomain.conf(CentOS/RHEL)
完整推荐配置:
# HTTPS server block
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# ─── Certificate files ───────────────────────
ssl_certificate /etc/ssl/gethttps/fullchain.pem;
ssl_certificate_key /etc/ssl/gethttps/privkey.pem;
# ─── TLS protocol and ciphers ────────────────
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
# ─── Session caching (performance) ───────────
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# ─── OCSP stapling (faster verification) ─────
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# ─── Security headers ────────────────────────
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
# ─── Your site ───────────────────────────────
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# HTTP redirect block
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
各部分说明:
| 指令 | 用途 |
|---|---|
listen 443 ssl http2 | 端口 443 上的 HTTPS,启用 HTTP/2 |
ssl_certificate | 证书 + 证书链的路径 |
ssl_certificate_key | 私钥的路径 |
ssl_protocols | 仅 TLS 1.2 和 1.3(1.0/1.1 自 2020 年起已弃用) |
ssl_prefer_server_ciphers off | 让客户端选择最佳加密套件(现代最佳实践) |
ssl_session_cache | 缓存 TLS 会话——回访用户无需重新握手 |
ssl_session_tickets off | Tickets 可能削弱前向保密 |
ssl_stapling | 服务器预取 OCSP 响应——对客户端更快 |
Strict-Transport-Security | HSTS — 浏览器记住始终使用 HTTPS |
return 301 | HTTP 到 HTTPS 的永久重定向 |
第三步:测试配置
重新加载前务必测试:
sudo nginx -t
预期输出:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
如果测试失败,Nginx 会告诉你确切的行号和错误。常见错误:
- 文件路径中的拼写错误(
ssl_certifcate而不是ssl_certificate) - 指定路径的文件不存在
- 缺少分号
第四步:重新加载 Nginx
sudo systemctl reload nginx
使用 reload,不是 restart。 Reload 将新配置应用到新连接而不断开现有连接——零停机。
第五步:验证证书
浏览器检查
访问 https://yourdomain.com。点击锁头图标确认:
- 签发者:“Let’s Encrypt”(或你的证书颁发机构)
- 有效期:起止日期
- 域名:与你的 URL 匹配
命令行检查
# Full certificate details
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
# Check the full chain is present
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null \
| grep -E 'Verify return code|depth='
预期: Verify return code: 0 (ok) 和多个深度级别(你的证书 + 中间证书)。
在线检查
使用 SSL Labs Server Test 获取全面报告。它检查:
- 证书链有效性
- 协议支持(应该只显示 TLS 1.2 + 1.3)
- 加密套件强度
- 已知漏洞(BEAST、POODLE、Heartbleed)
- HSTS 配置
目标: 等级 A 或 A+。
如何续签
当你的证书即将过期时(Let’s Encrypt 的第 60 天/共 90 天):
- 从 GetHTTPS(或你的续签工具)获取新证书
- 替换文件:
sudo cp new-fullchain.pem /etc/ssl/gethttps/fullchain.pem sudo cp new-privkey.pem /etc/ssl/gethttps/privkey.pem - 重新加载 Nginx:
sudo systemctl reload nginx
无需重启。Nginx 在 reload 时读取新文件。完整续签指南 →
想要自动续签? 安装 Certbot 实现免管理续签:
sudo certbot --nginx -d example.com。它处理一切包括 Nginx 配置。
故障排查
”SSL: error:0B080074:x509 certificate routines”
原因: 你使用了 cert.pem 而不是 fullchain.pem。
修复: 将 ssl_certificate 改为指向 fullchain.pem,它包含你的证书和中间证书链:
ssl_certificate /etc/ssl/gethttps/fullchain.pem; # NOT cert.pem
“cannot load certificate key”
原因: 私钥文件权限错误、文件损坏或密钥与证书不匹配。
修复:
# Check permissions (should be 600)
ls -la /etc/ssl/gethttps/privkey.pem
# Verify the key is valid
sudo openssl ec -in /etc/ssl/gethttps/privkey.pem -check # For ECDSA
sudo openssl rsa -in /etc/ssl/gethttps/privkey.pem -check # For RSA
# Verify key matches certificate
sudo openssl x509 -noout -modulus -in /etc/ssl/gethttps/fullchain.pem | md5sum
sudo openssl rsa -noout -modulus -in /etc/ssl/gethttps/privkey.pem | md5sum
# Both hashes MUST match
“nginx: [emerg] bind() to 0.0.0.0:443 failed”
原因: 端口 443 已被另一个进程占用。
修复:
# Find what's using port 443
sudo ss -tlnp | grep 443
# Usually: another Nginx instance or Apache
sudo systemctl stop apache2 # If Apache is running
sudo systemctl reload nginx
HTTPS 正常但浏览器显示”不安全”
原因: 混合内容——你的页面通过 http:// 加载图片、脚本或 CSS。
修复: 打开 DevTools(F12)→ Console → 查找”Mixed Content”警告。将所有资源 URL 更新为 https:// 或相对路径。
“ERR_SSL_VERSION_OR_CIPHER_MISMATCH”
原因: 客户端不支持你的服务器提供的 TLS 版本或加密套件。
修复: 确保配置中包含 TLS 1.2(不只是 1.3):
ssl_protocols TLSv1.2 TLSv1.3; # NOT just TLSv1.3
证书显示为”不受信任”但文件正确
原因: 证书链不完整——fullchain.pem 缺少中间证书,或文件顺序错误。
修复: 通过连接你的证书 + 中间证书重建 fullchain.pem:
cat cert.pem chain.pem > fullchain.pem
顺序很重要:你的证书在前,然后是中间证书。
常见问题
HTTP 和 HTTPS 需要单独的配置文件吗?
不需要。将两个 server 块(端口 80 和 443)放在同一个文件中。HTTP 块仅用于重定向到 HTTPS。
应该使用 ssl on; 吗?
不应该。ssl on; 已弃用。使用 listen 443 ssl; 代替——listen 指令中的 ssl 参数是现代做法。
reload 和 restart 有什么区别?
reload 优雅地将新配置应用到新连接而不断开现有连接。restart 停止并启动进程,短暂断开所有连接。证书更改始终使用 reload。
可以用不同的证书服务多个域名吗?
可以。使用不同的 server_name、ssl_certificate 和 ssl_certificate_key 指令创建单独的 server 块。Nginx 使用 SNI(Server Name Indication)根据请求的主机名提供正确的证书。
Nginx 支持 ECDSA/ECC 证书吗?
支持。Nginx 处理 ECDSA 证书的方式与 RSA 完全相同——相同的指令,相同的文件格式。GetHTTPS 默认生成 ECDSA P-256(更小的密钥,更快的握手)。
如何启用 HTTP/2?
在 listen 指令中添加 http2:listen 443 ssl http2;。这已经包含在上面的推荐配置中。HTTP/2 需要 HTTPS——无法在明文 HTTP 上使用。