Deploying a Node.js application to production requires more than just running node app.js. This guide covers everything from initial setup to a production-ready deployment with process management, reverse proxy, and SSL.
Prerequisites
- VPS with Ubuntu 22.04
- Domain name (optional but recommended)
- Basic Linux command line knowledge
- Node.js application ready to deploy
Step 1: Server Setup
Update System
sudo apt update && sudo apt upgrade -y
Install Node.js
# Install Node.js 20.x LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# Verify installation
node --version
npm --version
Create Deploy User
sudo adduser deploy
sudo usermod -aG sudo deploy
su - deploy
Step 2: Upload Your Application
Option A: Git Clone
cd ~
git clone https://github.com/yourusername/your-app.git
cd your-app
Option B: SCP Upload
From your local machine:
scp -r ./your-app deploy@your_server_ip:~/
Install Dependencies
cd ~/your-app
npm install --production
Step 3: Environment Configuration
Create Environment File
nano .env
Add your environment variables:
NODE_ENV=production
PORT=3000
DATABASE_URL=your_database_url
SECRET_KEY=your_secret_key
Secure the File
chmod 600 .env
Step 4: Process Management with PM2
PM2 keeps your app running and restarts it on crashes.
Install PM2
sudo npm install -g pm2
Start Your Application
pm2 start app.js --name "my-app"
# Or with npm script
pm2 start npm --name "my-app" -- start
PM2 Configuration File
Create ecosystem.config.js:
module.exports = {
apps: [{
name: 'my-app',
script: 'app.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}]
};
Start with config:
pm2 start ecosystem.config.js --env production
Auto-Start on Reboot
pm2 startup
pm2 save
Useful PM2 Commands
pm2 list # List all processes
pm2 logs my-app # View logs
pm2 monit # Monitor resources
pm2 restart my-app # Restart app
pm2 stop my-app # Stop app
pm2 delete my-app # Remove from PM2
Step 5: Nginx Reverse Proxy
Nginx handles incoming requests and forwards them to your Node.js app.
Install Nginx
sudo apt install nginx
Configure Nginx
Create configuration file:
sudo nano /etc/nginx/sites-available/my-app
Add configuration:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
location / {
proxy_pass http://localhost: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-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
Enable Configuration
sudo ln -s /etc/nginx/sites-available/my-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Configure Firewall
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP' # After SSL setup
Step 6: SSL Certificate with Let's Encrypt
Install Certbot
sudo apt install certbot python3-certbot-nginx
Obtain Certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Auto-Renewal
Certbot sets up auto-renewal automatically. Test it:
sudo certbot renew --dry-run
Step 7: Optimize for Production
Nginx Optimizations
Add to /etc/nginx/nginx.conf:
http {
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# Connection settings
keepalive_timeout 65;
client_max_body_size 10M;
}
Node.js Optimizations
In your app, ensure:
// Trust proxy for correct IP detection
app.set('trust proxy', 1);
// Helmet for security headers
const helmet = require('helmet');
app.use(helmet());
// Compression
const compression = require('compression');
app.use(compression());
Step 8: Monitoring
PM2 Monitoring
pm2 monit
Application Logs
pm2 logs my-app --lines 100
System Resources
htop
Step 9: Deployment Workflow
Manual Deployment
cd ~/your-app
git pull origin main
npm install --production
pm2 restart my-app
Deployment Script
Create deploy.sh:
#!/bin/bash
cd ~/your-app
git pull origin main
npm install --production
npm run build # If you have a build step
pm2 restart my-app
echo "Deployment complete!"
Make executable:
chmod +x deploy.sh
Troubleshooting
App Not Starting
Check PM2 logs:
pm2 logs my-app --err
502 Bad Gateway
- Check if Node.js app is running:
pm2 list - Check Nginx error logs:
sudo tail -f /var/log/nginx/error.log - Verify port configuration matches
High Memory Usage
- Check for memory leaks
- Consider using PM2 cluster mode
- Implement proper garbage collection
SSL Issues
- Verify certificate:
sudo certbot certificates - Check Nginx SSL config
- Ensure firewall allows HTTPS
Security Checklist
- [ ] Environment variables secured
- [ ] Non-root user for app
- [ ] Firewall configured
- [ ] SSL enabled
- [ ] Security headers set
- [ ] Rate limiting configured
- [ ] Input validation in app
Conclusion
Your Node.js application is now running in production with:
- PM2 for process management
- Nginx as reverse proxy
- SSL for secure connections
- Auto-restart on crashes and reboots
HeavenCloud VPS provides the perfect infrastructure for Node.js deployments with fast NVMe storage, reliable uptime, and easy scaling options.