Bläddra i källkod

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 11 månader sedan
förälder
incheckning
c69e943a3b
14 ändrade filer med 1231 tillägg och 231 borttagningar
  1. 20 14
      .env.example
  2. 1 0
      .gitignore
  3. 12 17
      DOCKER.md
  4. 65 192
      README.md
  5. 52 5
      docker-compose.prod.yml
  6. 90 0
      docker/certbot-init.sh
  7. 50 0
      docker/init-ssl.sh
  8. 49 0
      docker/nginx-entrypoint.sh
  9. 25 0
      docker/renew-ssl.sh
  10. 260 0
      docs/CONFIGURATION.md
  11. 369 0
      docs/DEPLOYMENT.md
  12. 69 0
      docs/README.md
  13. 4 3
      nginx/nginx.prod.conf
  14. 165 0
      nginx/nginx.prod.conf.template

+ 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;
+        }
+    }
+}
+