

摘要: 从零开始配置 Nginx 反向代理
我的博客使用 Next.js 构建,运行在 localhost:3000 端口。虽然 Next.js 本身就能对外提供服务,但直接用有几个问题:
http://IP:3000,而不是标准的 80/443 端口Nginx 就像一个「前台服务员」——接收所有客人(请求),然后转交给后厨(Next.js)处理。
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;
}
解释:
proxy_pass:把请求转发给 Next.jsproxy_set_header:传递客户端的真实 IP 和协议信息,否则 Next.js 只知道请求来自 Nginxupstream nextjs {
server 127.0.0.1:3000;
keepalive 64; # 保持 64 个空闲连接
keepalive_timeout 60s; # 空闲连接 60 秒后关闭
keepalive_requests 200;# 每个连接最多处理 200 个请求
}
作用:Nginx 和 Next.js 之间维护一个连接池,避免每次请求都重新建立 TCP 连接,大幅减少延迟。
listen 443 ssl http2;
ssl_certificate /etc/nginx/ssl/followxu.top_bundle.crt;
ssl_certificate_key /etc/nginx/ssl/followxu.top.key;
443 ssl:监听 HTTPS 标准端口http2:启用 HTTP/2 协议,支持请求多路复用ssl_session_cache shared:SSL:50m; # 共享 SSL 会话缓存
ssl_session_timeout 1d; # 会话缓存有效期
ssl_session_tickets on; # 允许会话票证恢复
ssl_stapling off; # 关闭 OCSP 装订
踩坑记录:最初开启了 OCSP Stapling,但腾讯云 Lighthouse 无法访问 TrustAsia 的 OCSP 服务器,导致首次 TLS 握手时浏览器等待 OCSP 响应超时,出现 ERR_CONNECTION_RESET。关闭后问题解决。
我的博客有两个域名入口:followxu.top 和 www.followxu.top。GitHub OAuth 回调时使用不带 www 的域名,但站点配置的 SITE_URL 是带 www 的,导致 302 重定向跨域,触发新的 TLS 握手,出现连接重置。
# 将所有请求统一重定向到 www.followxu.top
server {
listen 80;
server_name followxu.top www.followxu.top;
return 301 https://www.followxu.top$request_uri;
}
server {
listen 443 ssl;
server_name followxu.top;
ssl_certificate /etc/nginx/ssl/followxu.top_bundle.crt;
ssl_certificate_key /etc/nginx/ssl/followxu.top.key;
return 301 https://www.followxu.top$request_uri;
}
效果:无论用户访问哪个域名,最终都统一到 https://www.followxu.top,OAuth 回调不再跨域。
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
踩坑记录:最初设置了 proxy_buffering off,导致 OAuth 回调时 Next.js 需要向 GitHub 请求 token(耗时 3~5 秒),这期间 Nginx 和浏览器之间没有任何数据传输,浏览器认为连接断开,显示 ERR_CONNECTION_RESET。开启缓冲后,Nginx 先收完 Next.js 的完整响应再发给浏览器,问题解决。
proxy_connect_timeout 30s; # 连接 Next.js 最多等 30 秒
proxy_send_timeout 120s; # 发送请求最多 120 秒
proxy_read_timeout 120s; # 等待响应最多 120 秒
给 OAuth 回调足够的时间完成 GitHub token 交换,但不会无限等待。
# /etc/sysctl.conf
net.core.somaxconn = 4096 # 最大连接队列
net.ipv4.tcp_max_syn_backlog = 4096 # SYN 队列大小
net.ipv4.tcp_fastopen = 3 # TCP Fast Open
踩坑记录:之前将 somaxconn 从 4096 降到 1024,反而导致 Next.js RSC 预取时并发请求超出队列容量,触发 ERR_CONNECTION_RESET。恢复 4096 后问题缓解。
listen 443 ssl http2 backlog=4096;
keepalive_timeout 75;
keepalive_requests 200;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
backlog=4096:匹配系统 TCP 队列大小sendfile/tcp_nopush/tcp_nodelay:优化静态文件传输效率map $http_upgrade $connection_upgrade {
default upgrade;
'' '';
}
upstream nextjs {
server 127.0.0.1:3000;
keepalive 64;
keepalive_timeout 60s;
keepalive_requests 200;
}
# HTTP → HTTPS 重定向
server {
listen 80;
server_name followxu.top www.followxu.top;
return 301 https://www.followxu.top$request_uri;
}
# 不带 www 的 HTTPS → 重定向
server {
listen 443 ssl;
server_name followxu.top;
ssl_certificate /etc/nginx/ssl/followxu.top_bundle.crt;
ssl_certificate_key /etc/nginx/ssl/followxu.top.key;
return 301 https://www.followxu.top$request_uri;
}
# 主站点
server {
listen 443 ssl http2 backlog=4096;
server_name www.followxu.top;
ssl_certificate /etc/nginx/ssl/followxu.top_bundle.crt;
ssl_certificate_key /etc/nginx/ssl/followxu.top.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets on;
ssl_stapling off;
keepalive_timeout 75;
keepalive_requests 200;
location / {
proxy_pass http://nextjs;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
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;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_buffering on;
proxy_connect_timeout 30s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
}
}
Nginx 配置看似复杂,但核心就三件事:
遇到 ERR_CONNECTION_RESET 不要慌,从 TCP 层 → Nginx 层 → 应用层逐层排查,通常能找到根因。