Node.js Hosting on a VPS in 2026: PM2, Nginx and a Production Setup That Lasts

Platforms that run your Node.js app for you are convenient until you need a background worker, a WebSocket server, a specific Node version or predictable monthly costs. A VPS gives you all of that, as long as you set it up properly. This guide shows a production setup for Node.js on a Linux VPS: installing Node, running the app with PM2, putting Nginx in front, and the operational details that keep it fast and online.
Choosing the server
Node.js runs JavaScript on a single thread per process, so CPU matters in two ways: per-core speed for response time, and core count for how many processes you can run in parallel. For a typical API or Next.js app, 2 vCPU and 4 GB RAM is a good start. If you also build the app on the server, give it more memory, because builds are often heavier than the running app. A Cloud VPS with fully dedicated vCPU on AMD Ryzen and EPYC processors keeps response times stable under load; a Linux VPS is a cost-effective alternative for smaller services.
Step 1: Install Node.js the maintainable way
Avoid the outdated Node.js package that ships with many distributions. Use the NodeSource repository or a version manager such as nvm or fnm, and stick to an LTS release in production. Pin the same major version in your project's engines field so development and production match.
Step 2: Run the app with PM2
PM2 keeps your app running, restarts it on crashes, can use every CPU core in cluster mode and manages logs. Define the app in an ecosystem file:
module.exports = {
apps: [{
name: "api",
script: "dist/server.js",
instances: "max",
exec_mode: "cluster",
max_memory_restart: "500M",
env: { NODE_ENV: "production", PORT: 3000 }
}]
};Start it with pm2 start ecosystem.config.js, then run pm2 save and pm2 startup so it comes back after a reboot. Cluster mode runs one process per core and spreads requests across them; use it only if your app is stateless, or keeps state in Redis or a database rather than in memory. The max_memory_restart setting is a safety valve against slow memory leaks.
Add the pm2-logrotate module so logs do not grow until the disk is full.
Step 3: Put Nginx in front
Never expose the Node process directly on port 80 or 443. Bind it to 127.0.0.1 and let Nginx handle TLS, compression, static files and connection management:
server {
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}The Upgrade and Connection headers are what make WebSockets and Socket.IO work. Add HTTPS with Certbot. If your app sits behind the proxy, tell your framework to trust it, for example app.set("trust proxy", 1) in Express, so client IPs and HTTPS detection are correct.
Step 4: Deploy without downtime
With PM2 in cluster mode, pm2 reload api restarts processes one at a time, so the app keeps serving requests during a deploy. A simple, reliable flow:
Pull the new release into a fresh directory.
Run
npm ciand your build.Switch a symlink to the new directory.
Run
pm2 reload.
Keep the previous release on disk so rollback is one symlink change away. If builds are heavy, build in CI and copy only the output to the server.
Step 5: Environment and secrets
Keep configuration in environment variables or a protected .env file outside the repository. Set NODE_ENV=production, which enables optimizations in many frameworks and libraries.
Step 6: Performance basics
Serve static assets from Nginx or a CDN instead of Node.
Enable gzip or Brotli compression in Nginx.
Move CPU-heavy work, such as image processing or PDF generation, into a queue with separate worker processes, so it does not block the event loop.
Cache expensive responses in Redis.
Step 7: Monitoring and security
Use
pm2 monitfor a quick view, plus an external uptime check on a real health endpoint.Watch event-loop lag and memory, not just CPU.
Run
npm auditregularly and keep dependencies updated.Run the app as a non-root user and allow only SSH, HTTP and HTTPS through the firewall.
Host your Node.js apps on IM HOST
IM HOST Cloud VPS and Linux VPS plans give you full root access, NVMe storage, a dedicated IPv4 address and support from engineers 24/7, in the US, UK, Poland, Germany and Egypt. Cloud VPS also includes a free automatic backup every 72 hours for the length of your subscription.
More from our blog
Discover more practical guides and product insights from the IM Host team.
View all articles