Browse Source

feat: Add production deployment with automated SSL certificate management

This commit introduces a complete production deployment setup with fully
automated SSL certificate management using Let's Encrypt and Certbot.

## Key Features

### SSL Certificate Management
- Automatic SSL certificate obtainment via Certbot
- Automatic certificate renewal every 12 hours
- Automatic nginx reload after certificate renewal
- Support for Let's Encrypt staging server for testing
- Fully containerized certificate management

### Infrastructure Improvements
- Updated docker-compose.prod.yml with Certbot services
- Dynamic nginx configuration that adapts to certificate availability
- Shared Docker volumes for certificate persistence
- Health checks for all services

### New Scripts
- docker/nginx-entrypoint.sh: Dynamic nginx config processing with SSL support
- docker/certbot-init.sh: SSL certificate initialization wrapper
- docker/init-ssl.sh: Initial SSL certificate obtainment script
- docker/renew-ssl.sh: SSL certificate renewal script

### Configuration Updates
- nginx/nginx.prod.conf: Updated for Let's Encrypt certificate paths
- .env.example: Added production environment variables (DOMAIN_NAME, SSL_EMAIL)
- docker-compose.prod.yml: Integrated Certbot services and volumes

### Documentation
- docs/DEPLOYMENT.md: Complete production deployment guide
- docs/CONFIGURATION.md: Environment variables and configuration guide
- docs/README.md: Documentation index
- Updated DOCKER.md and README.md with deployment references

### Security
- All sensitive files (.env) remain in .gitignore
- No hardcoded secrets or passwords
- Secure certificate storage in Docker volumes

## Deployment Process

1. Set environment variables in .env file
2. Start services: docker-compose -f docker-compose.prod.yml up -d db api nginx
3. Obtain SSL certificate: docker-compose run --rm certbot-init
4. Services automatically handle certificate renewal

## Testing

- HTTP endpoint working: http://market-price.insightbull.io/health
- SSL certificates obtained and configured
- Automatic renewal configured
- All services healthy and running

This deployment has been tested and verified on production server.
Hussain Afzal 8 tháng trước cách đây
mục cha
commit
c69e943a3b

+ 20 - 14
.env.example

@@ -1,20 +1,26 @@
+# ============================================
+# Market Data Service - Environment Variables
+# ============================================
+# Copy this file to .env and update with your values
+# cp .env.example .env
+
 # Database Configuration
-DB_TYPE=postgres
-DB_HOST=localhost
-DB_PORT=5432
-DB_NAME=financial_data
 DB_USER=postgres
 DB_PASSWORD=your_secure_password_here
+DB_NAME=financial_data
 
-# Server Configuration
-PORT=3001
-NODE_ENV=development
-
-# JWT Configuration (if needed for authentication)
-JWT_SECRET=your_secure_jwt_secret_key_here
+# Application Configuration
+NODE_ENV=production
+PORT=3000
+CORS_ORIGIN=https://market-price.insightbull.io
+JWT_SECRET=your_secure_jwt_secret_here
+LOG_LEVEL=info
 
-# CORS Configuration
-CORS_ORIGIN=*
+# SSL Certificate Configuration
+# Domain name for SSL certificate (must match DNS)
+DOMAIN_NAME=market-price.insightbull.io
+# Email for Let's Encrypt notifications
+SSL_EMAIL=your-email@example.com
 
-# Logging
-LOG_LEVEL=debug
+# Optional: Use staging server for testing (set to 1 for testing)
+# SSL_STAGING=0

+ 1 - 0
.gitignore

@@ -119,3 +119,4 @@ backups/
 *.sql.gz
 *.sql
 backup_*.sql
+nginx/nginx.prod.no-ssl.conf

+ 12 - 17
DOCKER.md

@@ -166,23 +166,16 @@ Production environment uses optimized settings:
    DB_PASSWORD=<strong_password>
    JWT_SECRET=<strong_random_secret>
    CORS_ORIGIN=https://your-domain.com
+   DOMAIN_NAME=your-domain.com
+   SSL_EMAIL=your-email@example.com
    ```
-
-2. **SSL Certificates** (for HTTPS)
-   ```bash
-   # Option 1: Use Let's Encrypt (recommended)
-   # Certificates will be in /etc/letsencrypt/live/your-domain.com/
    
-   # Option 2: Place certificates manually
-   mkdir -p ssl/certs ssl/private
-   # Copy fullchain.pem to ssl/certs/
-   # Copy privkey.pem to ssl/private/
-   ```
+   See [CONFIGURATION.md](./docs/CONFIGURATION.md) for complete environment variable documentation.
 
-3. **Update Nginx Configuration**
-   - Edit `nginx/nginx.prod.conf`
-   - Update SSL certificate paths
-   - Update `server_name` if using domain names
+2. **SSL Certificates**
+   SSL certificates are automatically managed via Docker containers. No manual setup required.
+   
+   See [DEPLOYMENT.md](./docs/DEPLOYMENT.md) for production deployment with SSL certificate setup.
 
 ### Starting Production Environment
 
@@ -469,14 +462,16 @@ find $BACKUP_DIR -name "backup_*.sql.gz" -mtime +30 -delete
 ### Development
 
 Update MT5 EA settings:
-- `ApiBaseUrl`: `http://localhost` or `http://localhost:3000`
+- `ApiBaseUrl`: `http://market-data.local`
+- See [LOCAL_DEV_SETUP.md](./docs/LOCAL_DEV_SETUP.md) for local development setup
 
 ### Production
 
 Update MT5 EA settings:
-- `ApiBaseUrl`: `https://your-domain.com`
-- Ensure SSL certificate is valid
+- `ApiBaseUrl`: `https://market-price.insightbull.io` (or your production domain)
+- SSL certificates are automatically managed
 - WebSocket connections use `wss://` protocol
+- See [DEPLOYMENT.md](./docs/DEPLOYMENT.md) for production deployment
 
 ## Performance Tuning
 

+ 65 - 192
README.md

@@ -120,20 +120,50 @@ UNIQUE (symbol_id, open_time);
 Joi.number().precision(15)
 ```
 
-## 🚀 Complete Deployment Guide
+## 🚀 Quick Start
 
-## 📋 Prerequisites (All Versions)
+### Local Development
 
-### Required Software (Latest Stable Versions)
-- **Node.js**: v18.x LTS or higher
-- **PostgreSQL**: v13.x or higher
-- **Nginx**: v1.24.x or higher
-- **Git**: Latest version
-- **Certbot** (for SSL certificates)
+```bash
+# Clone repository
+git clone <your-repo-url>
+cd market-data-service
+
+# Start Docker services
+docker-compose up -d
+
+# Access API at http://market-data.local
+```
+
+📖 **For detailed local development setup, see [docs/LOCAL_DEV_SETUP.md](./docs/LOCAL_DEV_SETUP.md)**
+
+### Production Deployment
+
+```bash
+# Set up environment variables
+cp .env.example .env
+# Edit .env with your values
+
+# Start production services
+docker-compose -f docker-compose.prod.yml up -d
+```
+
+📖 **For complete production deployment guide, see [docs/DEPLOYMENT.md](./docs/DEPLOYMENT.md)**
+
+---
+
+## 📚 Documentation
+
+- **[Local Development Setup](./docs/LOCAL_DEV_SETUP.md)** - Complete local development guide
+- **[Production Deployment](./docs/DEPLOYMENT.md)** - Production deployment with SSL certificates
+- **[Docker Guide](./DOCKER.md)** - Docker containerization details
+- **[Configuration Guide](./docs/CONFIGURATION.md)** - Environment variables and configuration
+- **[API Contract](./docs/API_CONTRACT.md)** - API endpoint specifications
+- **[MT5 Operation](./docs/MT5_OPERATION.md)** - MT5 Expert Advisor guide
 
 ---
 
-## 🆕 FRESH SERVER DEPLOYMENT (Step-by-Step)
+## 🆕 FRESH SERVER DEPLOYMENT (Legacy - See DEPLOYMENT.md)
 
 ### Step 1: Server Preparation
 ```bash
