Runtime
Node.js 24 LTS
Framework
NestJS + TypeScript
Database
MariaDB 11.4
Process
PM2 + systemd
Start Building (Quickstart)
- SSH:
ssh root@172.235.194.189 - Upload code via SFTP / FileZilla / Cyberduck: host=
172.235.194.189, user=root, target=/opt/myapp_nestjs/ - Ownership:
chown -R appuser:appuser /opt/myapp_nestjs - Install & Build:
sudo -iu appuser→cd /opt/myapp_nestjs→pnpm install --prod→pnpm build - Restart:
exit→sudo -u appuser pm2 reload myapp_nestjs
Operate (root)
Service status
systemctl status pm2-appuserApp logs
sudo -u appuser pm2 logs myapp_nestjsReload app
sudo -u appuser pm2 reload myapp_nestjsDB env
sudo cat /etc/myapp_nestjs/envReference (paths & configs)
Runtime
Node.js 24 LTS (NestJS 11 needs Node 18+).Build tool
pnpm install --prod + pnpm build (TS → dist/). npm/yarn work too if you replace pnpm.Entry point
/opt/myapp_nestjs/dist/main.js (compiled from src/main.ts)PM2 config
/opt/myapp_nestjs/ecosystem.config.js — cluster mode, name=myapp_nestjs, script=dist/main.js. Reads /etc/myapp_nestjs/env at start.systemd unit
/etc/systemd/system/pm2-appuser.service — auto-generated by pm2 startup; runs as appuser. PM2 then resurrects ecosystem.config.js.DB env file
/etc/myapp_nestjs/env (mode 0640, root:appuser) — loaded by ecosystem.config.js, exposed to NestJS via process.env.App port
__APP_PORT__ (NestJS listen port). Nginx reverse-proxies :80 / :443 → :__APP_PORT__.Logs
sudo -u appuser pm2 logs myapp_nestjs (rotated under ~appuser/.pm2/logs/). systemd journal: journalctl -u pm2-appuser.Profile / NODE_ENVadd
NODE_ENV=production to /etc/myapp_nestjs/env; ecosystem.config.js auto-loads it.Redeployupload new source →
chown -R appuser:appuser /opt/myapp_nestjs → sudo -iu appuser → cd /opt/myapp_nestjs → pnpm install --prod → pnpm build → pm2 reload myapp_nestjs (zero-downtime in cluster mode).