Skip to main content

Production Deployment Guide

Complete guide for deploying Bellamy Book to production with best practices, security, and scalability considerations.

Pre-Deployment Checklist

Before deploying to production, ensure:

  • All environment variables are configured
  • Database backups are set up
  • SSL/TLS certificates are obtained
  • Domain names are configured
  • Monitoring and logging are configured
  • Security settings are reviewed
  • Performance testing is completed
  • Disaster recovery plan is in place

Deployment Options

Best for: Small to medium deployments, single server setups.

Advantages:

  • Easy to set up and maintain
  • All services in one place
  • Simple updates and rollbacks
  • Good for teams new to production deployments

Limitations:

  • Single point of failure
  • Limited horizontal scaling
  • Requires manual load balancing

Option 2: Cloud Platform (AWS, Azure, GCP)

Best for: Managed services, serverless options, global distribution.

Advantages:

  • Managed databases and services
  • Global CDN
  • Auto-scaling
  • Built-in monitoring
  • High availability zones

Limitations:

  • Vendor lock-in
  • Higher costs
  • Platform-specific configurations

Production Environment Setup

1. Server Requirements

Minimum Requirements:

  • CPU: 4 cores
  • RAM: 8GB
  • Storage: 100GB SSD
  • Network: 100Mbps

Recommended Requirements:

  • CPU: 8+ cores
  • RAM: 16GB+
  • Storage: 500GB+ SSD
  • Network: 1Gbps
  • Backup Storage: Separate from primary

Docker Compose deployment: If you deploy the full app (infrastructure + backend + frontend + admin + all workers) with Docker Compose on a single server, use 16GB+ RAM and 8+ CPU. See dockerLocalENV/RESOURCE_REQUIREMENTS.md in the repository for per-service resource breakdown.

2. Operating System

Recommended:

  • Ubuntu 20.04 LTS or 22.04 LTS
  • Debian 11+
  • RHEL 8+ / CentOS Stream 8+

Setup:

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

# Install essential tools
sudo apt install -y curl wget git vim ufw fail2ban

# Configure firewall
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable

3. Domain and DNS Configuration

DNS Records:

A Record: @ -> Your Server IP
A Record: api -> Your Server IP
A Record: admin -> Your Server IP
CNAME: www -> @

SSL Certificate: Use Let's Encrypt for free SSL certificates:

sudo apt install certbot
sudo certbot certonly --standalone -d your-domain.com -d api.your-domain.com

Docker Compose Production Deployment

Step 1: Prepare Production Environment

# Clone repository
git clone https://github.com/nmtri3108/BellamyBook-Official.git
cd bellamy-book/dockerLocalENV

Step 2: Configure Production Settings

Create .env.production (or use dockerProd/.env.example as reference for production) and edit:

# Application
NODE_ENV=production
ASPNETCORE_ENVIRONMENT=Production

# Database - Use strong passwords!
POSTGRES_USER=bellamy_prod
POSTGRES_PASSWORD=STRONG_PASSWORD_HERE
POSTGRES_DB=bellamybook_prod

# MongoDB
MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=STRONG_PASSWORD_HERE

# Redis
REDIS_PASSWORD=STRONG_PASSWORD_HERE

# JWT - Generate secure key: openssl rand -base64 32
JWT_SECRET_KEY=YOUR_SECURE_JWT_SECRET_KEY

# Storage
STORAGE_PROVIDER=S3
S3_BUCKET=your-bucket-name
S3_REGION=us-east-1
S3_ACCESS_KEY=your-access-key
S3_SECRET_KEY=your-secret-key

# SMTP
SMTP_SERVER=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USERNAME=apikey
SMTP_PASSWORD=your-sendgrid-api-key

# CORS - Add your production domains
ALLOWED_ORIGINS=https://your-domain.com,https://admin.your-domain.com

# Base URLs
API_BASE_URL=https://api.your-domain.com
FRONTEND_BASE_URL=https://your-domain.com
ADMIN_BASE_URL=https://admin.your-domain.com

Step 3: Create Production Docker Compose

Create docker-compose.prod.yml:

version: '3.8'

services:
postgres:
image: postgres:14-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- bellamy-network
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5

mongodb:
image: mongo:5.0
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
volumes:
- mongodb_data:/data/db
- ./mongo-keyfile:/etc/mongo-keyfile:ro
networks:
- bellamy-network
restart: unless-stopped
command: mongod --replSet rs0 --keyFile /etc/mongo-keyfile

redis:
image: redis:7-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
networks:
- bellamy-network
restart: unless-stopped

backend:
build:
context: ../Src/backend
dockerfile: Dockerfile
environment:
ASPNETCORE_ENVIRONMENT: Production
ConnectionStrings__PrimaryConnectionString: Host=postgres;Database=${POSTGRES_DB};Username=${POSTGRES_USER};Password=${POSTGRES_PASSWORD}
JwtSettings__SecretKey: ${JWT_SECRET_KEY}
depends_on:
- postgres
- mongodb
- redis
networks:
- bellamy-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/api/health"]
interval: 30s
timeout: 10s
retries: 3

frontend:
build:
context: ../Src/frontend
dockerfile: Dockerfile
environment:
VITE_API_URL: ${API_BASE_URL}
depends_on:
- backend
networks:
- bellamy-network
restart: unless-stopped

nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
- frontend_build:/usr/share/nginx/html:ro
depends_on:
- frontend
- backend
networks:
- bellamy-network
restart: unless-stopped

volumes:
postgres_data:
mongodb_data:
redis_data:
frontend_build:

networks:
bellamy-network:
driver: bridge

Step 4: Configure Nginx Reverse Proxy

Create nginx.conf:

upstream backend {
server backend:5000;
}

upstream frontend {
server frontend:3000;
}

server {
listen 80;
server_name your-domain.com www.your-domain.com;
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com;

ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

# Frontend
location / {
proxy_pass http://frontend;
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;
}

# Backend API
location /api {
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;
}

# WebSocket
location /ws {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}

# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
}

Step 5: Deploy

# Build and start services
docker-compose -f docker-compose.prod.yml --env-file .env.production up -d --build

# Run migrations
docker-compose -f docker-compose.prod.yml exec backend dotnet ef database update --project DatabaseApplication

# Verify services
docker-compose -f docker-compose.prod.yml ps
docker-compose -f docker-compose.prod.yml logs -f

Security Best Practices

1. Environment Variables

  • Never commit .env files to version control
  • Use strong, unique passwords
  • Rotate secrets regularly
  • Use secrets management (AWS Secrets Manager, HashiCorp Vault)

2. Database Security

# Use strong passwords
# Enable SSL connections
# Restrict network access
# Regular backups
# Enable audit logging

3. Application Security

  • Enable HTTPS only
  • Configure CORS properly
  • Use rate limiting
  • Enable input validation
  • Sanitize user inputs
  • Use parameterized queries

4. Server Security

# Keep system updated
sudo apt update && sudo apt upgrade -y

# Configure firewall
sudo ufw enable

# Install fail2ban
sudo apt install fail2ban
sudo systemctl enable fail2ban

# Disable root login
sudo nano /etc/ssh/sshd_config
# Set: PermitRootLogin no
sudo systemctl restart sshd

Monitoring and Logging

1. Application Logs

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

# Log rotation
# Configure in docker-compose or use logrotate

2. Health Checks

# API health check
curl https://api.your-domain.com/api/health

# Database health
docker-compose -f docker-compose.prod.yml exec postgres pg_isready

3. Monitoring Tools

  • Prometheus - Metrics collection
  • Grafana - Visualization
  • ELK Stack - Log aggregation
  • Sentry - Error tracking

Backup Strategy

1. Database Backups

# PostgreSQL backup
docker-compose -f docker-compose.prod.yml exec postgres pg_dump -U ${POSTGRES_USER} ${POSTGRES_DB} > backup_$(date +%Y%m%d).sql

# MongoDB backup
docker-compose -f docker-compose.prod.yml exec mongodb mongodump --out /backup/$(date +%Y%m%d)

2. Automated Backups

Create backup.sh:

#!/bin/bash
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d_%H%M%S)

# PostgreSQL backup
docker-compose -f docker-compose.prod.yml exec -T postgres pg_dump -U ${POSTGRES_USER} ${POSTGRES_DB} > ${BACKUP_DIR}/postgres_${DATE}.sql

# MongoDB backup
docker-compose -f docker-compose.prod.yml exec -T mongodb mongodump --archive > ${BACKUP_DIR}/mongodb_${DATE}.archive

# Upload to S3 (optional)
aws s3 cp ${BACKUP_DIR}/postgres_${DATE}.sql s3://your-backup-bucket/
aws s3 cp ${BACKUP_DIR}/mongodb_${DATE}.archive s3://your-backup-bucket/

# Cleanup old backups (keep 30 days)
find ${BACKUP_DIR} -type f -mtime +30 -delete

Add to crontab:

0 2 * * * /path/to/backup.sh

Scaling Considerations

Horizontal Scaling

  • Use load balancer (Nginx, HAProxy)
  • Multiple backend instances
  • Database read replicas
  • Redis cluster for caching
  • CDN for static assets

Vertical Scaling

  • Increase server resources
  • Optimize database queries
  • Enable connection pooling
  • Use caching effectively

Maintenance

Updates

# Pull latest code
git pull origin main

# Rebuild and restart
docker-compose -f docker-compose.prod.yml up -d --build

# Run migrations
docker-compose -f docker-compose.prod.yml exec backend dotnet ef database update --project DatabaseApplication

Rollback

# Revert to previous version
git checkout <previous-commit>
docker-compose -f docker-compose.prod.yml up -d --build

Performance Optimization

  1. Enable Caching

    • Redis for session and data caching
    • CDN for static assets
    • Browser caching headers
  2. Database Optimization

    • Add indexes
    • Use connection pooling
    • Optimize queries
    • Use read replicas
  3. Application Optimization

    • Enable compression (gzip)
    • Minimize API calls
    • Use pagination
    • Lazy load content

Troubleshooting Production Issues

Common Issues

  1. High Memory Usage

    • Check for memory leaks
    • Optimize queries
    • Increase server resources
  2. Slow Response Times

    • Check database performance
    • Review slow queries
    • Enable caching
    • Check network latency
  3. Database Connection Issues

    • Check connection pool settings
    • Verify database is running
    • Check network connectivity

Next Steps