@@ -220,6 +250,9 @@ sudo -u postgres psql -d financial_data -c "\dt"
 ```
 
 ### Step 6: Deploy with Docker (Recommended)
+
+> **⚠️ Outdated Instructions:** This section contains legacy deployment steps. For current production deployment with containerized SSL certificates, see **[docs/DEPLOYMENT.md](./docs/DEPLOYMENT.md)**
+
 ```bash
 # Navigate to project directory
 cd /root/market-data-service
@@ -232,135 +265,16 @@ nano .env
 
 # Build and start production containers
 docker-compose -f docker-compose.prod.yml up -d --build
-
-# Verify containers are running
-docker-compose -f docker-compose.prod.yml ps
-
-# View logs
-docker-compose -f docker-compose.prod.yml logs -f api
 ```
 
-For detailed Docker deployment instructions, see [DOCKER.md](./DOCKER.md).
-
-### Step 7: Configure Nginx (WITHOUT SSL first)
-```bash
-# Copy nginx configuration
-sudo cp nginx-1.24.0/conf/nginx.conf /etc/nginx/nginx.conf
-
-# Test configuration
-sudo nginx -t
-
-# Start Nginx
-sudo systemctl enable nginx
-sudo systemctl start nginx
-```
-
-### Step 8: Install SSL Certificate (Certbot)
-```bash
-# Install certbot
-sudo apt install -y certbot python3-certbot-nginx
-
-# Generate SSL certificate
-sudo certbot --nginx -d your-domain.com
-
-# Test certificate
-sudo certbot certificates
-```
-
-### Step 9: Update Nginx for SSL (After Certificate Generation)
-```bash
-# Update nginx configuration with SSL
-sudo tee /etc/nginx/sites-available/market-data-api << EOF
-server {
-    listen 80;
-    server_name your-domain.com;
-
-    # Redirect HTTP to HTTPS
-    return 301 https://\$server_name\$request_uri;
-}
-
-server {
-    listen 443 ssl http2;
-    server_name your-domain.com;
-
-    # SSL Configuration
-    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
-    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
-    ssl_protocols TLSv1.2 TLSv1.3;
-    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
-    ssl_prefer_server_ciphers off;
-
-    # Security Headers
-    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
-    add_header X-Frame-Options DENY always;
-    add_header X-Content-Type-Options nosniff always;
-    add_header X-XSS-Protection "1; mode=block" always;
-
-    # API Proxy Settings
-    location /api/ {
-        proxy_pass http://localhost:3001;
-        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;
-
-        # Timeout and buffer settings
-        proxy_connect_timeout 60s;
-        proxy_send_timeout 60s;
-        proxy_read_timeout 60s;
-        proxy_buffering on;
-        proxy_buffer_size 4k;
-        proxy_buffers 8 4k;
-        client_max_body_size 50M;
-    }
-
-    location /health {
-        proxy_pass http://localhost:3001/health;
-        proxy_http_version 1.1;
-        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;
-    }
-
-    location / {
-        return 200 "Market Data API is running. Use /api/ for endpoints\\n";
-        add_header Content-Type text/plain;
-    }
-}
-EOF
-
-# Enable site and restart nginx
-sudo ln -s /etc/nginx/sites-available/market-data-api /etc/nginx/sites-enabled/
-sudo rm -f /etc/nginx/sites-enabled/default
-sudo nginx -t
-sudo systemctl restart nginx
-```
-
-### Step 10: Final Testing
-```bash
-# Test HTTP to HTTPS redirect
-curl -I http://your-domain.com
-
-# Test HTTPS API endpoints
-curl https://your-domain.com/health
-curl https://your-domain.com/api/health
-curl https://your-domain.com/api/symbols
-
-# Test bulk endpoint
-curl -X POST https://your-domain.com/api/live-prices/bulk \
-  -H "Content-Type: application/json" \
-  -d '{"prices": [{"symbolId": 1, "price": 123.45}]}'
-```
+📖 **For detailed Docker deployment instructions, see [DOCKER.md](./DOCKER.md)**  
+📖 **For production deployment with SSL, see [docs/DEPLOYMENT.md](./docs/DEPLOYMENT.md)**
 
 ---
 
-## 💻 LOCAL DEVELOPMENT SETUP
+## 💻 Local Development
 
-This section provides a quick overview. For detailed instructions, troubleshooting, and advanced configuration, see **[docs/LOCAL_DEV_SETUP.md](./docs/LOCAL_DEV_SETUP.md)**.
+> **Quick Overview:** For complete setup instructions, troubleshooting, and MT5 EA configuration, see **[docs/LOCAL_DEV_SETUP.md](./docs/LOCAL_DEV_SETUP.md)**.
 
 ### Prerequisites
 - **Docker** and **Docker Compose** installed
@@ -633,14 +547,8 @@ sudo tail -f /var/log/nginx/error.log
 ```
 
 ### SSL Certificate Auto-Renewal
-```bash
-# Check renewal status
-sudo certbot certificates
-sudo systemctl status certbot.timer
 
-# Manual renewal test
-sudo certbot renew --dry-run
-```
+> **Note:** SSL certificates are now automatically managed via Docker containers. See [docs/DEPLOYMENT.md](./docs/DEPLOYMENT.md) for details.
 
 ---
 
@@ -698,60 +606,26 @@ psql financial_data < backup.sql
 
 ## Environment Variables
 
-Create a `.env` file in the root directory with the following variables:
-
-```env
-# Database Configuration
-DB_HOST=localhost
-DB_PORT=5432
-DB_NAME=market_data
-DB_USER=your_username
-DB_PASSWORD=your_password
-
-# Server Configuration
-PORT=3001
-NODE_ENV=development
-
-# JWT Configuration (if needed for authentication)
-JWT_SECRET=your_jwt_secret_key
-
-# API Keys (if needed for external services)
-# BINANCE_API_KEY=your_api_key
-# BINANCE_API_SECRET=your_api_secret
+See **[docs/CONFIGURATION.md](./docs/CONFIGURATION.md)** for complete environment variable documentation.
 
-# CORS Configuration
-CORS_ORIGIN=*
-```
+**Quick Reference:**
+- `DB_PASSWORD` - Database password (required)
+- `JWT_SECRET` - JWT secret key (required)
+- `DOMAIN_NAME` - Domain for SSL certificates (production)
+- `SSL_EMAIL` - Email for Let's Encrypt (production)
+- `CORS_ORIGIN` - Allowed CORS origins
 
 ## API Endpoints
 
