Nginx 反向代理 + 免费 HTTPS 证书,一次配好不返工
Nginx 的配置文件看着长,其实常用的就那么几块。这里给一份我一直在用的模板,以及每次配完必做的检查项。
一、安装与目录约定
sudo apt install -y nginx
sudo systemctl enable --now nginx
nginx -v/etc/nginx/sites-available/放配置文件;/etc/nginx/sites-enabled/放软链接,只有链进来的才会被加载;/var/log/nginx/日志,access.log和error.log分开;/etc/nginx/nginx.conf是主配置,里面include了上面两个目录。
sudo ln -s /etc/nginx/sites-available/baize.conf /etc/nginx/sites-enabled/
sudo nginx -t # 每次改完必跑,语法错了它会告诉你行号
sudo systemctl reload nginx # 平滑重载,不断连接二、托管静态站点
server {
listen 80;
listen [::]:80;
server_name bzii.cn www.bzii.cn;
root /var/www/baize;
index index.html;
# SPA 路由:找不到文件就回退到 index.html
location / {
try_files $uri $uri/ /index.html;
}
# 静态资源长缓存(前提是文件名带 hash,否则别这么干)
location ~* .(css|js|png|jpg|jpeg|gif|svg|webp|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_min_length 1024;
}三、反向代理本机服务
比如有个 Node 服务跑在 127.0.0.1:3000:
server {
listen 80;
server_name api.bzii.cn;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# 这几条是 WebSocket 与真实 IP 的关键
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 10s;
proxy_read_timeout 60s;
}
client_max_body_size 20m; # 上传大小,默认只有 1m,很容易踩
}用
127.0.0.1而不是localhost:后者可能解析到 IPv6 的::1,如果你的服务只监听 IPv4,就会 502。
四、签发 Let's Encrypt 证书
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d www.bzii.cn -d www.bzii.cncertbot 会自动改配置、加 443 端口和跳转。写入后的 server 块大概长这样:
server {
listen 443 ssl http2;
server_name bzii.cn www.bzii.cn;
ssl_certificate /etc/letsencrypt/live/www.bzii.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.bzii.cn/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/baize;
index index.html;
location / { try_files $uri $uri/ /index.html; }
}
# 80 端口全部跳转 HTTPS
server {
listen 80;
server_name bzii.cn www.bzii.cn;
return 301 https://$host$request_uri;
}自动续期:certbot 装完自带 systemd timer,检查一下就行。
systemctl status certbot.timer
sudo certbot renew --dry-run # 演习一次,确认续期链路通畅证书有效期 90 天,certbot 会在剩余 30 天时自动续。如果 80 端口被防火墙挡了,HTTP-01 校验会失败,这时改用 DNS-01(Cloudflare:
certbot-dns-cloudflare)。
五、加几行安全头
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;HSTS 加上之后浏览器会强制走 HTTPS,回滚 HTTP 会很麻烦,确认站点稳定了再加。
六、踩坑排查顺序
| 现象 | 排查顺序 |
|---|---|
| 502 Bad Gateway | 后端没起来 → curl 127.0.0.1:3000 → proxy_pass 端口对不对 |
| 403 Forbidden | 目录权限 → www-data 有没有读权限 → index 文件存不存在 |
| 404 | root 路径写错,或 try_files 回退顺序不对 |
| 改了没生效 | 没 nginx -t、没 reload,或改错了 sites-available 但没软链接 |
| 证书签发失败 | 域名没解析到本机 IP / 80 端口不通 / CDN 挡住了校验 |
sudo tail -f /var/log/nginx/error.log # 实时看错误日志
sudo nginx -T | grep -n "server_name" # 确认到底加载了哪些配置配完用 SSL Labs 跑一次评级,A+ 并不难拿。
