Rui Tao's Portfolio

Modern Web Application Deployment Setup

Published on
Published on
/4 mins read/---

Nginx Configuration

Complete Nginx configuration for a modern web application:

# /etc/nginx/sites-available/web-app
server {
    listen 80;
    server_name your-domain.com;
    
    # Security headers
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";
    add_header Referrer-Policy "strict-origin-when-cross-origin";
    add_header Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval';";
 
    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 10240;
    gzip_proxied expired no-cache no-store private auth;
    gzip_types text/plain text/css text/xml text/javascript application/javascript application/x-javascript application/xml;
    gzip_disable "MSIE [1-6]\.";
 
    # Frontend static files
    location / {
        root /var/www/web-app;
        index index.html;
        try_files $uri $uri/ /index.html;
 
        # Cache control
        location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
            expires 7d;
            add_header Cache-Control "public, no-transform";
        }
    }
 
    # API proxy
    location /api/ {
        proxy_pass http://localhost:3001/api/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        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;
 
        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
 
    # WebSocket proxy
    location /socket.io/ {
        proxy_pass http://localhost:3001/socket.io/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        
        # WebSocket specific timeouts
        proxy_connect_timeout 7d;
        proxy_send_timeout 7d;
        proxy_read_timeout 7d;
    }
 
    # Health check endpoint
    location /health {
        access_log off;
        return 200 'OK';
        add_header Content-Type text/plain;
    }
}

Cloudflare Tunnel Configuration

Configuration for secure access through Cloudflare Tunnel:

# config.yaml
tunnel: web-app-tunnel
credentials-file: /etc/cloudflared/cert.json
 
ingress:
  # Main website
  - hostname: your-domain.com
    service: http://localhost:80
    originRequest:
      connectTimeout: 10s
      noTLSVerify: true
 
  # API subdomain
  - hostname: api.your-domain.com
    service: http://localhost:3001
    originRequest:
      connectTimeout: 10s
      noTLSVerify: true
      http2Origin: true
 
  # Development environment
  - hostname: dev.your-domain.com
    service: http://localhost:8080
    originRequest:
      connectTimeout: 10s
      noTLSVerify: true
 
  # Catch-all rule
  - service: http_status:404

Deployment Scripts

1. Main Deployment Script

#!/bin/bash
# deploy.sh
 
# Configuration
APP_NAME="web-app"
DEPLOY_PATH="/var/www/$APP_NAME"
BACKUP_PATH="/var/www/backups"
NGINX_CONF="/etc/nginx/sites-available/$APP_NAME"
LOG_FILE="/var/log/deploy.log"
 
# Logging function
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
 
# Error handling
set -e
trap 'log "Error occurred on line $LINENO. Exit code: $?"' ERR
 
# Start deployment
log "Starting deployment..."
 
# Create backup
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
if [ -d "$DEPLOY_PATH" ]; then
    log "Creating backup..."
    mkdir -p "$BACKUP_PATH"
    tar -czf "$BACKUP_PATH/$APP_NAME-$BACKUP_DATE.tar.gz" -C "$DEPLOY_PATH" .
fi
 
# Build frontend
log "Building frontend..."
npm ci
npm run build
 
# Deploy frontend
log "Deploying frontend..."
rm -rf "$DEPLOY_PATH"/*
cp -r dist/* "$DEPLOY_PATH/"
chown -R www-data:www-data "$DEPLOY_PATH"
chmod -R 755 "$DEPLOY_PATH"
 
# Update Nginx configuration
log "Updating Nginx configuration..."
cp nginx.conf "$NGINX_CONF"
nginx -t && systemctl reload nginx
 
# Restart backend services
log "Restarting backend services..."
pm2 reload ecosystem.config.js --env production
 
# Verify deployment
log "Verifying deployment..."
curl -s -o /dev/null -w "%{http_code}" http://localhost/health
 
log "Deployment completed successfully!"

2. Environment Setup Script

#!/bin/bash
# setup-env.sh
 
# Install system dependencies
apt-get update
apt-get install -y nginx nodejs npm python3 python3-pip
 
# Install Node.js dependencies
npm install -g pm2
npm install -g typescript
 
# Install Python dependencies
pip3 install -r requirements.txt
 
# Setup Cloudflare Tunnel
curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
dpkg -i cloudflared.deb
cloudflared service install
 
# Setup directories
mkdir -p /var/www/web-app
mkdir -p /var/www/backups
mkdir -p /var/log/web-app
 
# Setup permissions
chown -R www-data:www-data /var/www/web-app
chmod -R 755 /var/www/web-app

3. Process Management Configuration

// ecosystem.config.js
module.exports = {
  apps: [
    {
      name: 'api-server',
      script: 'dist/main.js',
      instances: 'max',
      exec_mode: 'cluster',
      autorestart: true,
      watch: false,
      max_memory_restart: '1G',
      env_production: {
        NODE_ENV: 'production',
        PORT: 3001
      }
    },
    {
      name: 'python-service',
      script: 'run.py',
      interpreter: 'python3',
      instances: 1,
      autorestart: true,
      watch: false,
      max_memory_restart: '2G',
      env_production: {
        PYTHONUNBUFFERED: 1,
        PORT: 5000
      }
    }
  ]
};

4. Monitoring Script

#!/bin/bash
# monitor.sh
 
# Check system resources
check_resources() {
    echo "=== System Resources ==="
    echo "CPU Usage:"
    top -bn1 | grep "Cpu(s)" | awk '{print $2}'
    echo "Memory Usage:"
    free -m | awk 'NR==2{printf "%.2f%%\n", $3*100/$2}'
    echo "Disk Usage:"
    df -h / | awk 'NR==2{print $5}'
}
 
# Check services
check_services() {
    echo "=== Service Status ==="
    services=("nginx" "pm2-root" "cloudflared")
    for service in "${services[@]}"; do
        status=$(systemctl is-active "$service")
        echo "$service: $status"
    done
}
 
# Check logs for errors
check_logs() {
    echo "=== Recent Errors ==="
    echo "Nginx Errors:"
    tail -n 5 /var/log/nginx/error.log
    echo "Application Errors:"
    tail -n 5 /var/log/web-app/error.log
}
 
# Main monitoring loop
while true; do
    clear
    date
    echo "===================="
    check_resources
    echo "===================="
    check_services
    echo "===================="
    check_logs
    sleep 60
done

Notes

  • Keep scripts up to date
  • Monitor script execution
  • Implement proper error handling
  • Maintain backup strategy
  • Regular security updates
  • Monitor resource usage
  • Document configuration changes