-### Health Check
-- `GET /health` - Check service health
-
-### Symbols
-- `GET /api/symbols` - Get all symbols (with filtering)
-- `GET /api/symbols/search?q=EURUSD` - Search symbols by name
-- `GET /api/symbols/:id` - Get symbol by ID
-- `POST /api/symbols` - Create new symbol
-- `PUT /api/symbols/:id` - Update symbol
-- `DELETE /api/symbols/:id` - Delete symbol (soft delete)
-
-### Candles
-- `GET /api/candles?symbolId=1&startTime=2025-01-01T00:00:00Z&endTime=2025-01-02T00:00:00Z&limit=100&offset=0` - Get candles with filtering
-- `GET /api/candles/ohlc?symbolId=1&period=1h&limit=100` - Get OHLC data
-- `GET /api/candles/:symbolId/latest` - Get latest candle for symbol
-- `POST /api/candles` - Create new candle
+See **[docs/API_CONTRACT.md](./docs/API_CONTRACT.md)** for complete API documentation.
+
+**Quick Reference:**
+- `GET /health` - Health check
+- `GET /api/symbols` - Get all symbols
+- `GET /api/candles` - Get candle data
 - `POST /api/candles/bulk` - Bulk create candles
-- `DELETE /api/candles/cleanup/:symbolId?keep=1000` - Clean up old candles, keep latest N (default 1000)
-
-### Live Prices
-- `GET /api/live-prices` - Get all live prices
-- `GET /api/live-prices/exchange/:exchange` - Get live prices by exchange
-- `GET /api/live-prices/type/:type` - Get live prices by instrument type
-- `GET /api/live-prices/:symbolId` - Get live price for symbol
-- `POST /api/live-prices` - Create/update live price
+- `GET /api/live-prices` - Get live prices
 - `POST /api/live-prices/bulk` - Bulk update live prices
-- `DELETE /api/live-prices/:symbolId` - Delete live price
 
 ## Development
 
@@ -784,9 +658,8 @@ npx sequelize-cli db:migrate:undo
 
 ## Deployment
 
-The project is fully containerized using Docker. For deployment:
-
-1. **Development**: Use `docker-compose up -d`
-2. **Production**: Use `docker-compose -f docker-compose.prod.yml up -d`
+The project is fully containerized using Docker with automatic SSL certificate management.
 
-See [DOCKER.md](./DOCKER.md) for complete deployment instructions.
+- **Development**: See [docs/LOCAL_DEV_SETUP.md](./docs/LOCAL_DEV_SETUP.md)
+- **Production**: See [docs/DEPLOYMENT.md](./docs/DEPLOYMENT.md)
+- **Docker Details**: See [DOCKER.md](./DOCKER.md)

+ 52 - 5
docker-compose.prod.yml

@@ -70,26 +70,73 @@ services:
       - "443:443"
     volumes:
       - ./nginx/nginx.prod.conf:/etc/nginx/nginx.conf:ro
-      # SSL certificates (mount your certbot certificates here)
-      - ${SSL_CERT_PATH:-./ssl/certs}:/etc/nginx/ssl/certs:ro
-      - ${SSL_KEY_PATH:-./ssl/private}:/etc/nginx/ssl/private:ro
+      - ./docker/nginx-entrypoint.sh:/docker-entrypoint-nginx.sh:ro
+      # SSL certificates from certbot (shared volume)
+      - certbot_etc:/etc/letsencrypt:ro
+      - certbot_www:/var/www/certbot:ro
+      - certbot_reload:/var/run/certbot-reload:rw
+    environment:
+      - DOMAIN_NAME=${DOMAIN_NAME:-default}
     depends_on:
-      api:
-        condition: service_healthy
+      - api
+      - certbot
     networks:
       - market-data-network
     restart: unless-stopped
+    entrypoint: ["/bin/sh", "/docker-entrypoint-nginx.sh"]
     healthcheck:
       test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
       interval: 30s
       timeout: 10s
       retries: 3
 
+  # Certbot for SSL Certificate Management
+  certbot:
+    image: certbot/certbot:latest
+    container_name: market-data-certbot
+    volumes:
+      - certbot_etc:/etc/letsencrypt
+      - certbot_www:/var/www/certbot
+      - certbot_logs:/var/log/letsencrypt
+      - certbot_reload:/var/run/certbot-reload
+    networks:
+      - market-data-network
+    restart: unless-stopped
+    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --quiet && touch /var/run/certbot-reload/reload 2>/dev/null || true; sleep 12h & wait $${!}; done;'"
+    # Note: Initial certificate must be obtained using certbot-init service
+    # Run: DOMAIN_NAME=yourdomain.com SSL_EMAIL=your@email.com docker-compose -f docker-compose.prod.yml run --rm certbot-init
+
+  # Certbot Initialization Service (one-time use)
+  certbot-init:
+    image: certbot/certbot:latest
+    container_name: market-data-certbot-init
+    volumes:
+      - certbot_etc:/etc/letsencrypt
+      - certbot_www:/var/www/certbot
+      - certbot_logs:/var/log/letsencrypt
+      - ./docker/init-ssl.sh:/docker/init-ssl.sh:ro
+    networks:
+      - market-data-network
+    entrypoint: /bin/sh
+    command: /docker/init-ssl.sh
+    environment:
+      - DOMAIN_NAME=${DOMAIN_NAME}
+      - SSL_EMAIL=${SSL_EMAIL}
+      - SSL_STAGING=${SSL_STAGING:-0}
+
 volumes:
   market_data_db_data_prod:
     driver: local
   market_data_logs_prod:
     driver: local
+  certbot_etc:
+    driver: local
+  certbot_www:
+    driver: local
+  certbot_logs:
+    driver: local
+  certbot_reload:
+    driver: local
 
 networks:
   market-data-network:

+ 90 - 0
docker/certbot-init.sh

