Install Node.js with nvm and Run an App with pm2
Run on the server with one command (check the script contents below first):
curl -sSL https://cp.lv/scripts/ustanovit-nodejs-pm2.sh | sudo bash…or with wget:
wget -qO- https://cp.lv/scripts/ustanovit-nodejs-pm2.sh | sudo bashScript contents ustanovit-nodejs-pm2.sh:
#!/usr/bin/env bash
set -e
APP_DIR=/var/www/myapp
# 1. Install nvm and load it into the current shell
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# 2. Node.js LTS as the default version
nvm install --lts
nvm use --lts
nvm alias default 'lts/*'
# 3. Application dependencies (exact versions from the lock file)
cd "$APP_DIR"
npm ci --omit=dev
# 4. Install pm2 and start the application
npm install -g pm2
pm2 start app.js --name myapp
# 5. Start automatically after a server reboot
sudo env PATH=$PATH:$(dirname "$(command -v node)") \
pm2 startup systemd -u "$USER" --hp "$HOME"
pm2 save
pm2 status
echo "Node.js application myapp is running under pm2."
For a Node.js application to run reliably in production, you cannot simply start it with node app.js in an SSH session — it stops when you log out. You need the pm2 process manager: it keeps the application alive, restarts it after a crash and brings it back after a server reboot. Node.js itself is best installed through nvm, which makes switching versions easy.
Step 1. Install nvm
nvm (Node Version Manager) installs Node.js without root rights and lets you keep several versions side by side:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc
Check it:
nvm --version
Step 2. Install Node.js LTS
Install the LTS release — it is stable and gets long-term support:
nvm install --lts
nvm use --lts
nvm alias default lts/*
Check the versions:
node -v
npm -v
Step 3. Prepare the application
Upload the code (with git clone or rsync) and install the dependencies in production mode:
cd /var/www/myapp
npm ci --omit=dev
npm ci installs the exact versions from package-lock.json — more predictable than npm install. Check that the application starts:
node app.js
If you see “server listening on port 3000”, stop it (Ctrl+C) and move on to pm2.
Step 4. Install pm2 and start the app
Install pm2 globally and start the application:
npm install -g pm2
pm2 start app.js --name myapp
For applications whose entry point is declared in package.json:
pm2 start npm --name myapp -- run start
Check the status:
pm2 status
pm2 logs myapp
Step 5. Autostart after a reboot
So that pm2 brings the applications up when the server starts, generate a systemd service and save the process list:
pm2 startup systemd
# run the command pm2 prints (it starts with sudo env ...)
pm2 save
pm2 save records the current set of processes, and pm2 resurrect restores them automatically after a reboot.
Step 6. Cluster mode (optional)
If the application supports several workers, pm2 can run a process on every CPU core:
pm2 start app.js --name myapp -i max
That balances the load across the cores without an external balancer.
Useful pm2 commands
| Task | Command |
|---|---|
| List processes | pm2 list |
| Restart | pm2 restart myapp |
| Graceful reload | pm2 reload myapp |
| Stop | pm2 stop myapp |
| Remove from pm2 | pm2 delete myapp |
| Monitoring | pm2 monit |
FAQ
Why use nvm if Node.js is in apt? The version in the Ubuntu repository is often outdated. nvm installs any version you need and lets you switch quickly between projects with different requirements.
What is the difference between pm2 restart and reload?
restart restarts the process completely (with a short outage), while reload in cluster mode restarts the workers one by one with zero downtime.
My app crashes — will pm2 bring it back?
Yes, pm2 restarts a crashed process automatically. Set --max-restarts and watch the logs so a permanent error does not turn into a restart loop.
How do I limit the memory a process uses?
The --max-memory-restart 300M flag restarts the application when it exceeds the limit — protection against memory leaks.
Node.js applications benefit from a fast CPU and enough memory. You can pick a server on the VPS hosting page, and for containerised builds there is Docker VPS.