Files
oldvine/docs/DEPLOYMENT.md

17 KiB

Deployment Guide - The Old Vine Hotel

🚀 Production Deployment

This guide covers deploying The Old Vine Hotel website to production environments.

🏗️ Infrastructure Requirements

Minimum Server Specifications

Backend Server:

  • CPU: 2 vCPUs
  • RAM: 4GB
  • Storage: 50GB SSD
  • OS: Ubuntu 20.04 LTS or CentOS 8

Database Server:

  • CPU: 2 vCPUs
  • RAM: 4GB
  • Storage: 100GB SSD
  • MongoDB 5.0+

Recommended for High Traffic:

  • Load Balancer (nginx)
  • Redis for caching
  • CDN for static assets
  • Multiple application instances

1. Build Production Images

# Clone repository
git clone <your-repo-url>
cd old-vine-hotel-website

# Build frontend
cd client
npm install
npm run build

# Build backend
cd ../server
npm install

2. Docker Configuration

Frontend Dockerfile:

# client/Dockerfile
FROM node:16-alpine as builder

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Backend Dockerfile:

# server/Dockerfile
FROM node:16-alpine

WORKDIR /app

# Install dependencies
COPY package*.json ./
RUN npm ci --only=production

# Copy source code
COPY . .

# Create logs directory
RUN mkdir -p logs

# Expose port
EXPOSE 5000

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

CMD ["npm", "start"]

3. Production Docker Compose

# docker-compose.prod.yml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
    depends_on:
      - frontend
      - backend
    restart: unless-stopped

  frontend:
    build:
      context: ./client
      dockerfile: Dockerfile
    restart: unless-stopped

  backend:
    build:
      context: ./server
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
      - MONGODB_URI=${MONGODB_URI}
      - JWT_SECRET=${JWT_SECRET}
      - STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
    env_file:
      - .env.production
    volumes:
      - ./logs:/app/logs
    depends_on:
      - mongodb
      - redis
    restart: unless-stopped

  mongodb:
    image: mongo:5.0
    environment:
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_ROOT_USERNAME}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_ROOT_PASSWORD}
      - MONGO_INITDB_DATABASE=oldvinehotel
    volumes:
      - mongodb_data:/data/db
      - ./mongodb/mongod.conf:/etc/mongod.conf:ro
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    restart: unless-stopped

volumes:
  mongodb_data:
  redis_data:

4. Nginx Configuration

# nginx/nginx.conf
events {
    worker_connections 1024;
}

http {
    upstream backend {
        server backend:5000;
    }

    upstream frontend {
        server frontend:80;
    }

    # Rate limiting
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

    # SSL Configuration
    server {
        listen 80;
        server_name oldvinehotel.com www.oldvinehotel.com;
        return 301 https://$server_name$request_uri;
    }

    server {
        listen 443 ssl http2;
        server_name oldvinehotel.com www.oldvinehotel.com;

        ssl_certificate /etc/nginx/ssl/fullchain.pem;
        ssl_certificate_key /etc/nginx/ssl/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;

        # 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";

        # API routes
        location /api/ {
            limit_req zone=api burst=20 nodelay;
            proxy_pass http://backend;
            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;
        }

        # Auth routes with stricter limits
        location /api/auth/login {
            limit_req zone=login burst=3 nodelay;
            proxy_pass http://backend;
        }

        # Frontend
        location / {
            proxy_pass http://frontend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # Static files caching
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
            expires 1y;
            add_header Cache-Control "public, no-transform";
            proxy_pass http://frontend;
        }
    }
}

5. Environment Configuration

# .env.production
NODE_ENV=production
PORT=5000

# Database
MONGODB_URI=mongodb://admin:secure_password@mongodb:27017/oldvinehotel?authSource=admin
MONGO_ROOT_USERNAME=admin
MONGO_ROOT_PASSWORD=secure_password

# Security
JWT_SECRET=your_super_secure_jwt_secret_key_for_production
JWT_EXPIRES_IN=7d

# External APIs
STRIPE_SECRET_KEY=sk_live_your_live_stripe_key
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret
GOOGLE_MAPS_API_KEY=your_production_maps_key

# Email
EMAIL_HOST=smtp.sendgrid.net
EMAIL_PORT=587
EMAIL_USER=apikey
EMAIL_PASS=your_sendgrid_api_key
EMAIL_FROM=noreply@oldvinehotel.com

# Hotel Information
HOTEL_NAME=The Old Vine Hotel
HOTEL_ADDRESS=123 Luxury Avenue, Downtown District, City, State 12345
HOTEL_PHONE=+1 (555) 123-4567
HOTEL_EMAIL=info@oldvinehotel.com

# Integration APIs
OPERA_PMS_URL=https://your-opera-pms.com/api
OPERA_PMS_USERNAME=production_user
OPERA_PMS_PASSWORD=production_password

BOOKING_COM_API_URL=https://distribution-xml.booking.com
BOOKING_COM_USERNAME=your_booking_username
BOOKING_COM_PASSWORD=your_booking_password