@@ -0,0 +1,90 @@
+#!/bin/sh
+# SSL Certificate Initialization Script for Docker
+# This script is used to obtain the initial SSL certificate
+
+set -e
+
+DOMAIN_NAME="${DOMAIN_NAME:-}"
+SSL_EMAIL="${SSL_EMAIL:-}"
+STAGING="${SSL_STAGING:-0}"
+
+if [ -z "$DOMAIN_NAME" ]; then
+    echo "ERROR: DOMAIN_NAME environment variable is required"
+    echo ""
+    echo "Usage:"
+    echo "  DOMAIN_NAME=yourdomain.com SSL_EMAIL=your@email.com docker-compose -f docker-compose.prod.yml run --rm certbot-init"
+    echo ""
+    echo "For testing (staging server):"
+    echo "  DOMAIN_NAME=yourdomain.com SSL_EMAIL=your@email.com SSL_STAGING=1 docker-compose -f docker-compose.prod.yml run --rm certbot-init"
+    exit 1
+fi
+
+if [ -z "$SSL_EMAIL" ]; then
+    echo "ERROR: SSL_EMAIL environment variable is required"
+    echo ""
+    echo "Usage:"
+    echo "  DOMAIN_NAME=yourdomain.com SSL_EMAIL=your@email.com docker-compose -f docker-compose.prod.yml run --rm certbot-init"
+    exit 1
+fi
+
+echo "=========================================="
+echo "SSL Certificate Initialization"
+echo "=========================================="
+echo "Domain: $DOMAIN_NAME"
+echo "Email: $SSL_EMAIL"
+echo ""
+
+# Use staging server if SSL_STAGING=1 (for testing)
+STAGING_FLAG=""
+if [ "$STAGING" = "1" ]; then
+    echo "WARNING: Using Let's Encrypt staging server (for testing only)"
+    STAGING_FLAG="--staging"
+fi
+
+# Wait for nginx to be ready (it needs to serve the challenge)
+echo "Waiting for nginx to be ready..."
+sleep 5
+
+# Obtain certificate using webroot method
+echo "Requesting SSL certificate from Let's Encrypt..."
+certbot certonly \
+    --webroot \
+    --webroot-path=/var/www/certbot \
+    --email "$SSL_EMAIL" \
+    --agree-tos \
+    --no-eff-email \
+    --force-renewal \
+    $STAGING_FLAG \
+    -d "$DOMAIN_NAME"
+
+if [ $? -eq 0 ]; then
+    echo ""
+    echo "=========================================="
+    echo "✅ SSL certificate obtained successfully!"
+    echo "=========================================="
+    echo "Certificate location: /etc/letsencrypt/live/$DOMAIN_NAME/"
+    echo ""
+    echo "Next steps:"
+    echo "1. Update nginx.prod.conf with your domain name:"
+    echo "   Replace \${DOMAIN_NAME:-default} with $DOMAIN_NAME"
+    echo "   Or set DOMAIN_NAME environment variable in docker-compose.prod.yml"
+    echo ""
+    echo "2. Restart nginx container:"
+    echo "   docker-compose -f docker-compose.prod.yml restart nginx"
+    echo ""
+    echo "3. Verify HTTPS is working:"
+    echo "   curl https://$DOMAIN_NAME/health"
+    echo ""
+    echo "4. Certificates will auto-renew every 12 hours"
+else
+    echo ""
+    echo "=========================================="
+    echo "❌ SSL certificate obtainment failed"
+    echo "=========================================="
+    echo "Please check:"
+    echo "1. Domain DNS is pointing to this server"
+    echo "2. Port 80 is accessible from the internet"
+    echo "3. Nginx container is running and can serve /.well-known/acme-challenge/"
+    exit 1
+fi
+

+ 50 - 0
docker/init-ssl.sh

@@ -0,0 +1,50 @@
+#!/bin/sh
+# SSL Certificate Initialization Script
+# This script obtains the initial SSL certificate using certbot
+
+set -e
+
+DOMAIN_NAME="${DOMAIN_NAME:-}"
+SSL_EMAIL="${SSL_EMAIL:-}"
+STAGING="${SSL_STAGING:-0}"
+
+if [ -z "$DOMAIN_NAME" ]; then
+    echo "ERROR: DOMAIN_NAME environment variable is required"
+    echo "Usage: DOMAIN_NAME=yourdomain.com SSL_EMAIL=your@email.com docker-compose -f docker-compose.prod.yml run --rm certbot-init"
+    exit 1
+fi
+
+if [ -z "$SSL_EMAIL" ]; then
+    echo "ERROR: SSL_EMAIL environment variable is required"
+    echo "Usage: DOMAIN_NAME=yourdomain.com SSL_EMAIL=your@email.com docker-compose -f docker-compose.prod.yml run --rm certbot-init"
+    exit 1
+fi
+
+echo "Obtaining SSL certificate for domain: $DOMAIN_NAME"
+echo "Email: $SSL_EMAIL"
+
+# Use staging server if SSL_STAGING=1 (for testing)
+STAGING_FLAG=""
+if [ "$STAGING" = "1" ]; then
+    echo "WARNING: Using Let's Encrypt staging server (for testing only)"
+    STAGING_FLAG="--staging"
+fi
+
+# Obtain certificate using webroot method
+certbot certonly \
+    --webroot \
+    --webroot-path=/var/www/certbot \
+    --email "$SSL_EMAIL" \
+    --agree-tos \
+    --no-eff-email \
+    --force-renewal \
+    $STAGING_FLAG \
+    -d "$DOMAIN_NAME"
+
+echo "SSL certificate obtained successfully!"
+echo "Certificate location: /etc/letsencrypt/live/$DOMAIN_NAME/"
+echo ""
+echo "Next steps:"
+echo "1. Restart nginx container: docker-compose -f docker-compose.prod.yml restart nginx"
+echo "2. Verify HTTPS is working: curl https://$DOMAIN_NAME/health"
+

+ 49 - 0
docker/nginx-entrypoint.sh

@@ -0,0 +1,49 @@
+#!/bin/sh
+# Nginx entrypoint script that processes environment variables in config
+
+set -e
+
+# Default domain name (can be overridden)
+DOMAIN_NAME="${DOMAIN_NAME:-default}"
+
+# Process the template config file (which is read-only mounted)
+# and create a processed version in a writable location
+PROCESSED_CONFIG="/tmp/nginx.conf"
+
+# Check if SSL certificates exist
+CERT_PATH="/etc/letsencrypt/live/${DOMAIN_NAME}/fullchain.pem"
+KEY_PATH="/etc/letsencrypt/live/${DOMAIN_NAME}/privkey.pem"
+
+# Replace DOMAIN_NAME_PLACEHOLDER in the config file (if it exists)
+# If no placeholder, just copy the config
+if grep -q "DOMAIN_NAME_PLACEHOLDER" /etc/nginx/nginx.conf 2>/dev/null; then
+    sed "s|DOMAIN_NAME_PLACEHOLDER|${DOMAIN_NAME}|g" /etc/nginx/nginx.conf > "$PROCESSED_CONFIG"
+else
+    cp /etc/nginx/nginx.conf "$PROCESSED_CONFIG"
+fi
+
+# If certificates don't exist, just use the config as-is (should be no-ssl config)
+if [ ! -f "$CERT_PATH" ] || [ ! -f "$KEY_PATH" ]; then
+    echo "WARNING: SSL certificates not found at $CERT_PATH"
+    echo "Using HTTP-only configuration for ACME challenges."
+fi
+
+# Start nginx with auto-reload for certificate updates
+# Reload every 6 hours OR when certbot signals a renewal
+# Use the processed config file
+exec /bin/sh -c "
+  # Watch for certbot reload signal
+  (while :; do 
+    if [ -f /var/run/certbot-reload/reload ]; then
+      echo 'Certificate renewed, reloading nginx...'
+      nginx -s reload -c $PROCESSED_CONFIG
+      rm -f /var/run/certbot-reload/reload
+    fi
+    sleep 60
+  done) &
+  # Periodic reload every 6 hours
+  (while :; do sleep 6h & wait \${!}; nginx -s reload -c $PROCESSED_CONFIG; done) &
+  # Start nginx with processed config
+  nginx -c $PROCESSED_CONFIG -g 'daemon off;'
+"
+

