Skip to Content
WWWDeployment

Deployment Guide

Overview

This guide covers deployment strategies, environment setup, and best practices for deploying the www application in different environments.

Deployment Architecture

Infrastructure Components

  • Web Server: Node.js application server
  • Reverse Proxy: Nginx for load balancing and SSL termination
  • Database/Cache: Redis for session storage and caching
  • Container Platform: Docker and Docker Compose

Environment Structure

┌─ Production ─┐ ┌─ Staging ─┐ ┌─ Development ─┐ │ Live App │ │ Testing │ │ Local │ │ Real Data │ │ Sandbox │ │ Hot Reload │ │ SSL/CDN │ │ Testing │ │ Debug Mode │ └──────────────┘ └───────────┘ └──────────────┘

Docker Deployment

Docker Configuration

Located in docker/www/Dockerfile:

FROM node:20.11.1-alpine WORKDIR /app # Copy package files COPY package*.json ./ # Install dependencies RUN npm ci --only=production # Copy application code COPY . . # Build assets RUN npm run build # Expose port EXPOSE 8079 # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8079/health || exit 1 # Start application CMD ["npm", "start"]

Docker Compose Setup

# docker-compose.yml version: '3.8' services: www: build: context: ./www dockerfile: ../docker/www/Dockerfile ports: - "8079:8079" environment: - NODE_ENV=production - REDIS_URL=redis://redis:6379 depends_on: - redis restart: unless-stopped volumes: - ./logs:/app/logs redis: image: redis:7-alpine ports: - "6379:6379" volumes: - redis_data:/data restart: unless-stopped nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf - ./ssl:/etc/nginx/ssl depends_on: - www restart: unless-stopped volumes: redis_data:

Environment Setup

Production Environment

Prerequisites

  • Docker and Docker Compose
  • SSL certificates
  • Domain name configuration
  • Environment variables configured

Deployment Steps

# 1. Clone repository git clone <repository-url> cd tunnelflight # 2. Set up environment variables cp .env.example .env.production # Edit .env.production with production values # 3. Build and start services docker-compose -f docker-compose.prod.yml up -d # 4. Verify deployment docker-compose ps curl -f http://localhost:8079/health

Staging Environment

Configuration

# Staging-specific environment NODE_ENV=staging APP_PORT=8082 REDIS_URL=redis://staging-redis:6379 # Build and deploy docker-compose -f docker-compose.staging.yml up -d

Development Environment

Local Setup

# Install dependencies cd www npm install # Set up local environment cp .env.example .env # Edit .env with development values # Start development server npm run dev

Nginx Configuration

Reverse Proxy Setup

# /etc/nginx/sites-available/tunnelflight server { listen 80; listen 443 ssl http2; server_name yourdomain.com; # SSL Configuration ssl_certificate /etc/nginx/ssl/cert.pem; ssl_certificate_key /etc/nginx/ssl/key.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; # Security Headers add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; # Gzip Compression gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml; # Static Assets location /css/ { alias /var/www/tunnelflight/public/css/; expires 1y; add_header Cache-Control "public, immutable"; } location /js/ { alias /var/www/tunnelflight/public/js/; expires 1y; add_header Cache-Control "public, immutable"; } location /img/ { alias /var/www/tunnelflight/public/img/; expires 1y; add_header Cache-Control "public, immutable"; } # Proxy to Node.js App location / { proxy_pass http://www:8079; 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; } # Health Check location /health { proxy_pass http://www:8079/health; access_log off; } }

Environment Variables

Production Variables

# Application NODE_ENV=production APP_PORT=8079 IS_PRODUCTION=true # Database/Cache REDIS_URL=redis://prod-redis:6379 REDIS_PASSWORD=secure_redis_password # Authentication JWT_SECRET=your_production_jwt_secret GOOGLE_CLIENT_ID=prod_google_client_id GOOGLE_CLIENT_SECRET=prod_google_client_secret # External Services INFISICAL_CLIENT_ID=prod_infisical_client_id INFISICAL_CLIENT_SECRET=prod_infisical_client_secret INFISICAL_PROJECT_ID=prod_project_id # Monitoring LOG_LEVEL=info SENTRY_DSN=your_sentry_dsn

Staging Variables

# Application NODE_ENV=staging APP_PORT=8082 # Use staging credentials and endpoints GOOGLE_CLIENT_ID=staging_google_client_id API_BASE_URL=https://staging-api.yourdomain.com

CI/CD Pipeline

GitHub Actions Example

# .github/workflows/deploy.yml name: Deploy to Production on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '20.11.1' cache: 'npm' cache-dependency-path: www/package-lock.json - name: Install dependencies run: | cd www npm ci - name: Run tests run: | cd www npm test - name: Build assets run: | cd www npm run build - name: Build Docker image run: docker build -t tunnelflight-www:${{ github.sha }} -f docker/www/Dockerfile ./www - name: Deploy to production run: | # Deploy logic (e.g., push to registry, update services) echo "Deploying to production..."

Health Checks and Monitoring

Application Health Check

// Health check endpoint app.get('/health', (req, res) => { const health = { status: 'healthy', timestamp: new Date().toISOString(), uptime: process.uptime(), version: process.env.npm_package_version, environment: process.env.NODE_ENV }; // Check Redis connection redisClient.ping((err, result) => { if (err) { health.status = 'unhealthy'; health.redis = 'disconnected'; } else { health.redis = 'connected'; } const statusCode = health.status === 'healthy' ? 200 : 503; res.status(statusCode).json(health); }); });

Docker Health Check

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8079/health || exit 1

Monitoring Integration

  • Application Monitoring: Sentry for error tracking
  • Performance Monitoring: APM tools integration
  • Log Aggregation: Centralized logging setup
  • Uptime Monitoring: External service monitoring

SSL/TLS Configuration

Certificate Management

# Let's Encrypt with Certbot certbot --nginx -d yourdomain.com # Or manual certificate installation sudo cp cert.pem /etc/nginx/ssl/ sudo cp private.key /etc/nginx/ssl/

SSL Best Practices

  • Use TLS 1.2 or higher
  • Strong cipher suites
  • HSTS headers
  • Certificate auto-renewal

Database Migrations and Seeding

Redis Data Management

# Backup Redis data redis-cli --rdb /backup/dump.rdb # Restore Redis data redis-cli --pipe < /backup/restore.redis

Data Seeding

# Seed initial data npm run seed:production

Troubleshooting

Common Deployment Issues

Container Won’t Start

# Check container logs docker-compose logs www # Verify environment variables docker-compose exec www env | grep NODE_ENV

Redis Connection Issues

# Test Redis connectivity docker-compose exec www redis-cli -h redis ping # Check Redis logs docker-compose logs redis

Nginx Configuration Issues

# Test Nginx configuration docker-compose exec nginx nginx -t # Reload Nginx configuration docker-compose exec nginx nginx -s reload

Performance Optimization

Application Optimization

  • Enable gzip compression
  • Optimize asset loading
  • Implement caching strategies
  • Monitor memory usage

Database Optimization

  • Redis memory optimization
  • Connection pooling
  • Query optimization
  • Index management

Rollback Procedures

Application Rollback

# Tag current version before deployment docker tag tunnelflight-www:latest tunnelflight-www:backup # Rollback to previous version docker-compose down docker-compose up -d tunnelflight-www:previous-version

Database Rollback

# Restore Redis from backup redis-cli flushall redis-cli --pipe < /backup/previous-state.redis
Last updated on