# Redis
REDIS_URL=redis://redis:6379

# Logging
LOG_LEVEL=info

6. Deploy with Docker Compose

# Create production environment file
cp .env.example .env.production
# Edit .env.production with your production values

# Deploy
docker-compose -f docker-compose.prod.yml up -d

# Check status
docker-compose -f docker-compose.prod.yml ps

# View logs
docker-compose -f docker-compose.prod.yml logs -f backend

☁️ Cloud Deployment Options

AWS Deployment

Using AWS ECS

# Install AWS CLI and ECS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# Configure AWS credentials
aws configure

# Create ECS cluster
aws ecs create-cluster --cluster-name old-vine-hotel

# Create task definition
aws ecs register-task-definition --cli-input-json file://ecs-task-definition.json

# Create service
aws ecs create-service \
  --cluster old-vine-hotel \
  --service-name hotel-website \
  --task-definition hotel-website:1 \
  --desired-count 2

ECS Task Definition

{
  "family": "hotel-website",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "512",
  "memory": "1024",
  "executionRoleArn": "arn:aws:iam::account:role/ecsTaskExecutionRole",
  "containerDefinitions": [
    {
      "name": "hotel-backend",
      "image": "your-account.dkr.ecr.us-east-1.amazonaws.com/hotel-backend:latest",
      "portMappings": [
        {
          "containerPort": 5000,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "NODE_ENV",
          "value": "production"
        }
      ],
      "secrets": [
        {
          "name": "MONGODB_URI",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:account:secret:hotel/mongodb-uri"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/hotel-website",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ]
}

Google Cloud Platform

# Install gcloud CLI
curl https://sdk.cloud.google.com | bash
exec -l $SHELL
gcloud init

# Create GKE cluster
gcloud container clusters create hotel-cluster \
  --num-nodes=3 \
  --zone=us-central1-a

# Build and push images
gcloud builds submit --tag gcr.io/PROJECT_ID/hotel-backend ./server
gcloud builds submit --tag gcr.io/PROJECT_ID/hotel-frontend ./client

# Deploy to GKE
kubectl apply -f k8s/

DigitalOcean App Platform

# .do/app.yaml
name: old-vine-hotel
services:
- name: backend
  source_dir: /server
  github:
    repo: your-username/old-vine-hotel
    branch: main
  run_command: npm start
  environment_slug: node-js
  instance_count: 2
  instance_size_slug: basic-xxs
  env:
  - key: NODE_ENV
    value: production
  - key: MONGODB_URI
    value: ${DB_CONNECTION_STRING}
    type: SECRET

- name: frontend
  source_dir: /client
  github:
    repo: your-username/old-vine-hotel
    branch: main
  build_command: npm run build
  environment_slug: node-js
  instance_count: 1
  instance_size_slug: basic-xxs
  routes:
  - path: /

databases:
- name: hotel-db
  engine: MONGODB
  version: "5"

🔧 Manual Server Deployment

1. Server Setup

# Update system
sudo apt update && sudo apt upgrade -y

# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs

# Install MongoDB
wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | sudo apt-key add -
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-5.0.list
sudo apt-get update
sudo apt-get install -y mongodb-org

# Install PM2 for process management
npm install -g pm2

# Install nginx
sudo apt install nginx

2. Application Deployment

# Clone repository
git clone <your-repo-url> /var/www/hotel
cd /var/www/hotel

# Install backend dependencies
cd server
npm install --production

# Install frontend dependencies and build
cd ../client
npm install
npm run build

# Copy build to nginx directory
sudo cp -r build/* /var/www/html/

3. PM2 Configuration

// ecosystem.config.js
module.exports = {
  apps: [
    {
      name: 'hotel-backend',
      script: './server/index.js',
      instances: 'max',
      exec_mode: 'cluster',
      env: {
        NODE_ENV: 'production',
        PORT: 5000
      },
      error_file: './logs/err.log',
      out_file: './logs/out.log',
      log_file: './logs/combined.log',
      time: true
    }
  ]
};
# Start application with PM2
pm2 start ecosystem.config.js

# Save PM2 configuration
pm2 save

# Setup PM2 startup
pm2 startup
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u $USER --hp $HOME

4. Nginx Configuration

# /etc/nginx/sites-available/hotel
server {
    listen 80;
    server_name oldvinehotel.com www.oldvinehotel.com;
    root /var/www/html;
    index index.html;

    # API proxy
    location /api/ {
        proxy_pass http://localhost:5000;
        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;
    }

    # Frontend
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Static files
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, no-transform";
    }
}
# Enable site
sudo ln -s /etc/nginx/sites-available/hotel /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

🔐 SSL Certificate Setup

Using Let's Encrypt (Certbot)

# Install Certbot
sudo apt install certbot python3-certbot-nginx

# Get SSL certificate
sudo certbot --nginx -d oldvinehotel.com -d www.oldvinehotel.com

# Test automatic renewal
sudo certbot renew --dry-run

Manual SSL Certificate

# Add to nginx configuration
server {
    listen 443 ssl http2;
    server_name oldvinehotel.com;
    
    ssl_certificate /etc/ssl/certs/oldvinehotel.com.crt;
    ssl_certificate_key /etc/ssl/private/oldvinehotel.com.key;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
    ssl_prefer_server_ciphers off;
    
    # ... rest of configuration
}

📊 Monitoring Setup

Application Monitoring

# Install monitoring tools
npm install -g clinic
npm install newrelic

# Setup log rotation
sudo nano /etc/logrotate.d/hotel
# /etc/logrotate.d/hotel
/var/www/hotel/logs/*.log {
    daily
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    create 644 www-data www-data
    postrotate
        pm2 reload hotel-backend
    endscript
}

Database Monitoring

# Enable MongoDB profiler
mongo
use oldvinehotel
db.setProfilingLevel(1, { slowms: 100 })

# Setup monitoring script
crontab -e
# Monitor disk space every hour
0 * * * * /usr/local/bin/check-disk-space.sh

# Backup database daily at 2 AM
0 2 * * * /usr/local/bin/backup-mongodb.sh

🔄 Backup Strategy

Database Backup

#!/bin/bash
# backup-mongodb.sh

DATE=$(date +"%Y%m%d_%H%M%S")
BACKUP_DIR="/backups/mongodb"
DB_NAME="oldvinehotel"

# Create backup directory
mkdir -p $BACKUP_DIR

# Create backup
mongodump --db $DB_NAME --out $BACKUP_DIR/$DATE

# Compress backup
tar -czf $BACKUP_DIR/mongodb_backup_$DATE.tar.gz -C $BACKUP_DIR $DATE

# Remove uncompressed backup
rm -rf $BACKUP_DIR/$DATE

# Keep only last 7 days of backups
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete

# Upload to cloud storage (optional)
# aws s3 cp $BACKUP_DIR/mongodb_backup_$DATE.tar.gz s3://hotel-backups/

Application Backup

#!/bin/bash
# backup-application.sh

DATE=$(date +"%Y%m%d_%H%M%S")
APP_DIR="/var/www/hotel"
BACKUP_DIR="/backups/application"

# Create backup
tar -czf $BACKUP_DIR/app_backup_$DATE.tar.gz \
    --exclude="node_modules" \
    --exclude=".git" \
    --exclude="logs" \
    $APP_DIR

# Keep only last 3 backups
ls -t $BACKUP_DIR/app_backup_*.tar.gz | tail -n +4 | xargs rm -f

🚨 Disaster Recovery

Recovery Procedures

# Database Recovery
mongorestore --db oldvinehotel /path/to/backup/oldvinehotel

# Application Recovery
cd /var/www
tar -xzf /backups/application/app_backup_YYYYMMDD_HHMMSS.tar.gz
sudo chown -R www-data:www-data hotel

# Restart services
pm2 restart all
sudo systemctl restart nginx

Health Check Automation

#!/bin/bash
# health-check.sh

# Check API health
if ! curl -f http://localhost:5000/health > /dev/null 2>&1; then
    echo "API health check failed" | mail -s "Hotel API Down" admin@oldvinehotel.com
    pm2 restart hotel-backend
fi

# Check database connection
if ! mongo --eval "db.adminCommand('ismaster')" > /dev/null 2>&1; then
    echo "Database connection failed" | mail -s "Hotel DB Down" admin@oldvinehotel.com
    sudo systemctl restart mongod
fi

# Check disk space
USAGE=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $USAGE -gt 80 ]; then
    echo "Disk usage is at $USAGE%" | mail -s "High Disk Usage" admin@oldvinehotel.com
fi

📈 Performance Optimization

Database Optimization

# MongoDB configuration
# /etc/mongod.conf
storage:
  wiredTiger:
    engineConfig:
      cacheSizeGB: 2
    collectionConfig:
      blockCompressor: snappy

net:
  bindIp: 127.0.0.1
  port: 27017
  maxIncomingConnections: 100

operationProfiling:
  slowOpThresholdMs: 100
  mode: slowOp

Application Optimization

// Add to server configuration
const compression = require('compression');
const helmet = require('helmet');

app.use(compression());
app.use(helmet());

// Connection pooling
mongoose.connect(process.env.MONGODB_URI, {
  maxPoolSize: 10,
  serverSelectionTimeoutMS: 5000,
  socketTimeoutMS: 45000,
});

🔍 Troubleshooting

Common Issues

# Check application logs
pm2 logs hotel-backend

# Check nginx logs
sudo tail -f /var/log/nginx/error.log

# Check MongoDB logs
sudo tail -f /var/log/mongodb/mongod.log

# Check system resources
top
df -h
free -h

Performance Issues

# Monitor database performance
mongo
db.currentOp()
db.serverStatus()

# Check slow queries
db.system.profile.find().limit(5).sort({ts:-1}).pretty()

# Monitor Node.js performance
node --inspect server/index.js
# Then open chrome://inspect

This deployment guide provides comprehensive instructions for deploying The Old Vine Hotel website in production environments. Choose the deployment method that best fits your infrastructure and requirements.