This is the quick, copy‑paste friendly checklist to build locally and deploy to your Ubuntu server with PM2 + Nginx.
- Node 22.x (same major as server)
- npm (or pnpm/yarn, but commands below use npm)
- SSH access to the server
- Your repo cloned locally
git pull origin main
# optional but recommended before a clean build
rm -rf node_modules server/node_modules package-lock.json server/package-lock.json
npm install --workspacesnpm run buildWhat that does (per your root package.json):
- Builds the client (
vite build->dist/) - Builds the server (
tsc->server/dist/) - Copies the client build into
server/dist/public - Packages a deploy bundle via
scripts/package-prod.mjsintotextguard-build.tar.gz
If you only want the tarball:
node scripts/package-prod.mjs
scp -i ~/.ssh/<your_key> textguard-build.tar.gz root@hacia.net:/var/www/textguard.chrishacia.com/ssh -i ~/.ssh/<your_key> root@hacia.net
cd /var/www/textguard.chrishacia.comtar -xzf textguard-build.tar.gz
cd .deploy/textguard
# install only prod deps for server
npm ci --omit=devMake sure
.envis present here (it’s copied by the script if it existed locally).
If not, create it now and setSERVER_PORT,SPAM_THRESHOLD, etc.
First time:
pm2 start ecosystem.config.cjs --env production
pm2 saveSubsequent deploys:
pm2 reload TextGuardCheck logs:
pm2 logs TextGuard --lines 100Your server block already proxies to PM2 on 127.0.0.1:. After changes:
sudo nginx -t && sudo systemctl reload nginxOn the server:
curl -s http://127.0.0.1:<PORT>/api/aliveFrom your browser:
https://textguard.chrishacia.com
- Keep the previous tarball as
textguard-build-prev.tar.gz pm2 reload TextGuard --update-envafter swapping folders- Or
pm2 restart TextGuard --name TextGuard@previf you kept another app entry
| Symptom | Fix |
|---|---|
| 502 from Nginx | PM2 app not running or wrong port. Check pm2 logs, verify SERVER_PORT. |
Cannot find module in PM2 logs |
Forgot npm ci --omit=dev in the deploy folder or missing .env. |
| Build fails on server (Rollup/esbuild binaries) | Don’t build on server. Build locally and upload the bundle. |
bad-words ESM/CJS error |
Make sure you are using leo-profanity (we removed bad-words). Rebuild if necessary. |
Happy shipping! 🚀