这篇教程适合谁—— 你大概懂一点命令行但从没在生产环境部署过 Node 项目最终目标把你的 NestJS / Express 后端安全跑在 Windows 服务器上并且用 HTTPS 对外提供服务 先说说我为什么要搞这件事大家好我是码农刚子。最近我“Vibe Coding”了一个小网站技术栈如下前端Next.js 16 (App Router) Tailwind CSS v4 shadcn/ui后端NestJS (Node.js)数据库Supabase PostgreSQL一开始我想着全部扔到 Vercel 上不就完事了毕竟 Vercel 对 Next.js 太友好了一键部署自动给 HTTPS爽得很。结果很快就被打脸了Vercel 其实不适合部署 Node.js 后端。它虽然有 Serverless Functions但限制一大堆响应时间、包大小、WebSocket 支持……我这个 NestJS 项目体积不小还用了不少传统的 Node 库硬塞进去就是自找麻烦。所以只能把后端单独部署出来。正好手里有一台阿里云的 Windows Server上面已经跑着一些 .NET 站点而且我本人从来没在生产环境部署过 Node 项目——这是纯纯的第一次实操踩了无数坑。于是我把整个折腾过程记了下来整理成这篇小白照着做就能成功的教程。如果你也跟我一样想把一个真实的 Node 后端扔到自己的 Windows 云服务器上那这篇文章就是为你写的。 你需要提前准备好这些东西一台 Windows Server2016 / 2019 / 2022 都行要有管理员权限你的后端项目代码我用的是 NestJS但 Express 之类的也一样一个域名后面要配 HTTPS 用阿里云 / 腾讯云 / 其他云厂商的免费 SSL 证书或者你知道怎么用 Lets Encrypt 也行一、装好基础环境1. 装 Node.js打开官网https://nodejs.org/下载LTS 版本比如 22.x的.msi安装包双击安装一路点“下一步”不要乱改安装路径默认装在C:\Program Files\nodejs装完之后以管理员身份打开 PowerShell敲下面两行检查一下node -v # 应该显示 v22.x.x npm -v # 应该显示 10.x.x 或更高2. 装 PM2进程守护工具PM2 的作用就是让你的 Node 程序在后台跑着挂了能自动重启服务器重启了也能自己起来。npm install -g pm2 npm install -g pm2-windows-startup pm2-startup install这三条命令分别是装 PM2 → 装 Windows 开机自启插件 → 把 PM2 注册成系统服务。搞定之后重启服务器也不用怕了。二、把项目代码弄到服务器上1. 创建目录mkdir C:\wwwroot\my-node-project cd C:\wwwroot\my-node-project2. 上传或克隆代码方法一推荐用 Git 直接拉下来git clone https://github.com/你的用户名/你的仓库.git .方法二用远程桌面或者 FTP 把文件夹整个复制进去3. 重要安全提醒检查.gitignore确保你的项目根目录或backend目录下有一个.gitignore文件里面至少包含node_modules/ dist/ .env *.log如果你的.env文件已经被提交到 Git了赶紧把它从版本控制里移除但本地文件要保留git rm --cached .env git commit -m remove env from git⚠️.env里存着数据库密码、JWT 密钥这些敏感信息死活不能上传到 Git记住了嗷。三、装依赖 构建项目1. 进入后端目录如果你的前后端是分开的cd C:\wwwroot\my-node-project\backend # 根据你的实际路径来2. 装依赖npm install这个过程可能会花几分钟耐心等一等。3. 配置生产环境变量在backend目录下创建.env文件如果没有的话New-Item -Path .env -ItemType File然后用记事本或 VS Code 打开.env写上类似下面的内容按你自己的项目来PORT3000 JWT_SECRET一定改成一个超长的随机字符串 DATABASE_URL你的数据库连接地址 想生成一个随机 JWT_SECRET在 PowerShell 里直接跑这条命令-join ((48..57)(65..90)(97..122) | Get-Random -Count 64 | ForEach-Object {[char]$_})4. 构建项目这一步容易踩坑 ⚠️大部分 Node 项目尤其是 NestJS需要把 TypeScript 编译成 JavaScript。通常的命令是npm run build但是如果你的项目用了module: nodenext这种配置直接跑nest build可能会失败导致dist目录是空的。解决办法以 NestJS 为例打开package.json找到build脚本把build: nest build改成build: tsc -p tsconfig.build.json如果你不是 NestJS而是普通的 TypeScript Node那构建命令一般就是tsc或者tsc --project tsconfig.json。改完之后重新跑一遍构建npm run build检查一下编译产物Test-Path dist/main.js # 或者 dist/src/main.js看你的配置如果返回True说明编译成功了。 实在不行你也可以在本地编译好了把整个dist文件夹直接上传到服务器跳过服务器上编译这一步。四、用 PM2 启动后端1. 写 PM2 配置文件在项目的根目录比如C:\wwwroot\my-node-project下新建一个文件叫ecosystem.config.js内容如下module.exports { apps: [ { name: my-node-backend, // 给你的应用起个好认的名字 cwd: ./backend, // 入口文件在哪个目录按你实际的改 script: dist/main.js, // 编译后的入口文件 instances: 1, autorestart: true, watch: false, max_memory_restart: 500M, env: { NODE_ENV: production, PORT: 3000, }, error_file: ./logs/backend-error.log, out_file: ./logs/backend-out.log, log_date_format: YYYY-MM-DD HH:mm:ss, }, ], }; 别忘了先创建logs文件夹mkdir C:\wwwroot\my-node-project\backend\logs2. 启动应用cd C:\wwwroot\my-node-project pm2 start ecosystem.config.js pm2 save3. 看看到底跑起来没有pm2 status你应该会看到类似这样的输出只要status是online就说明成了。4. 本地测试一下接口curl http://localhost:3000/api/health # 换成你项目里真实存在的接口如果返回了数据哪怕是 401 未授权也没关系起码说明服务在跑就恭喜你Node 程序已经在后台欢快地工作了。五、配置 HTTPS 反向代理用 Caddy为啥要搞这个因为你的前端比如部署在 Vercel强制用了 HTTPS而浏览器有个安全策略HTTPS 页面不能去请求 HTTP 接口否则会报 Mixed Content 错误。所以你的后端也必须通过 HTTPS 对外暴露。但是你服务器上可能已经有 IIS 或者其他服务占用了 80 和 443 端口。所以我们换个思路用 Caddy 监听一个高位端口比如 8443手动挂上 SSL 证书这样就不会跟 IIS 打架了。1. 下载 Caddy在 PowerShell 里执行Invoke-WebRequest -Uri https://github.com/caddyserver/caddy/releases/download/v2.9.1/caddy_2.9.1_windows_amd64.zip -OutFile $env:TEMP\caddy.zip New-Item -Path C:\caddy -ItemType Directory -Force Expand-Archive $env:TEMP\caddy.zip -DestinationPath C:\caddy -Force2. 搞一张免费 SSL 证书以阿里云为例登录阿里云控制台搜索“SSL 证书”点“免费证书” → “立即购买”0 元选“DV 单域名证书”证书绑定的域名写你的 API 域名比如api.yourdomain.com验证方式选 DNS如果你的域名也在阿里云它会自动帮你添加 TXT 记录签发成功后下载证书格式选Nginx你会得到两个文件.pem证书和.key私钥把这两个文件放到C:\caddy\目录下像这样C:\caddy\api.yourdomain.com.pem C:\caddy\api.yourdomain.com.key3. 配置 DNS 解析去你的域名管理后台加一条A 记录主机记录记录类型记录值apiA你服务器的公网 IP等几分钟让解析生效可以用这条命令验证Resolve-DnsName api.yourdomain.com应该会返回你的公网 IP。4. 写 Caddyfile在C:\caddy\目录下新建一个文件就叫Caddyfile没有扩展名内容如下{ auto_https off } api.yourdomain.com:8443 { tls C:\caddy\api.yourdomain.com.pem C:\caddy\api.yourdomain.com.key reverse_proxy localhost:3000 }⚠️ 这一行的auto_https off千万不能少不然 Caddy 会试图去占 80 端口做自动重定向然后就报错了。5. 测试一下 Caddy 能不能跑cd C:\caddy .\caddy.exe run --config Caddyfile --resumefalse如果你看到了server running并且没有报错那就成功了。按CtrlC先停掉。6. 让 Caddy 开机自启用任务计划关掉刚才的 Caddy 窗口然后以管理员身份打开 PowerShell执行下面这一大坨命令$action New-ScheduledTaskAction -Execute C:\caddy\caddy.exe -Argument run --config C:\caddy\Caddyfile -WorkingDirectory C:\caddy $trigger New-ScheduledTaskTrigger -AtStartup $settings New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RestartCount 5 -RestartInterval (New-TimeSpan -Minutes 1) Register-ScheduledTask -TaskName Caddy-API-Proxy -Action $action -Trigger $trigger -Settings $settings -RunLevel Highest -Force Start-ScheduledTask -TaskName Caddy-API-Proxy检查一下 8443 端口是不是已经在监听了netstat -ano | findstr :8443应该会显示LISTENING。7. 开放防火墙端口netsh advfirewall firewall add rule nameAllow HTTPS 8443 dirin actionallow protocolTCP localport8443另外如果你的云服务器还有安全组阿里云叫安全组规则也要去控制台添加入方向规则允许 TCP 8443。8. 测试 HTTPS 接口打开浏览器或者直接敲命令curl https://api.yourdomain.com:8443/api/health如果能返回数据哪怕是 401就说明 HTTPS 反向代理大功告成了。六、日常更新代码的流程以后每次改了代码在服务器上走这几步cd C:\wwwroot\my-node-project git pull cd backend npm install # 如果有新依赖就装一下 npm run build # 重新编译 pm2 restart my-node-backend pm2 logs my-node-backend # 看一眼启动日志确认没报错七、常见翻车现场 解决办法现象可能原因怎么办PM2 状态是errored入口文件路径不对或者依赖没装全检查ecosystem.config.js里的script路径手动node dist/main.js看看报什么错curl localhost:3000没反应Node 没启动或者端口被占netstat -ano \| findstr :3000看端口pm2 logs看日志Caddy 启动报 80 端口错误忘了加auto_https off检查 Caddyfile 第一行浏览器提示“连接不安全”证书域名不匹配或者证书过期重新申请证书确认 Caddyfile 里的域名跟证书域名完全一样前端调用接口报 CORS 错误后端的.env没配允许的前端域名加上CORS_ORIGINhttps://你的前端域名然后pm2 restart改了.env但没生效PM2 没重启环境变量没重新读pm2 restart my-node-backend就好了八、你成功完成了这些事✅ 装了 Node.js 和 PM2✅ 把代码弄到服务器上装了依赖✅ 解决了 TypeScript 编译的小坑✅ 用 PM2 把 Node 进程守护起来还能开机自启✅ 用 Caddy 免费 SSL 证书 搞定了 HTTPS 反向代理✅ 开了防火墙端口配置了开机启动任务现在你的 Node.js 后端已经安安稳稳地跑在生产环境可以通过https://api.yourdomain.com:8443对外提供服务了。 最后再啰嗦几句定期比如每个月登录阿里云控制台瞅一眼 SSL 证书过期了没快到期的重新申请替换一下每天有空就pm2 logs --lines 50看看有没有报错永远、永远不要把.env文件发给任何人也不要传到 Git 上去我是刚子一个还在写 .NET 代码的程序员。祝你部署顺顺利利永不宕机如果觉得文章对你有用记得点赞、收藏、转发给更多的小伙伴。阅读原文从零开始在 Windows 服务器上部署 Node.js 项目小白实战教程 - 码农刚子的开发笔记