海外服务器部署Next.js SSR站点,PM2、Nginx反向代理与HTTPS配置如何配合
面向前端开发工程师,梳理Next.js SSR站点部署到海外服务器的关键流程,包括Node.js环境准备、PM2守护、Nginx反向代理、HTTPS证书配置及重启后可用性验证。

目标状态:让 Next.js SSR、PM2、Nginx 与 HTTPS 各司其职
Next.js 项目在本地 npm run build 正常,传到海外服务器后却常见几类问题:关闭 SSH 后站点不可访问;浏览器访问域名返回 502;HTTP 能打开但 HTTPS 证书签发失败;服务器重启后 Node 进程没有自动恢复。这些问题通常不是 Next.js 本身导致的,而是进程管理、反向代理和证书配置没有形成完整链路。
部署 Next.js SSR 站点时,推荐的目标状态是:
- Next.js SSR 应用只监听服务器本机地址,例如
127.0.0.1:3000; - PM2 负责守护 Node.js 进程,并配置开机自启;
- Nginx 对外监听
80/443,通过 Nginx反向代理 转发请求到 Next.js; - HTTPS 证书由可信 CA 签发,Nginx 负责 TLS 终止;
- 服务器重启、Nginx reload、PM2 restart 后,站点仍可访问。
下面示例以 Ubuntu 22.04/24.04 或 Debian 12 为参考。若你的海外服务器使用其他发行版,需要先确认包管理器、服务管理方式和 Nginx 配置路径是否一致。
部署前先核对环境和前置条件
正式操作前,不建议直接复制命令上线。先确认以下条件是否满足:
| 检查项 | 要求 |
|---|---|
| 域名解析 | example.com 已解析到服务器公网 IP |
| 端口开放 | 安全组、防火墙允许 80、443 入站 |
| Node.js 版本 | 与 Next.js 项目要求一致,建议使用当前 LTS 版本 |
| 构建依赖 | 服务器可访问 npm registry 或已配置可用镜像 |
| 证书条件 | 公网域名可验证;内网域名或未解析域名不能直接申请公网信任证书 |
先查看系统和基础软件状态:
lsb_release -a
node -v
npm -v
nginx -v
ss -lntp
安装常用依赖:
sudo apt update
sudo apt install -y nginx git curl build-essential
如果服务器启用了 UFW,需要允许 Web 端口:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status
Node.js 的安装方式可以使用系统包、NodeSource、nvm、fnm 等。生产环境要注意一点:PM2 开机自启时使用的用户必须能找到同一个 Node.js 路径。若使用 nvm 部署,后续 pm2 startup 和应用启动用户要保持一致,否则重启后可能出现“找不到 node/npm”的问题。
上传项目并完成生产构建
假设应用部署目录为 /var/www/next-ssr,建议使用普通部署用户操作,不要长期使用 root 跑 Node 应用。
sudo mkdir -p /var/www/next-ssr
sudo chown -R $USER:$USER /var/www/next-ssr
cd /var/www/next-ssr
git clone https://your-git-repo.example/next-ssr.git .
准备生产环境变量。常见文件名是 .env.production,但具体以你的项目读取方式为准:
nano .env.production
安装依赖并构建:
npm ci
npm run build
如果这里失败,不要继续配置 Nginx。先看构建报错,例如 Node.js 版本不匹配、缺少环境变量、依赖安装失败、服务端代码访问了浏览器对象等。SSR 站点必须保证服务端构建和运行都正常,Nginx 只能代理请求,不能修复应用构建问题。
确认 package.json 中存在生产启动脚本,例如:
{
"scripts": {
"build": "next build",
"start": "next start"
}
}
可以先手动启动一次验证:
npm run start -- -p 3000 -H 127.0.0.1
另开一个 SSH 窗口检查本机访问:
curl -I http://127.0.0.1:3000
看到 200、301、302、404 都说明 Next.js 服务有响应;如果是连接失败,说明 Node 服务没有监听成功。验证后按 Ctrl + C 停止手动进程,交给 PM2 管理。
使用 PM2 守护 Next.js SSR 进程
安装 PM2:
sudo npm install -g pm2
pm2 -v
在项目目录创建 ecosystem.config.js,这样比直接敲一长串启动命令更容易维护:
module.exports = {
apps: [
{
name: "next-ssr",
cwd: "/var/www/next-ssr",
script: "node_modules/next/dist/bin/next",
args: "start -p 3000 -H 127.0.0.1",
env: {
NODE_ENV: "production"
},
instances: 1,
exec_mode: "fork",
max_memory_restart: "512M"
}
]
};
启动应用:
cd /var/www/next-ssr
pm2 start ecosystem.config.js
pm2 status
pm2 logs next-ssr --lines 50
保存 PM2 进程列表:
pm2 save
配置开机自启:
pm2 startup systemd
执行后,PM2 会输出一条带 sudo 的命令,例如包含当前用户名和 home 路径。需要复制并执行它,然后再次保存:
pm2 save
如果你使用的是非 root 用户部署,重启后应检查对应的 systemd 服务,例如服务名可能是 pm2-用户名:
systemctl status pm2-$USER
这里有一个容易误判的点:pm2 status 显示 online,只代表 Node 进程正在运行,不代表域名能访问。域名访问还依赖 Nginx反向代理、防火墙、DNS 和 HTTPS 配置。
如果项目使用 Next.js standalone 输出,启动方式会不同,通常是运行 .next/standalone/server.js,并通过环境变量指定端口和主机名:
module.exports = {
apps: [
{
name: "next-ssr",
cwd: "/var/www/next-ssr",
script: ".next/standalone/server.js",
env: {
NODE_ENV: "production",
PORT: "3000",
HOSTNAME: "127.0.0.1"
}
}
]
};
选择哪种方式取决于你的 next.config.js 和构建产物,不要混用。
配置 Nginx 反向代理到本机 Node 服务
Next.js 不建议直接暴露在公网端口上。更稳妥的做法是:Node 只监听 127.0.0.1:3000,Nginx 对外提供 HTTP/HTTPS 服务。
先为 WebSocket/连接升级准备一个 Nginx 变量文件:
sudo nano /etc/nginx/conf.d/connection_upgrade.conf
写入:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
创建站点配置:
sudo nano /etc/nginx/sites-available/next-ssr
先配置 HTTP 反向代理,证书申请前不要急着写死 HTTPS:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
access_log /var/log/nginx/next-ssr.access.log;
error_log /var/log/nginx/next-ssr.error.log;
client_max_body_size 20m;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
}
启用站点:
sudo ln -s /etc/nginx/sites-available/next-ssr /etc/nginx/sites-enabled/next-ssr
sudo nginx -t
sudo systemctl reload nginx
如果 nginx -t 报错,先不要 reload。常见原因包括配置文件分号遗漏、server_name 写错位置、connection_upgrade 变量未定义、重复监听同一域名等。
验证 Nginx 到 Next.js 的代理链路:
curl -I http://127.0.0.1:3000
curl -I -H "Host: example.com" http://127.0.0.1
curl -I http://example.com
如果本机 127.0.0.1:3000 正常,但域名访问 502,优先查看:
pm2 logs next-ssr --lines 100
sudo tail -n 100 /var/log/nginx/next-ssr.error.log
502 多半是 Nginx 连接不到上游 Node 服务,例如 PM2 进程未运行、端口不一致、Next.js 监听到 0.0.0.0 以外的错误地址、应用启动后立即崩溃等。
配置 HTTPS:证书签发方式要匹配实际环境
HTTPS 的配置不能只看 Nginx 示例,还要看证书能否被签发。公网用户访问的站点,应使用受信任 CA 证书,例如 Let’s Encrypt、商业证书或云平台证书。自签名证书只适合内部测试,不适合正式公网业务。
使用 Let’s Encrypt 时,通常有两种验证方式:
- HTTP-01:域名已解析到当前服务器,且公网可访问 80 端口;
- DNS-01:适合通配符证书、服务器 80 端口不可访问、域名暂未切流等场景,但需要操作 DNS 解析记录或接入 DNS API。
如果你的域名已经指向这台海外服务器,并且 80 端口可访问,可以使用 Certbot 的 Nginx 插件:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
执行过程中,Certbot 会检查域名、申请证书,并可自动修改 Nginx 配置。完成后建议重新检查配置:
sudo nginx -t
sudo systemctl reload nginx
证书自动续期通常由 systemd timer 或 cron 管理,可用以下命令验证续期流程:
sudo certbot renew --dry-run
如果证书签发失败,不要反复盲目重试。先确认:
- 域名 A/AAAA 记录是否指向当前服务器;
- 服务器安全组和系统防火墙是否允许 80 端口;
- Nginx 的
server_name是否与申请证书的域名一致; - 是否存在 CDN、WAF、反向代理导致验证请求没有到达源站;
- 是否申请了通配符证书,通配符通常需要 DNS-01 验证。
一个常见的 HTTPS Nginx 配置大致如下,证书路径以实际签发结果为准:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
access_log /var/log/nginx/next-ssr.access.log;
error_log /var/log/nginx/next-ssr.error.log;
client_max_body_size 20m;
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 https;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
}
HSTS 可以提升 HTTPS 强制访问效果,但不建议刚上线就直接开启长周期 HSTS。若证书、子域名或回源链路还未稳定,错误的 HSTS 配置会让浏览器在一段时间内强制访问 HTTPS,增加回滚难度。
上线后验证:不仅看首页,还要验证重启恢复
部署完成后,至少从三个层面检查。
先看应用进程:
pm2 status
pm2 logs next-ssr --lines 50
curl -I http://127.0.0.1:3000
再看 Nginx 和域名:
sudo systemctl status nginx
sudo nginx -t
curl -I http://example.com
curl -I https://example.com
然后从本地浏览器或第三方网络环境访问:
- 首页是否正常返回;
- SSR 页面刷新后是否正常;
- 登录、接口请求、图片和静态资源是否正常;
- HTTP 是否跳转到 HTTPS;
- 浏览器证书是否可信,域名是否匹配;
- Nginx error log 是否持续出现 502、499、504。
最后做一次受控重启验证。建议在低峰期操作,避免影响真实用户:
sudo reboot
服务器恢复后检查:
systemctl status nginx
systemctl status pm2-$USER
pm2 status
ss -lntp | grep -E ':80|:443|:3000'
curl -I https://example.com
如果重启后 Nginx 正常但 PM2 没有恢复,重点检查 pm2 startup 是否按正确用户执行、pm2 save 是否执行、Node.js 路径是否因 nvm/fnm 导致 systemd 找不到。若 PM2 正常但域名不可访问,再回到 Nginx 日志和防火墙层面排查。
回滚条件与保留项
上线前建议至少保留三类可回滚内容:上一版代码提交、上一份 Nginx 配置、当前可用的 PM2 启动配置。修改 Nginx 前可以先备份:
sudo cp /etc/nginx/sites-available/next-ssr /etc/nginx/sites-available/next-ssr.bak-$(date +%F-%H%M)
出现以下情况时,不建议继续追加修改,应先回滚到可用状态:
- 新版本
npm run build失败或 PM2 进程反复重启; - Nginx 出现持续 502/504,且无法在短时间内定位;
- HTTPS 证书申请失败导致正式域名不可访问;
- 重启服务器后 PM2 无法自动恢复;
- 关键业务页面、登录、支付、接口请求异常。
代码回滚可以切回上一个已验证提交后重新构建并重启 PM2:
cd /var/www/next-ssr
git checkout <last-good-commit>
npm ci
npm run build
pm2 restart next-ssr
pm2 save
Nginx 配置回滚时,先恢复备份,再测试配置,最后 reload:
sudo cp /etc/nginx/sites-available/next-ssr.bak-YYYY-MM-DD-HHMM /etc/nginx/sites-available/next-ssr
sudo nginx -t
sudo systemctl reload nginx
回滚完成后不要只看浏览器缓存页面,应重新执行 curl -I https://example.com、查看 PM2 日志和 Nginx error log。只有 Node.js 进程、Nginx反向代理、HTTPS 证书和重启恢复都验证通过,Next.js SSR 站点在海外服务器上的部署才算进入可维护状态。