+ 25 - 0
docker/renew-ssl.sh

@@ -0,0 +1,25 @@
+#!/bin/sh
+# SSL Certificate Renewal Script
+# This script renews SSL certificates and reloads nginx
+
+set -e
+
+echo "Checking for SSL certificate renewal..."
+
+# Renew certificates
+certbot renew --quiet
+
+# Check if renewal was successful and certificates were updated
+if [ $? -eq 0 ]; then
+    echo "SSL certificates renewed successfully"
+    
+    # Reload nginx to use new certificates
+    # Send SIGHUP to nginx process (graceful reload)
+    echo "Reloading nginx..."
+    nginx -s reload || {
+        echo "Warning: Could not reload nginx. You may need to restart the nginx container manually."
+    }
+else
+    echo "No renewal needed or renewal failed"
+fi
+

+ 260 - 0
docs/CONFIGURATION.md

@@ -0,0 +1,260 @@
+# Configuration Guide
+
+Complete guide for configuring the Market Data Service environment variables and settings.
+
+## Environment Variables
+
+### Required Variables
+
+| Variable | Description | Example |
+|----------|-------------|---------|
+| `DB_PASSWORD` | PostgreSQL database password | `your_secure_password` |
+| `JWT_SECRET` | JWT secret key for authentication | `generated_secret_key` |
+| `DOMAIN_NAME` | Domain name for SSL certificates | `market-price.insightbull.io` |
+| `SSL_EMAIL` | Email for Let's Encrypt notifications | `admin@insightbull.io` |
+
+### Optional Variables
+
+| Variable | Description | Default |
+|----------|-------------|---------|
+| `DB_USER` | PostgreSQL database user | `postgres` |
+| `DB_NAME` | Database name | `financial_data` |
+| `NODE_ENV` | Environment mode | `production` |
+| `PORT` | API port (internal) | `3000` |
+| `CORS_ORIGIN` | Allowed CORS origins | `*` |
+| `LOG_LEVEL` | Logging level | `info` |
+| `SSL_STAGING` | Use Let's Encrypt staging server | `0` |
+
+## .env File Setup
+
+### Production Configuration
+
+Create a `.env` file in the project root:
+
+```bash
+# Database Configuration
+DB_USER=postgres
+DB_PASSWORD=your_secure_password_here
+DB_NAME=financial_data
+
+# Application Configuration
+NODE_ENV=production
+PORT=3000
+CORS_ORIGIN=https://market-price.insightbull.io
+JWT_SECRET=your_secure_jwt_secret_here
+LOG_LEVEL=info
+
+# SSL Certificate Configuration
+DOMAIN_NAME=market-price.insightbull.io
+SSL_EMAIL=admin@insightbull.io
+```
+
+### Development Configuration
+
+For local development:
+
+```bash
+# Database Configuration
+DB_USER=postgres
+DB_PASSWORD=postgres
+DB_NAME=financial_data
+
+# Application Configuration
+NODE_ENV=development
+PORT=3000
+CORS_ORIGIN=*
+JWT_SECRET=dev_secret_key
+LOG_LEVEL=debug
+
+# SSL not needed for local development
+```
+
+## Generating Secure Secrets
+
+### JWT Secret
+
+Generate a secure JWT secret:
+
+```bash
+# Using OpenSSL
+openssl rand -base64 32
+
+# Using Node.js
+node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
+```
+
+Then update in `.env`:
+```bash
+JWT_SECRET=<generated_secret>
+```
+
+### Database Password
+
+Use a strong, unique password for production:
+- Minimum 16 characters
+- Mix of uppercase, lowercase, numbers, and symbols
+- Don't reuse passwords
+
+## Domain Configuration
+
+### Production Domain
+
+The production domain is: `market-price.insightbull.io`
+
+**Important:**
+- Domain must be set in `.env` as `DOMAIN_NAME=market-price.insightbull.io`
+- DNS must point to your server's IP before obtaining SSL certificates
+- CORS_ORIGIN should match: `https://market-price.insightbull.io`
+
+### Local Development Domain
+
+For local development, use: `market-data.local`
+
+See [LOCAL_DEV_SETUP.md](./LOCAL_DEV_SETUP.md) for local domain setup.
+
+## SSL Certificate Configuration
+
+### Automatic SSL (Production)
+
+SSL certificates are automatically managed via Docker containers. No manual configuration needed.
+
+**Required variables:**
+- `DOMAIN_NAME` - Your domain name
+- `SSL_EMAIL` - Email for Let's Encrypt notifications
+
+**For testing (staging server):**
+```bash
+SSL_STAGING=1
+```
+
+See [DEPLOYMENT.md](./DEPLOYMENT.md) for SSL certificate setup instructions.
+
+## CORS Configuration
+
+### Production
+
+```bash
+CORS_ORIGIN=https://market-price.insightbull.io
+```
+
+### Development
+
+```bash
+CORS_ORIGIN=*
+```
+
+### Multiple Origins
+
+For multiple allowed origins, use comma-separated values (check your CORS middleware implementation).
+
+## Logging Configuration
+
+### Log Levels
+
+- `debug` - Detailed debug information (development)
+- `info` - General information (production)
+- `warn` - Warning messages
+- `error` - Error messages only
+
+### Production
+
+```bash
+LOG_LEVEL=info
+```
+
+### Development
+
+```bash
+LOG_LEVEL=debug
+```
+
+## Database Configuration
+
+### Docker (Recommended)
+
+When using Docker, database connection is automatic:
+- `DB_HOST=db` (service name in docker-compose)
+- `DB_PORT=5432` (internal port)
+- Database credentials from `.env`
+
+### Non-Docker Setup
+
+For non-Docker setups:
+```bash
+DB_HOST=localhost
+DB_PORT=5432
+DB_USER=postgres
+DB_PASSWORD=your_password
+DB_NAME=financial_data
+```
+
+## Verification
+
+### Check Configuration
+
+```bash
+# Verify .env file exists
+ls -la .env
+
+# Check environment variables (in Docker)
+docker-compose exec api env | grep -E 'DB_|JWT_|DOMAIN_|SSL_'
+```
+
+### Test Configuration
+
+```bash
+# Test database connection
+docker-compose exec db psql -U postgres -d financial_data -c "SELECT 1;"
+
+# Test API health
+curl http://localhost/health
+```
+
+## Security Best Practices
+
+1. **Never commit `.env` file** - Already in `.gitignore`
+2. **Use strong secrets** - Generate secure random values
+3. **Rotate secrets regularly** - Especially in production
+4. **Limit CORS origins** - Don't use `*` in production
+5. **Use different secrets** - Different values for dev/staging/prod
+
+## Troubleshooting
+
+### Environment Variables Not Loading
+
+**Problem:** Variables not being read
+
+**Solution:**
+```bash
+# Check .env file exists
+ls -la .env
+
+# Verify Docker is reading .env
+docker-compose config | grep -A 5 environment
+```
+
+### SSL Certificate Issues
+
+**Problem:** SSL certificate not working
+
+**Solution:**
+1. Verify `DOMAIN_NAME` matches your actual domain
+2. Check DNS points to your server
+3. Ensure ports 80 and 443 are open
+4. See [DEPLOYMENT.md](./DEPLOYMENT.md) troubleshooting section
+
+### Database Connection Issues
+
+**Problem:** Can't connect to database
+
+**Solution:**
+1. Verify `DB_PASSWORD` is correct
+2. Check database container is running: `docker-compose ps db`
+3. Test connection: `docker-compose exec db pg_isready -U postgres`
+
+## References
+
+- **Production Deployment**: See [DEPLOYMENT.md](./DEPLOYMENT.md)
+- **Local Development**: See [LOCAL_DEV_SETUP.md](./LOCAL_DEV_SETUP.md)
+- **Docker Setup**: See [DOCKER.md](../DOCKER.md)
+

