我的博客

Nginx 反向代理与 HTTPS 配置速查

Node 应用一般不直接对外监听 80 / 443 端口,而是放在 Nginx 后面。这样做的好处是证书、压缩、静态文件、多站点都交给 Nginx 处理,应用本身只管业务。

下面是我自己部署时最常用的一份配置,按需修改域名和端口即可。

申请证书

用 certbot 申请免费的 Let's Encrypt 证书最省事:

# Ubuntu / Debian
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

证书有效期 90 天,certbot 安装后会自动添加续期任务,可以用下面的命令确认续期是否正常:

sudo certbot renew --dry-run

如果用的是云厂商的免费证书,下载 Nginx 格式的证书文件,放到服务器上,在配置里指定路径即可。

完整配置

# HTTP 全部跳转到 HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

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

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    client_max_body_size 10m;

    gzip on;
    gzip_types text/css application/javascript application/json image/svg+xml;
    gzip_min_length 1024;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

几个容易忽略的点

X-Forwarded-Proto:应用拿到的请求永远是 HTTP 的。不传这个头的话,应用会以为自己跑在 HTTP 下,生成的回调地址、Cookie 的 Secure 属性都会出错。Express 需要配合 app.set('trust proxy', 'loopback') 才会读取它。

client_max_body_size:默认只有 1MB,上传图片或提交长文章时会直接返回 413。

http2 写法:Nginx 1.25.1 之后推荐用单独的 http2 on;,旧写法 listen 443 ssl http2; 会有警告。

WebSocket:如果应用用到了 WebSocket,还需要加上:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

修改后

每次改完配置,先检查再重载,不要直接 restart:

sudo nginx -t && sudo systemctl reload nginx

nginx -t 能发现绝大多数语法错误,reload 不会中断现有连接。