Node.js项目上线:域名访问、后台运行与重启恢复
本文使用Ubuntu 24.04 LTS、amd64、Node.js 24.22.2,从一个最小 HTTP 应用走完部署流程:本机运行、systemd 托管、Nginx 代理、域名和 HTTPS。示例适合新建测试实例;已有面板或其他方式管理 Web 服务时,应沿用原管理方式,不重复安装第二套 Nginx。
安装一个明确版本的Node.js
先运行 dpkg --print-architecture,本例应返回 amd64。ARM 机器不能使用下方 x64 压缩包。以下下载原厂二进制并核对 SHA256,固定版本目录便于以后核对实际运行文件:
sudo apt update
sudo apt install -y ca-certificates curl xz-utils libatomic1 nginx nano
mkdir -m 700 ~/baole-node-setup
cd ~/baole-node-setup
curl --fail --location --remote-name https://nodejs.org/dist/v24.22.2/node-v24.22.2-linux-x64.tar.xz
curl --fail --location --remote-name https://nodejs.org/dist/v24.22.2/SHASUMS256.txt
awk '$2 == "node-v24.22.2-linux-x64.tar.xz"' SHASUMS256.txt | sha256sum --check -
只在目标文件显示 OK后继续。下载报错、没有匹配的校验条目或校验失败时停止,不使用未确认的压缩包:
sudo install -d -m 0755 /opt/baole-node-runtime
sudo tar --extract --xz --file node-v24.22.2-linux-x64.tar.xz --directory /opt/baole-node-runtime --no-same-owner
/opt/baole-node-runtime/node-v24.22.2-linux-x64/bin/node --version
版本应显示 v24.22.2。这是本文的固定示例版本;以后维护时先核对受支持分支、修复版本和项目兼容性,再安排升级,不把旧版本号长期照抄到新项目。
先跑通一个只监听本机的应用
创建独立运行账户和新目录。若这些名称已被其他项目使用,先换成自己的名称,并同步替换后续路径与服务配置:
sudo adduser --system --group --home /srv/baole-node --no-create-home baole-node
sudo install -d -o root -g baole-node -m 0750 /srv/baole-node
sudo nano /srv/baole-node/server.mjs
在文件中保存下面内容:
import { createServer } from 'node:http';
const server = createServer((request, response) => {
if (request.url !== '/health') {
response.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
response.end('请访问 /health');
return;
}
response.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
response.end(JSON.stringify({ status: 'ok', name: '宝乐云应用测试' }));
});
server.listen(3000, '127.0.0.1');
sudo chmod 0644 /srv/baole-node/server.mjs
sudo -u baole-node /opt/baole-node-runtime/node-v24.22.2-linux-x64/bin/node --check /srv/baole-node/server.mjs
本例不需要安装额外 npm 包。真实项目则按自己的锁文件、构建脚本和生产入口部署;需要 npm ci或 npm run build时,由部署账户执行,并确保使用与运行服务相同的 Node.js 版本。
让systemd接管运行进程
新建 /etc/systemd/system/baole-node.service,写入:
[Unit]
Description=Baole Node application
After=network.target
[Service]
Type=exec
User=baole-node
Group=baole-node
WorkingDirectory=/srv/baole-node
Environment=NODE_ENV=production
ExecStart=/opt/baole-node-runtime/node-v24.22.2-linux-x64/bin/node /srv/baole-node/server.mjs
Restart=on-failure
RestartSec=3
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now baole-node
sudo systemctl status baole-node --no-pager
curl --fail --show-error --retry 5 --retry-connrefused --retry-delay 1 --max-time 5 http://127.0.0.1:3000/health
应看到 active (running)及包含 "status":"ok"的 JSON。先在这一层跑通,再配域名;服务器防火墙不需要把 3000 端口开放到公网。
通过Nginx接入域名
新建 /etc/nginx/sites-available/baole-node。将 app.example.com换成实际域名,不与已有站点重复:
server {
listen 80;
server_name app.example.com;
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;
}
}
sudo ln -s /etc/nginx/sites-available/baole-node /etc/nginx/sites-enabled/baole-node
sudo nginx -t && sudo systemctl reload nginx
只有配置检查通过才重载;提示链接已存在时先查看旧配置,不强制覆盖。按DNS教程设置域名,按实际产品规则放行 Web 入口。HTTP 的 /health正常后,继续用Certbot教程为该站点配置 HTTPS 并验证续期;正式使用带登录或业务数据的应用前,应完成 HTTPS。
退出SSH以后再验收一次
关闭 SSH 会话,从自己的电脑访问 https://实际域名/health。随后重新登录服务器,执行:
sudo systemctl restart baole-node
systemctl is-enabled baole-node
curl --fail --show-error --retry 5 --retry-connrefused --retry-delay 1 --max-time 5 http://127.0.0.1:3000/health
sudo journalctl -u baole-node --since '10 minutes ago' --no-pager
应确认服务已设置开机启动、重启服务后能恢复响应、域名访问也正常。若要验证整机重启后的自动恢复,在维护窗口重启实例后重复这些检查;只看 enabled不能代替这一步的实际结果。
| 现象 | 定位方向 |
|---|---|
| 本机3000连接失败 | 先看systemd状态和应用日志,核对入口文件、运行账户、Node路径与端口占用。 |
| 本机正常,域名返回502 | 检查Nginx实际加载配置中的代理地址,查看错误日志,不先换服务器IP。 |
| 返回默认网页或其他网站 | 核对DNS、server_name和请求域名,确认命中本次站点。 |
| 终端启动正常,systemd启动失败 | 核对绝对路径、工作目录和环境变量;服务不会自动继承交互终端里的版本管理器配置。 |
上线自己的项目时,为配置、依赖锁文件和上传数据分别安排备份。更新失败先保留日志,恢复上一版代码与对应依赖后重启服务;涉及数据库变更的项目还要准备匹配的数据库恢复方案。