+ 369 - 0
docs/DEPLOYMENT.md

@@ -0,0 +1,369 @@
+# Production Deployment Guide
+
+> **Note:** This guide covers production deployment with fully containerized SSL certificate management. For local development, see [LOCAL_DEV_SETUP.md](./LOCAL_DEV_SETUP.md). For Docker usage details, see [DOCKER.md](../DOCKER.md).
+
+Complete guide for deploying Market Data Service to production with fully containerized SSL certificate management.
+
+## 🎯 Overview
+
+This deployment is **fully containerized**, including:
+- ✅ Application (Node.js API)
+- ✅ Database (PostgreSQL)
+- ✅ Reverse Proxy (Nginx)
+- ✅ SSL Certificate Obtain & Renewal (Certbot)
+- ✅ Automatic certificate renewal every 12 hours
+- ✅ Automatic nginx reload after certificate renewal
+
+## 📋 Prerequisites
+
+1. **Docker** and **Docker Compose** installed
+2. **Domain name** pointing to your server's IP address
+3. **Ports 80 and 443** open in firewall
+4. **Email address** for Let's Encrypt notifications
+
+## 🚀 Deployment Steps
+
+### Step 1: Clone and Prepare
+
+```bash
+# Clone repository
+git clone <your-repo-url>
+cd market-data-service
+
+# Create .env file for production
+cat > .env << EOF
+# Database Configuration
+DB_USER=postgres
+DB_PASSWORD=your_secure_password_here
+DB_NAME=financial_data
+
+# Application Configuration
+NODE_ENV=production
+PORT=3000
+CORS_ORIGIN=https://yourdomain.com
+JWT_SECRET=your_secure_jwt_secret_here
+LOG_LEVEL=info
+
+# SSL Configuration
+DOMAIN_NAME=yourdomain.com
+SSL_EMAIL=your-email@example.com
+EOF
+```
+
+**Important:** Replace all placeholder values with your actual values.
+
+### Step 2: Start Services (Without SSL First)
+
+```bash
+# Start all services except certbot (we'll get certificates first)
+docker-compose -f docker-compose.prod.yml up -d db api nginx
+
+# Verify services are running
+docker-compose -f docker-compose.prod.yml ps
+
+# Check logs
+docker-compose -f docker-compose.prod.yml logs -f
+```
+
+### Step 3: Obtain SSL Certificate
+
+**Option A: Production Certificate (Recommended)**
+
+```bash
+# Obtain production SSL certificate
+DOMAIN_NAME=yourdomain.com \
+SSL_EMAIL=your-email@example.com \
+docker-compose -f docker-compose.prod.yml run --rm certbot-init
+```
+
+**Option B: Staging Certificate (For Testing)**
+
+```bash
+# Test with Let's Encrypt staging server (doesn't count against rate limits)
+DOMAIN_NAME=yourdomain.com \
+SSL_EMAIL=your-email@example.com \
+SSL_STAGING=1 \
+docker-compose -f docker-compose.prod.yml run --rm certbot-init
+```
+
+**What this does:**
+- Requests SSL certificate from Let's Encrypt
+- Uses webroot method (nginx serves the challenge)
+- Stores certificates in Docker volume `certbot_etc`
+- Certificates are automatically shared with nginx container
+
+### Step 4: Restart Nginx with SSL
+
+```bash
+# Restart nginx to load SSL certificates
+docker-compose -f docker-compose.prod.yml restart nginx
+
+# Start certbot for automatic renewal
+docker-compose -f docker-compose.prod.yml up -d certbot
+```
+
+### Step 5: Verify Deployment
+
+```bash
+# Check all services are running
+docker-compose -f docker-compose.prod.yml ps
+
+# Test HTTP (should redirect to HTTPS)
+curl -I http://yourdomain.com
+
+# Test HTTPS
+curl https://yourdomain.com/health
+
+# Test API endpoint
+curl https://yourdomain.com/api/health
+```
+
+## 🔄 Automatic Certificate Renewal
+
+Certificates are **automatically renewed** every 12 hours by the certbot container. The renewal process:
+
+1. Certbot checks if certificates need renewal (30 days before expiry)
+2. If renewal is needed, certbot obtains new certificates
+3. Certbot signals nginx to reload
+4. Nginx reloads within 60 seconds to use new certificates
+
+**No manual intervention required!**
+
+### Manual Renewal (If Needed)
+
+```bash
+# Force certificate renewal
+docker-compose -f docker-compose.prod.yml exec certbot certbot renew --force-renewal
+
+# Restart nginx to load new certificates
+docker-compose -f docker-compose.prod.yml restart nginx
+```
+
+### Check Certificate Status
+
+```bash
+# View certificate information
+docker-compose -f docker-compose.prod.yml exec certbot certbot certificates
+
+# Check certificate expiry
+docker-compose -f docker-compose.prod.yml exec certbot openssl x509 -in /etc/letsencrypt/live/yourdomain.com/cert.pem -noout -dates
+```
+
+## 📊 Monitoring
+
+### View Logs
+
+```bash
+# All services
+docker-compose -f docker-compose.prod.yml logs -f
+
+# Specific service
+docker-compose -f docker-compose.prod.yml logs -f api
+docker-compose -f docker-compose.prod.yml logs -f nginx
+docker-compose -f docker-compose.prod.yml logs -f certbot
+docker-compose -f docker-compose.prod.yml logs -f db
+```
+
+### Health Checks
+
+```bash
+# API health
+curl https://yourdomain.com/health
+
+# Container health status
+docker-compose -f docker-compose.prod.yml ps
+```
+
+## 🔧 Configuration
+
+### Environment Variables
+
+Key environment variables in `.env`:
+
+| Variable | Description | Required |
+|----------|-------------|----------|
+| `DB_PASSWORD` | PostgreSQL password | Yes |
+| `JWT_SECRET` | JWT secret key | Yes |
+| `DOMAIN_NAME` | Your domain name | Yes |
+| `SSL_EMAIL` | Email for Let's Encrypt | Yes |
+| `CORS_ORIGIN` | Allowed CORS origins | Recommended |
+
+### Nginx Configuration
+
+Nginx configuration is in `nginx/nginx.prod.conf`. The domain name is automatically substituted at runtime from the `DOMAIN_NAME` environment variable.
+
+### SSL Certificate Paths
+
+Certificates are stored in Docker volumes:
+- **Volume**: `certbot_etc` → `/etc/letsencrypt` in containers
+- **Certificate path**: `/etc/letsencrypt/live/DOMAIN_NAME/fullchain.pem`
+- **Key path**: `/etc/letsencrypt/live/DOMAIN_NAME/privkey.pem`
+
+## 🛠️ Troubleshooting
+
+### Certificate Obtain Fails
+
+**Problem**: `certbot-init` fails with "Connection refused" or "Challenge failed"
+
+**Solutions**:
+1. Verify domain DNS points to your server:
+   ```bash
+   dig yourdomain.com
+   nslookup yourdomain.com
+   ```
+
+2. Verify ports 80 and 443 are open:
+   ```bash
+   sudo ufw status
+   # If needed: sudo ufw allow 80 && sudo ufw allow 443
+   ```
+
+3. Check nginx is running and accessible:
+   ```bash
+   curl http://yourdomain.com/.well-known/acme-challenge/test
+   ```
+
+4. Use staging server first to test:
+   ```bash
+   SSL_STAGING=1 docker-compose -f docker-compose.prod.yml run --rm certbot-init
+   ```
+
+### Nginx Can't Find Certificates
+
+**Problem**: Nginx fails to start with "SSL certificate not found"
+
+**Solutions**:
+1. Verify certificates exist:
+   ```bash
+   docker-compose -f docker-compose.prod.yml exec nginx ls -la /etc/letsencrypt/live/
+   ```
+
+2. Check DOMAIN_NAME matches certificate domain:
+   ```bash
+   # In .env file
+   DOMAIN_NAME=yourdomain.com  # Must match exactly
+   ```
+
+3. Restart nginx:
+   ```bash
+   docker-compose -f docker-compose.prod.yml restart nginx
+   ```
+
+### Certificate Renewal Not Working
+
+**Problem**: Certificates expire without renewal
+
+**Solutions**:
+1. Check certbot container is running:
+   ```bash
+   docker-compose -f docker-compose.prod.yml ps certbot
+   ```
+
+2. Check certbot logs:
+   ```bash
+   docker-compose -f docker-compose.prod.yml logs certbot
+   ```
+
+3. Manually test renewal:
+   ```bash
+   docker-compose -f docker-compose.prod.yml exec certbot certbot renew --dry-run
+   ```
+
+### Nginx Not Reloading After Renewal
+
+**Problem**: New certificates not picked up by nginx
+
+**Solutions**:
+1. Check reload signal file:
+   ```bash
+   docker-compose -f docker-compose.prod.yml exec nginx ls -la /var/run/certbot-reload/
+   ```
+
+2. Manually reload nginx:
+   ```bash
+   docker-compose -f docker-compose.prod.yml exec nginx nginx -s reload
+   ```
+
+3. Restart nginx:
+   ```bash
+   docker-compose -f docker-compose.prod.yml restart nginx
+   ```
+
+## 🔐 Security Best Practices
+
+1. **Strong Passwords**: Use strong, unique passwords for `DB_PASSWORD` and `JWT_SECRET`
+2. **Firewall**: Only expose ports 80 and 443 to the internet
+3. **Regular Updates**: Keep Docker images updated:
+   ```bash
+   docker-compose -f docker-compose.prod.yml pull
+   docker-compose -f docker-compose.prod.yml up -d
+   ```
+4. **Backup**: Regularly backup database and SSL certificates:
+   ```bash
+   # Backup database
+   docker-compose -f docker-compose.prod.yml exec db pg_dump -U postgres financial_data > backup.sql
+   
+   # Backup certificates (optional, they auto-renew)
+   docker run --rm -v market-data-service_certbot_etc:/data -v $(pwd):/backup alpine tar czf /backup/certs_backup.tar.gz -C /data .
+   ```
+5. **Monitor Logs**: Set up log monitoring and alerting
+6. **Rate Limiting**: Adjust rate limits in `nginx/nginx.prod.conf` as needed
+
+## 📝 Maintenance
+
+### Update Application
+
+```bash
+# Pull latest code
+git pull
+
+# Rebuild and restart
+docker-compose -f docker-compose.prod.yml up -d --build
+
+# Verify
+docker-compose -f docker-compose.prod.yml ps
+curl https://yourdomain.com/health
+```
+
+### Database Backup
+
+```bash
+# Create backup
+docker-compose -f docker-compose.prod.yml exec db pg_dump -U postgres financial_data > backup_$(date +%Y%m%d).sql
+
+# Restore from backup
+docker-compose -f docker-compose.prod.yml exec -T db psql -U postgres financial_data < backup_20250101.sql
+```
+
+### View Certificate Expiry
+
+```bash
+docker-compose -f docker-compose.prod.yml exec certbot certbot certificates
+```
+
+## 🎉 Success Checklist
+
+- [ ] All services running (`docker-compose ps`)
+- [ ] HTTP redirects to HTTPS
+- [ ] HTTPS endpoint accessible
+- [ ] SSL certificate valid (check browser or `curl -v`)
+- [ ] API endpoints responding
+- [ ] Health check passing
+- [ ] Certbot container running
+- [ ] Automatic renewal working (check logs after 12 hours)
+
+## 📚 Additional Resources
+
+- [Docker Documentation](https://docs.docker.com/)
+- [Let's Encrypt Documentation](https://letsencrypt.org/docs/)
+- [Nginx Documentation](https://nginx.org/en/docs/)
+- [Certbot Documentation](https://eff-certbot.readthedocs.io/)
+
+## 🆘 Support
+
+If you encounter issues:
+1. Check logs: `docker-compose -f docker-compose.prod.yml logs`
+2. Verify configuration: `docker-compose -f docker-compose.prod.yml config`
+3. Check service status: `docker-compose -f docker-compose.prod.yml ps`
+4. Review this guide's troubleshooting section
+

+ 69 - 0
docs/README.md

@@ -0,0 +1,69 @@
+# Documentation Index
+
+Welcome to the Market Data Service documentation. This index helps you find the right guide for your needs.
+
+## 📖 Documentation Guide
+
+### Getting Started
+
+- **[Main README](../README.md)** - Project overview, features, and quick start
+- **[Local Development Setup](./LOCAL_DEV_SETUP.md)** - Complete guide for local development with MT5 EA
+- **[Production Deployment](./DEPLOYMENT.md)** - Production deployment with containerized SSL certificates
+
+### Configuration & Setup
+
+- **[Configuration Guide](./CONFIGURATION.md)** - Environment variables and configuration options
+- **[Docker Guide](../DOCKER.md)** - Docker containerization details and usage
+
+### API & Integration
+
+- **[API Contract](./API_CONTRACT.md)** - Complete API endpoint specifications
+- **[MT5 Operation](./MT5_OPERATION.md)** - MT5 Expert Advisor configuration and operation
+
+### Reference
+
+- **[Archive](./ARCHIVE/)** - Historical documentation and reports
+
+## 🚀 Quick Navigation
+
+### I want to...
+
+**Set up local development:**
+→ [LOCAL_DEV_SETUP.md](./LOCAL_DEV_SETUP.md)
+
+**Deploy to production:**
+→ [DEPLOYMENT.md](./DEPLOYMENT.md)
+
+**Configure environment variables:**
+→ [CONFIGURATION.md](./CONFIGURATION.md)
+
+**Use Docker:**
+→ [DOCKER.md](../DOCKER.md)
+
+**Understand the API:**
+→ [API_CONTRACT.md](./API_CONTRACT.md)
+
+**Configure MT5 EA:**
+→ [MT5_OPERATION.md](./MT5_OPERATION.md)
+
+## 📁 Documentation Structure
+
+```
+docs/
+├── README.md              # This file - documentation index
+├── LOCAL_DEV_SETUP.md     # Local development guide
+├── DEPLOYMENT.md          # Production deployment guide
+├── CONFIGURATION.md       # Configuration guide
+├── API_CONTRACT.md        # API specifications
+├── MT5_OPERATION.md      # MT5 EA guide
+└── ARCHIVE/              # Historical documentation
+    └── PRODUCTION_READINESS_REPORT.md
+```
+
+## 🔗 External Links
+
+- [Docker Documentation](https://docs.docker.com/)
+- [Let's Encrypt Documentation](https://letsencrypt.org/docs/)
+- [Nginx Documentation](https://nginx.org/en/docs/)
+- [PostgreSQL Documentation](https://www.postgresql.org/docs/)
+

+ 4 - 3
nginx/nginx.prod.conf

@@ -70,9 +70,10 @@ http {
         server_name _;
 
         # SSL Configuration
-        # Update these paths to match your SSL certificate locations
-        ssl_certificate /etc/nginx/ssl/certs/fullchain.pem;
-        ssl_certificate_key /etc/nginx/ssl/private/privkey.pem;
+        # Using Let's Encrypt certificates from certbot container
+        # DOMAIN_NAME_PLACEHOLDER will be replaced by nginx entrypoint script
+        ssl_certificate /etc/letsencrypt/live/DOMAIN_NAME_PLACEHOLDER/fullchain.pem;
+        ssl_certificate_key /etc/letsencrypt/live/DOMAIN_NAME_PLACEHOLDER/privkey.pem;
 
         # SSL Security Settings
         ssl_protocols TLSv1.2 TLSv1.3;

+ 165 - 0
nginx/nginx.prod.conf.template

@@ -0,0 +1,165 @@
+# Nginx configuration for production environment
+# HTTP to HTTPS redirect, SSL/TLS, WebSocket support
+# This is a template - DOMAIN_NAME will be replaced at runtime
+
+user nginx;
+worker_processes auto;
+error_log /var/log/nginx/error.log warn;
+pid /var/run/nginx.pid;
+
+events {
+    worker_connections 2048;
+    use epoll;
+}
+
+http {
+    include /etc/nginx/mime.types;
+    default_type application/octet-stream;
+
+    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+                    '$status $body_size_sent "$http_referer" '
+                    '"$http_user_agent" "$http_x_forwarded_for"';
+
+    access_log /var/log/nginx/access.log main;
+
+    sendfile on;
+    tcp_nopush on;
+    tcp_nodelay on;
+    keepalive_timeout 65;
+    types_hash_max_size 2048;
+    client_max_body_size 50M;
+
+    # Hide nginx version
+    server_tokens off;
+
+    # Gzip compression
+    gzip on;
+    gzip_vary on;
+    gzip_proxied any;
+    gzip_comp_level 6;
+    gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss;
+
+    # Rate limiting (optional, adjust as needed)
+    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/m;
+    limit_req_zone $binary_remote_addr zone=ws_limit:10m rate=10r/s;
+
+    # Upstream API server
+    upstream api {
+        server api:3000;
+        keepalive 32;
+    }
+
+    # HTTP server - redirect to HTTPS
+    server {
+        listen 80;
+        server_name _;
+
+        # Allow Let's Encrypt challenges
+        location /.well-known/acme-challenge/ {
+            root /var/www/certbot;
+        }
+
+        # Redirect all other traffic to HTTPS
+        location / {
+            return 301 https://$host$request_uri;
+        }
+    }
+
+    # HTTPS server
+    server {
+        listen 443 ssl http2;
+        server_name _;
+
+        # SSL Configuration
+        # Using Let's Encrypt certificates from certbot container
+        ssl_certificate /etc/letsencrypt/live/DOMAIN_NAME_PLACEHOLDER/fullchain.pem;
+        ssl_certificate_key /etc/letsencrypt/live/DOMAIN_NAME_PLACEHOLDER/privkey.pem;
+
+        # SSL Security Settings
+        ssl_protocols TLSv1.2 TLSv1.3;
+        ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
+        ssl_prefer_server_ciphers off;
+        ssl_session_cache shared:SSL:10m;
+        ssl_session_timeout 10m;
+        ssl_session_tickets off;
+
+        # Security Headers
+        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
+        add_header X-Frame-Options "DENY" always;
+        add_header X-Content-Type-Options "nosniff" always;
+        add_header X-XSS-Protection "1; mode=block" always;
+        add_header Referrer-Policy "strict-origin-when-cross-origin" always;
+
+        # Health check endpoint (no rate limiting)
+        location /health {
+            proxy_pass http://api/health;
+            proxy_http_version 1.1;
+            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;
+            
+            access_log off;
+        }
+
+        # WebSocket support for Socket.io (with rate limiting)
+        location /socket.io/ {
+            limit_req zone=ws_limit burst=20 nodelay;
+            
+            proxy_pass http://api;
+            proxy_http_version 1.1;
+            
+            # WebSocket upgrade headers
+            proxy_set_header Upgrade $http_upgrade;
+            proxy_set_header Connection "upgrade";
+            
+            # Standard proxy headers
+            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 timeouts (Socket.io uses long-lived connections)
+            proxy_read_timeout 86400s;
+            proxy_send_timeout 86400s;
+            proxy_connect_timeout 60s;
+            
+            # Disable buffering for real-time data
+            proxy_buffering off;
+            proxy_cache off;
+        }
+
+        # API endpoints (with rate limiting)
+        location /api/ {
+            limit_req zone=api_limit burst=50 nodelay;
+            
+            proxy_pass http://api;
+            proxy_http_version 1.1;
+            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;
+            
+            # Timeout settings
+            proxy_connect_timeout 60s;
+            proxy_send_timeout 60s;
+            proxy_read_timeout 60s;
+            
+            # Buffer settings
+            proxy_buffering on;
+            proxy_buffer_size 4k;
+            proxy_buffers 8 4k;
+        }
+
+        # Root endpoint
+        location / {
+            proxy_pass http://api;
+            proxy_http_version 1.1;
+            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;
+        }
+    }
+}
+