DEV Community

khimananda Oli
khimananda Oli

Posted on • Originally published at khimananda.com

Setting Up NVM, PM2, and Process Management on Linux

Why NVM Over System Node?

Don't apt install nodejs. You'll get a stale version pinned to your distro's release cycle, and switching between projects that need different Node versions becomes a mess.

NVM gives you per-user Node version management with zero system-level conflicts.


Install NVM

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
Enter fullscreen mode Exit fullscreen mode

Reload your shell:

source ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

Verify:

nvm --version
# 0.40.1
Enter fullscreen mode Exit fullscreen mode

Install Node.js

# Install LTS
nvm install --lts

# Or a specific version
nvm install 20.18.0

# Set default — without this, new shells may pick a different version
nvm alias default 20.18.0

# Verify
node -v && npm -v
Enter fullscreen mode Exit fullscreen mode

Where Does Node Live?

NVM installs per-user. Your Node binary path looks like:

/home/deploy/.nvm/versions/node/v20.18.0/bin/node
Enter fullscreen mode Exit fullscreen mode

This matters when PM2 needs to register a systemd service. Keep it in mind.


Install PM2

npm install -g pm2
Enter fullscreen mode Exit fullscreen mode

Since we used NVM, PM2 lives at:

~/.nvm/versions/node/v20.18.0/bin/pm2
Enter fullscreen mode Exit fullscreen mode

Quick sanity check:

pm2 --version
Enter fullscreen mode Exit fullscreen mode

PM2 Startup — Survive Reboots

This is where NVM + PM2 gets tricky. PM2's startup script needs the full path to the Node binary because systemd runs non-interactively — NVM isn't loaded in that context.

Generate the startup script:

pm2 startup systemd
Enter fullscreen mode Exit fullscreen mode

PM2 will print a command like:

sudo env PATH=$PATH:/home/deploy/.nvm/versions/node/v20.18.0/bin \
  /home/deploy/.nvm/versions/node/v20.18.0/lib/node_modules/pm2/bin/pm2 \
  startup systemd -u deploy --hp /home/deploy
Enter fullscreen mode Exit fullscreen mode

Copy and run that exact command. Don't modify it.

Then save the current process list:

pm2 save
Enter fullscreen mode Exit fullscreen mode

PM2 will now resurrect all managed apps on reboot.

The Stale dump.pm2 Trap

If PM2 keeps resurrecting old or dead processes after a restart, it's because pm2 save wrote a dump.pm2 file with stale state.

Fix:

pm2 kill
rm -f ~/.pm2/dump.pm2
# start your apps again (covered in Part 2)
pm2 save
Enter fullscreen mode Exit fullscreen mode

Always run pm2 save after any change to your process list. Forgetting this will bite you at 3 AM when the server reboots and your app doesn't come back.


PM2 Log Rotation

By default, PM2 logs grow unbounded. In production, that's a disk space incident waiting to happen.

Option A: pm2-logrotate (Recommended)

pm2 install pm2-logrotate

pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 10
pm2 set pm2-logrotate:compress true
pm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss
pm2 set pm2-logrotate:workerInterval 30
pm2 set pm2-logrotate:rotateInterval '0 0 * * *'
Enter fullscreen mode Exit fullscreen mode

Verify:

pm2 conf pm2-logrotate
Enter fullscreen mode Exit fullscreen mode

Option B: System logrotate

If you prefer the OS-level approach:

# /etc/logrotate.d/pm2-myapp
/home/deploy/.pm2/logs/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    copytruncate
}
Enter fullscreen mode Exit fullscreen mode

Use copytruncate — PM2 holds the file handle open, so you can't move the log file out from under it.


Quick Reference — PM2 Commands

pm2 status              # list all managed processes
pm2 logs                # tail all logs
pm2 logs myapp          # tail specific app
pm2 monit               # real-time CPU/memory dashboard
pm2 reload myapp        # zero-downtime reload (cluster mode)
pm2 restart myapp       # hard restart
pm2 stop myapp          # stop without removing
pm2 delete myapp        # stop and remove from list
pm2 save                # persist process list
pm2 resurrect           # restore saved list
Enter fullscreen mode Exit fullscreen mode

What We Have So Far

At this point:

  • ✅ NVM installed with a pinned Node.js version
  • ✅ PM2 installed globally via NVM
  • ✅ Startup script registered — apps survive reboots
  • ✅ Log rotation configured — no disk space surprises

Follow for Part 2 — Running Your Node.js Application with PM2

Top comments (0)