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
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.
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).
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 processespm2 restart myapp - Restart apppm2 stop myapp - Stop apppm2 logs myapp - View logspm2 monit - Monitor resourcespm2 reload myapp - Zero-downtime reloadConfigure 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
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