nginx 反向代理 + Let’s Encrypt:生产环境 HTTPS 完整配置
这篇教程会带你用 nginx 给 WordPress 站点配 HTTPS,包含自动续期、HSTS、性能优化。看完之后你能直接复制粘贴到自己的服务器上。
前置条件
- 一台 Linux 服务器(Ubuntu 22.04 或 Debian 12 推荐)
- 一个域名,DNS 已经解析到服务器 IP
- nginx 已安装(
nginx -v应有输出) - 80 和 443 端口没被占用
安装 acme.sh(自动签发 Let’s Encrypt 证书)
acme.sh 比官方 certbot 简单,不依赖 Python:
curl https://get.acme.sh | sh -s email=your@email.com
source ~/.bashrc
acme.sh --version
安装完成后 ~/.acme.sh/ 是工作目录,所有证书都存在这里。
签发第一个证书
最简单的方式是 HTTP 验证(acme.sh 在你服务器上启动一个临时服务,Let’s Encrypt 来访问):
acme.sh --issue -d yourdomain.com -d www.yourdomain.com --nginx
--nginx 会自动读取你的 nginx vhost,找到 server_name 匹配的块做验证。
签发成功后证书会存到:
~/.acme.sh/yourdomain.com/
├── fullchain.cer # 服务器证书 + 中间证书
├── yourdomain.com.cer
├── yourdomain.com.key
└── ca.cer
安装证书到 nginx 目录
不要直接 cp,用 acme.sh 的 --install-cert 命令,它会自动创建 reload hook:
acme.sh --install-cert -d yourdomain.com \
--cert-file /etc/nginx/ssl/yourdomain.com.crt \
--key-file /etc/nginx/ssl/yourdomain.com.key \
--fullchain-file /etc/nginx/ssl/yourdomain.com.fullchain.crt \
--reloadcmd "systemctl reload nginx"
这样以后每次快过期时,acme.sh 会自动重新签发并 reload nginx。
nginx vhost 配置(HTTPS + 性能)
完整的 /etc/nginx/conf.d/yourdomain.com.conf:
# 强制 HTTPS
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
HTTPS server
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
# SSL 证书
ssl_certificate /etc/nginx/ssl/yourdomain.com.fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;
# SSL 协议 + 加密套件(强安全)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# HSTS(强制浏览器用 HTTPS)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 根目录
root /www/wwwroot/yourdomain.com;
index index.php index.html;
# WordPress 路由
location / {
try_files $uri $uri/ /index.php?$args;
}
# 静态资源缓存 + CORS
location ~ \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000";
access_log off;
}
# PHP-FPM(BT 面板用 sock,其他系统用 127.0.0.1:9000)
location ~ \.php$ {
include fastcgi-php.conf;
fastcgi_pass unix:/tmp/php-cgi-82.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 60s;
}
# 拒绝访问敏感文件
location ~ /\.(ht|git|env) {
deny all;
}
# WordPress 主题静态资源(如果是 Sage 11 主题)
location ^~ /app/themes/sage/public/build/ {
expires 30d;
add_header Cache-Control "public, max-age=2592000";
access_log off;
}
# 安全 headers
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; img-src 'self' data: https:; font-src 'self' https://cdn.jsdelivr.net;" always;
# 日志
access_log /var/log/nginx/yourdomain.com.access.log;
error_log /var/log/nginx/yourdomain.com.error.log;
}
启用 HTTP/2(性能提升 30%+)
新版 nginx 已经默认开启 HTTP/2(在 listen 后加 http2)。检查:
nginx -V 2>&1 | grep -o 'http_v2_module'
测试
# 1. nginx 配置语法检查
nginx -t
2. 重载
systemctl reload nginx
3. 测试 HTTPS
curl -I https://yourdomain.com
4. SSL Labs 测试(A 级评分)
https://www.ssllabs.com/ssltest/analyze.html?d=yourdomain.com
性能优化(进阶)
启用 OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/yourdomain.com.fullchain.crt;
resolver 8.8.8.8 8.8.4.4 valid=300s;
Brotli 压缩(比 gzip 再省 20%)
# Ubuntu/Debian
apt install nginx-module-brotli
# /etc/nginx/nginx.conf
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
在 http {} 块里
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
启用 HTTP/3(QUIC,最快)
需要 nginx 1.25+,并编译 quiche:
git clone https://github.com/cloudflare/quiche
cd quiche
cargo build --release --features=openssl
然后 nginx listen 加 quic:
listen 443 ssl http2;
listen 443 quic;
add_header Alt-Svc 'h3=":443"; ma=86400';
自动续期
acme.sh 默认会创建一个 cron 任务每天检查一次,快过期(30 天内)时自动重新签发:
crontab -l | grep acme
0 0 "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
如果你修改了 vhost(新增域名),记得手动跑一次:
acme.sh --renew -d yourdomain.com --force
常见问题
1. nginx reload 失败
通常是配置语法错。先 nginx -t 检查:
nginx -t
nginx: [emerg] unknown directive "..." in /etc/nginx/conf.d/xxx.conf:23
2. acme.sh 验证失败
检查 80 端口是否被占用(特别是 BT 面板默认会装 Apache 占 80):
netstat -tlnp | grep ':80 '
3. SSL Labs 评分低
通常是 TLS 1.0/1.1 没禁用,或者加密套件太弱。我上面的配置能拿到 A+。
4. WordPress 后台样式丢失
通常是 HTTPS 混合内容(页面是 https,但 CSS 是 http)。在 wp-config.php 加:
$_SERVER['HTTPS'] = 'on';
define('FORCE_SSL_ADMIN', true);
总结
生产级 HTTPS 配置没那么复杂,关键是:
- 用 acme.sh 自动签发 + 续期
- nginx 配置强 TLS 协议 + 现代加密套件
- HSTS + 安全 headers 防 XSS/clickjacking
- HTTP/2 + Brotli + OCSP Stapling 性能优化
下一篇会讲怎么用 nginx 反向代理把 WordPress 跟其他服务(如 Node.js API、Go 微服务)一起托管。