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
Option 1: Docker Compose (Recommended for Small-Medium Scale)
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
.envfiles 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
-
Enable Caching
- Redis for session and data caching
- CDN for static assets
- Browser caching headers
-
Database Optimization
- Add indexes
- Use connection pooling
- Optimize queries
- Use read replicas
-
Application Optimization
- Enable compression (gzip)
- Minimize API calls
- Use pagination
- Lazy load content
Troubleshooting Production Issues
Common Issues
-
High Memory Usage
- Check for memory leaks
- Optimize queries
- Increase server resources
-
Slow Response Times
- Check database performance
- Review slow queries
- Enable caching
- Check network latency
-
Database Connection Issues
- Check connection pool settings
- Verify database is running
- Check network connectivity