Node.js Deployment

Deploy and manage Node.js applications on your TinyBox VPS

Deployment Overview

This guide covers deploying Node.js applications with proper process management, reverse proxy configuration, and SSL certificates.

Process Manager

PM2 for application lifecycle

Reverse Proxy

Nginx for load balancing

Security

SSL/TLS encryption

1

Install Node.js and npm

Option A: Install from NodeSource Repository (Recommended)

# Update system
apt update && apt upgrade -y

# Install curl if not present
apt install curl -y

# Add NodeSource repository (Node.js 20.x)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -

# Install Node.js and npm
apt install nodejs -y

# Verify installation
node --version
npm --version

Option B: Install using Node Version Manager (NVM)

# Install NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

# Reload shell configuration
source ~/.bashrc

# Install latest LTS Node.js
nvm install --lts
nvm use --lts

# Set default version
nvm alias default node

✓ Pro Tip

Use NVM if you need to manage multiple Node.js versions. Use NodeSource for production deployments with a single version.

2

Prepare Your Application

Upload Application Code

# Create application directory
mkdir -p /var/www/myapp
cd /var/www/myapp

# Upload your code using SCP or Git
# Example with Git:
git clone https://github.com/yourusername/your-app.git .

# Set proper ownership
chown -R www-data:www-data /var/www/myapp
chmod -R 755 /var/www/myapp

Install Dependencies

# Navigate to app directory
cd /var/www/myapp

# Install production dependencies
npm install --production

# Or if using package-lock.json
npm ci --production

Configure Environment Variables

# Create environment file
nano /var/www/myapp/.env

# Example environment variables:
NODE_ENV=production
PORT=3000
DB_HOST=localhost
DB_USER=your_db_user
DB_PASS=your_db_password
DB_NAME=your_database

# Set proper permissions for env file
chmod 600 /var/www/myapp/.env

Security Note

Never commit .env files to version control. Keep sensitive credentials secure and use proper file permissions (600).

3

Install and Configure PM2

Install PM2 Process Manager

# Install PM2 globally
npm install -g pm2

# Verify PM2 installation
pm2 --version

# Setup PM2 startup script
pm2 startup systemd

# Follow the instructions shown and run the generated command

Create PM2 Configuration

# Create PM2 ecosystem file
nano /var/www/myapp/ecosystem.config.js
module.exports = { apps: [{ name: 'myapp', script: './app.js', // or server.js, index.js cwd: '/var/www/myapp', instances: 'max', // Use all CPU cores exec_mode: 'cluster', env: { NODE_ENV: 'production', PORT: 3000 }, error_file: './logs/err.log', out_file: './logs/out.log', log_file: './logs/combined.log', time: true, max_restarts: 10, min_uptime: '10s', max_memory_restart: '1G', watch: false, ignore_watch: ['node_modules', 'logs'] }] };

Start Application with PM2

# Create logs directory mkdir -p /var/www/myapp/logs # Start application using ecosystem file cd /var/www/myapp pm2 start ecosystem.config.js # Save PM2 process list pm2 save # Check application status pm2 status pm2 logs myapp

Useful PM2 Commands

pm2 list - Show all processes
pm2 restart myapp - Restart app
pm2 stop myapp - Stop app
pm2 logs myapp - View logs
pm2 monit - Monitor resources
pm2 reload myapp - Zero-downtime reload
4

Configure Nginx Reverse Proxy

Install Nginx (if not already installed)

# Install Nginx apt install nginx -y # Start and enable Nginx systemctl start nginx systemctl enable nginx

Create Nginx Configuration

# Create site configuration nano /etc/nginx/sites-available/myapp.com
server { listen 80; server_name myapp.com www.myapp.com; # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; # 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 application/xml+rss text/javascript; 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; # Timeout settings proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # Static files (if your app serves them) location /static { alias /var/www/myapp/public; expires 1y; add_header Cache-Control "public, immutable"; } # Health check endpoint location /health { access_log off; return 200 "healthy\n"; add_header Content-Type text/plain; } }

Enable Site and Test Configuration

# Enable the site ln -s /etc/nginx/sites-available/myapp.com /etc/nginx/sites-enabled/ # Test Nginx configuration nginx -t # Reload Nginx systemctl reload nginx # Check if your app is accessible curl -H "Host: myapp.com" http://localhost
5

Setup SSL Certificate

Install Certbot and Obtain SSL Certificate

# Install Certbot for Nginx apt install certbot python3-certbot-nginx -y # Obtain SSL certificate certbot --nginx -d myapp.com -d www.myapp.com # Test automatic renewal certbot renew --dry-run

✓ SSL Configuration Complete

Certbot automatically updated your Nginx configuration to redirect HTTP to HTTPS and configured SSL certificates.

Monitoring and Logging

Application Logs

# View PM2 logs pm2 logs myapp # View specific log files tail -f /var/www/myapp/logs/out.log tail -f /var/www/myapp/logs/err.log # View Nginx logs tail -f /var/log/nginx/access.log tail -f /var/log/nginx/error.log

System Monitoring

# PM2 monitoring dashboard pm2 monit # System resource usage htop iotop # Check application performance pm2 show myapp # Memory usage free -h df -h

Setup Log Rotation

# Install PM2 log rotation module pm2 install pm2-logrotate # Configure log rotation (keep 30 days, max 10MB per file) pm2 set pm2-logrotate:max_size 10M pm2 set pm2-logrotate:retain 30 pm2 set pm2-logrotate:compress true

Best Practices & Security

✓ Security Checklist

  • • Use environment variables for secrets
  • • Enable HTTPS with valid SSL certificates
  • • Keep Node.js and dependencies updated
  • • Use security headers in Nginx
  • • Implement rate limiting
  • • Regular security audits with `npm audit`

⚡ Performance Tips

  • • Use PM2 cluster mode for multi-core usage
  • • Enable Nginx gzip compression
  • • Implement proper caching strategies
  • • Optimize database queries
  • • Monitor memory usage and restart limits
  • • Use CDN for static assets

Automated Deployment Script

Create a deployment script for easy updates:

#!/bin/bash
# Create deployment script
nano /var/www/myapp/deploy.sh

#!/bin/bash
set -e

echo "🚀 Starting deployment..."

# Pull latest code
git pull origin main

# Install/update dependencies
npm ci --production

# Run database migrations (if applicable)
# npm run migrate

# Restart application with PM2
pm2 reload myapp

echo "✅ Deployment completed successfully!"

# Make script executable
chmod +x /var/www/myapp/deploy.sh

# Usage: ./deploy.sh

Common Issues & Solutions

Application won't start

Check PM2 logs and verify all dependencies are installed:

pm2 logs myapp --lines 50 npm ls --depth=0

502 Bad Gateway Error

Check if Node.js app is running and port configuration:

pm2 status netstat -tulpn | grep :3000 nginx -t

High Memory Usage

Monitor memory usage and set restart limits:

pm2 monit # Set memory limit in ecosystem.config.js: max_memory_restart: '512M'

SSL Certificate Issues

Verify certificate status and renewal:

certbot certificates certbot renew --dry-run systemctl status certbot.timer