Deployment Guide

🚀 Deployment Architecture

The Material Kai Vision Platform uses a multi-service deployment strategy:

  1. Frontend: Vercel (Static hosting + Edge functions)
  2. MIVAA Service: Docker containers (Self-hosted or cloud)
  3. Database: Supabase (Managed PostgreSQL)
  4. External APIs: Third-party services (OpenAI, HuggingFace, Replicate)

🏗️ Infrastructure Overview

graph TB
    subgraph "Production Environment"
        A[Vercel Frontend<br/>Static + Edge]
        B[MIVAA Service<br/>Docker Container]
        C[Supabase<br/>Database + Auth]
        D[External APIs<br/>OpenAI, HuggingFace]
    end
    
    subgraph "Development Environment"
        E[Local Frontend<br/>localhost:5173]
        F[Local MIVAA<br/>localhost:8000]
        G[Supabase Cloud<br/>Shared Instance]
    end
    
    A --> B
    A --> C
    B --> C
    B --> D
    E --> F
    E --> G
    F --> G

🔧 Environment Configuration

Production Environment Variables

Frontend (Set in Vercel Production Environment)

# Application
NODE_ENV=production
VITE_DEBUG=false

# Supabase
SUPABASE_URL=https://bgbavxtjlbvgplozizxu.supabase.co
SUPABASE_ANON_KEY=your_production_anon_key

# Services
MIVAA_GATEWAY_URL=https://v1api.materialshub.gr
MIVAA_API_KEY=your_production_mivaa_jwt_token

# External APIs
VITE_OPENAI_API_KEY=your_production_openai_key
VITE_HUGGINGFACE_API_KEY=your_production_hf_key
VITE_REPLICATE_API_TOKEN=your_production_replicate_token

# Security
VITE_ALLOWED_ORIGINS=https://your-domain.com

MIVAA Service (Set in Deployment Platform)

# Application
ENVIRONMENT=production
DEBUG=false
LOG_LEVEL=ERROR
HOST=0.0.0.0
PORT=8000

# Database
SUPABASE_URL=https://bgbavxtjlbvgplozizxu.supabase.co
SUPABASE_ANON_KEY=your_production_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_production_service_key

# Security
JWT_SECRET_KEY=your_secure_production_jwt_secret
CORS_ORIGINS=https://your-domain.com
RATE_LIMIT_REQUESTS=50
RATE_LIMIT_WINDOW=60

# Performance
MAX_WORKERS=4
CACHE_TTL=3600
DATABASE_POOL_SIZE=20

# Monitoring
SENTRY_DSN=your_sentry_dsn
LOG_FILE=/var/log/mivaa/app.log

📦 Frontend Deployment (Vercel)

Vercel Configuration

File: vercel.json

{
  "buildCommand": "npm run build",
  "outputDirectory": "dist",
  "framework": "vite",
  "headers": [
    {
      "source": "/assets/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=31536000, immutable"
        }
      ]
    },
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        },
        {
          "key": "X-Frame-Options",
          "value": "DENY"
        },
        {
          "key": "X-XSS-Protection",
          "value": "1; mode=block"
        }
      ]
    }
  ]
}

Deployment Steps

  1. Connect Repository:

    # Install Vercel CLI
    npm install -g vercel
    
    # Login and link project
    vercel login
    vercel link
    
  2. Configure Environment Variables:

    # Set production environment variables
    vercel env add SUPABASE_URL production
    vercel env add SUPABASE_ANON_KEY production
    vercel env add VITE_MIVAA_SERVICE_URL production
    # ... add all required variables
    
  3. Deploy:

    # Deploy to production
    vercel --prod
    
    # Or use automatic deployment via Git
    git push origin main  # Triggers automatic deployment
    

Build Optimization

Vite Configuration (vite.config.ts):

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          ui: ['@radix-ui/react-dialog', '@radix-ui/react-dropdown-menu'],
          supabase: ['@supabase/supabase-js'],
          utils: ['clsx', 'tailwind-merge', 'lucide-react'],
        },
      },
    },
    sourcemap: true,
    chunkSizeWarningLimit: 1000,
  },
});

🐳 MIVAA Service Deployment (Docker)

🚀 Deployment Options

🔄 Default Deployment (Recommended)

🚀 Orchestrated Deployment (Advanced)

🏥 Health Check & Monitoring Features

Real-Time Health Monitoring

Automatic Diagnostics

When health checks fail, the system automatically:

Auto-Recovery Features

🌐 Service Endpoints

All MIVAA service endpoints are available at:

Docker Configuration

Dockerfile:

FROM python:3.9-slim

WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \
    gcc \
    g++ \
    && rm -rf /var/lib/apt/lists/*

# Copy requirements and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY . .

# Create non-root user
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser

# Expose port
EXPOSE 8000

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

# Start application
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

Docker Compose (docker-compose.yml):

version: '3.8'

services:
  mivaa-service:
    build: .
    ports:
      - "8000:8000"
    environment:
      - ENVIRONMENT=production
      - DEBUG=false
      - SUPABASE_URL=${SUPABASE_URL}
      - SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
      - JWT_SECRET_KEY=${JWT_SECRET_KEY}
    volumes:
      - ./logs:/var/log/mivaa
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl
    depends_on:
      - mivaa-service
    restart: unless-stopped

Deployment Options

Option 1: Cloud Provider (AWS/GCP/Azure)

AWS ECS Deployment:

# Build and push to ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin your-account.dkr.ecr.us-east-1.amazonaws.com

docker build -t mivaa-service .
docker tag mivaa-service:latest your-account.dkr.ecr.us-east-1.amazonaws.com/mivaa-service:latest
docker push your-account.dkr.ecr.us-east-1.amazonaws.com/mivaa-service:latest

# Deploy to ECS
aws ecs update-service --cluster mivaa-cluster --service mivaa-service --force-new-deployment

Option 2: VPS/Dedicated Server

Setup Script (deploy/setup-server.sh):

#!/bin/bash

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

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
sudo usermod -aG docker $USER

# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Clone repository
git clone https://github.com/your-org/material-kai-vision-platform.git
cd material-kai-vision-platform/mivaa-pdf-extractor

# Set up environment variables for Docker deployment
# These MUST be available in the shell environment where docker-compose runs
export SUPABASE_URL="https://your-project.supabase.co"
export SUPABASE_ANON_KEY="your-anon-key"
export OPENAI_API_KEY="your-openai-key"
export MATERIAL_KAI_API_URL="https://your-platform-url.com"
export MATERIAL_KAI_API_KEY="your-api-key"
export SENTRY_DSN="your-sentry-dsn"

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

# Set up SSL with Let's Encrypt
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com

🤖 GitHub Actions Deployment Workflows

🚀 Default Deployment Workflow

File: .github/workflows/deploy.yml

Features:

Usage:

# Automatic deployment
git push origin main

# Manual deployment
# Go to GitHub Actions → "MIVAA Deployment (Default)" → Run workflow

🚀 Orchestrated Deployment Workflow

File: .github/workflows/orchestrated-deployment.yml

Features:

Usage:

# Manual orchestrated deployment
# Go to GitHub Actions → "Orchestrated MIVAA Deployment Pipeline (On-Demand)"
# Configure options:
# - Deployment Mode: intelligent
# - Target Branch: main
# - Deployment Reason: "Feature release with enhanced monitoring"
# Run workflow

🏥 Health Check Features

Both workflows include comprehensive health monitoring:

Endpoint Testing

# Tested endpoints:
curl https://v1api.materialshub.gr/health
curl https://v1api.materialshub.gr/docs
curl https://v1api.materialshub.gr/redoc
curl https://v1api.materialshub.gr/openapi.json

Status Code Verification

Automatic Diagnostics on Failure

# System diagnostics collected:
- Server uptime and load averages
- Memory and disk usage
- Service status (systemctl status mivaa-pdf-extractor)
- Recent service logs (last 50 lines)
- Network status (port 8000 availability)
- Process binding verification
- Service restart attempt
- Post-restart verification

GitHub Action Summary

All deployment results are displayed on the main GitHub Action page with:

📋 Deployment Overview Features

Pre-Deployment Information

Post-Deployment Summary

Deployment Process Steps

  1. 🔄 Code Checkout: Latest code from target branch
  2. 🐍 Environment Setup: Python 3.9, pyenv, uv package manager
  3. 📦 Dependency Installation: Requirements and system packages
  4. 🔧 Service Configuration: systemd service setup and configuration
  5. 🚀 Service Deployment: Service restart and process management
  6. 🏥 Health Verification: Real-time endpoint testing with diagnostics
  7. 📊 Summary Generation: Comprehensive results on GitHub Action page
  8. ✅ Completion: Final status and next steps

System Architecture Overview

🔧 Workflow Configuration

Required Secrets

Set these in GitHub repository secrets:

# Server Access
SSH_PRIVATE_KEY=your_ssh_private_key
DEPLOY_HOST=104.248.68.3

# Application Environment
SUPABASE_URL=https://bgbavxtjlbvgplozizxu.supabase.co
SUPABASE_ANON_KEY=your_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
JWT_SECRET_KEY=your_jwt_secret
OPENAI_API_KEY=your_openai_key
HUGGINGFACE_API_KEY=your_huggingface_key
MATERIAL_KAI_API_URL=https://v1api.materialshub.gr
MATERIAL_KAI_API_KEY=your_api_key
SENTRY_DSN=your_sentry_dsn

Deployment Process

  1. Code Checkout: Latest code from target branch
  2. Environment Setup: Python 3.9, pyenv, uv package manager
  3. Dependency Installation: Requirements and system packages
  4. Service Deployment: systemd service configuration and restart
  5. Health Verification: Real-time endpoint testing with diagnostics
  6. Summary Generation: Comprehensive results on GitHub Action page

🗄️ Database Deployment (Supabase)

Supabase Setup

  1. Create Project:

    • Go to supabase.com
    • Create new project
    • Note project URL and keys
  2. Configure Database:

    -- Enable required extensions
    CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
    CREATE EXTENSION IF NOT EXISTS "vector";
    CREATE EXTENSION IF NOT EXISTS "ltree";
    
  3. Set Up Authentication:

    # Configure JWT settings in Supabase dashboard
    # Set up email templates
    # Configure OAuth providers (if needed)
    
  4. Deploy Schema:

    # Initialize migrations (when available)
    supabase migration new initial_schema
    supabase db push
    

Database Security

Row Level Security (RLS):

-- Enable RLS on all tables
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
ALTER TABLE api_keys ENABLE ROW LEVEL SECURITY;

-- Create policies
CREATE POLICY "Users can only access their workspace data" ON documents
  FOR ALL USING (workspace_id IN (
    SELECT workspace_id FROM user_workspaces 
    WHERE user_id = auth.uid()
  ));

🔐 Security Configuration

SSL/TLS Setup

Nginx Configuration (nginx.conf):

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

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

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

    location / {
        proxy_pass http://mivaa-service:8000;
        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;
    }
}

Firewall Configuration

# UFW firewall setup
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

📊 Monitoring & Logging

Application Monitoring

Health Check Endpoints:

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

# MIVAA service health
curl https://your-mivaa-service.com/health

# Database health
curl https://your-mivaa-service.com/api/v1/health

Logging Configuration

Structured Logging:

# mivaa-pdf-extractor/app/utils/logging.py
import structlog

logger = structlog.get_logger()

# Log with context
logger.info("Document processed", 
           document_id=doc_id, 
           processing_time=time_taken,
           user_id=user_id)

Error Tracking

Sentry Integration:

// Frontend error tracking
import * as Sentry from "@sentry/react";

Sentry.init({
  dsn: process.env.VITE_SENTRY_DSN,
  environment: process.env.NODE_ENV,
});

🔄 CI/CD Pipeline

GitHub Actions Workflow

# .github/workflows/deploy.yml
name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
      - run: npm ci
      - run: npm test
      - run: npm run build

  deploy-frontend:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: amondnet/vercel-action@v20
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.ORG_ID }}
          vercel-project-id: ${{ secrets.PROJECT_ID }}
          vercel-args: '--prod'

  deploy-backend:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Deploy to server
        env:
          # ⚠️ IMPORTANT: Use GH_TOKEN, not GITHUB_TOKEN as env var name
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        uses: appleboy/ssh-action@v0.1.5
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          key: ${{ secrets.KEY }}
          script: |
            cd /app/material-kai-vision-platform
            git pull origin main
            # Authenticate with GitHub Container Registry
            echo "$GH_TOKEN" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
            docker-compose -f docker-compose.prod.yml up -d --build

⚠️ GitHub Actions Security Notes

  1. Token Naming: GitHub doesn't allow environment variables starting with GITHUB_ prefix

    • Correct: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    • Wrong: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  2. Container Registry Authentication: Always authenticate before pulling private images

    echo "$GH_TOKEN" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
    

🚨 Deployment Issues & Solutions

Common Issues

  1. Missing Docker Environment Variables:

    • Problem: Docker shows warnings like "variable is not set. Defaulting to a blank string"
    • Solution: Ensure all required environment variables are exported on the deployment server:
      export SUPABASE_URL="https://your-project.supabase.co"
      export SUPABASE_ANON_KEY="your-anon-key"
      export OPENAI_API_KEY="your-openai-key"
      export MATERIAL_KAI_API_URL="https://your-platform-url.com"
      export MATERIAL_KAI_API_KEY="your-api-key"
      export SENTRY_DSN="your-sentry-dsn"
      
  2. Environment Variable Mismatch:

    • Problem: Different env vars between environments
    • Solution: Configure environment-specific variables in Vercel (Production/Preview/Development)
  3. CORS Errors:

    • Problem: Frontend can't connect to backend
    • Solution: Configure CORS_ORIGINS properly
  4. Database Connection Issues:

    • Problem: Can't connect to Supabase
    • Solution: Verify connection strings and firewall rules
  5. SSL Certificate Issues:

    • Problem: HTTPS not working
    • Solution: Use Let's Encrypt or proper SSL certificates

Rollback Strategy

# Quick rollback for MIVAA service
docker-compose -f docker-compose.prod.yml down
docker-compose -f docker-compose.prod.yml up -d --scale mivaa-service=0
docker tag mivaa-service:previous mivaa-service:latest
docker-compose -f docker-compose.prod.yml up -d

📋 Deployment Checklist

Pre-Deployment

Deployment

Post-Deployment

💾 Backup & Disaster Recovery

Automated Backup Strategy

Database Backups (Supabase):

# Supabase provides automatic daily backups
# Access backups in Supabase Dashboard → Settings → Backups

# Point-in-time recovery (PITR) available for 7 days
# Restore via Supabase Dashboard or API

Application Data Backups:

# Automated backup script (runs daily via cron)
# Location: /usr/local/bin/backup-mivaa.sh

# Manual backup
backup-mivaa.sh

# Backup location: /backups/mivaa_backup_YYYYMMDD_HHMMSS.tar.gz
# Retention: Last 7 backups kept automatically

Disaster Recovery Procedures

Database Recovery:

  1. Go to Supabase Dashboard → Settings → Backups
  2. Select desired backup point
  3. Click "Restore" and confirm
  4. Verify data integrity after restore

Application Recovery:

# Restore from backup
cd /backups
tar -xzf mivaa_backup_YYYYMMDD_HHMMSS.tar.gz -C /app

# Restart service
systemctl restart mivaa-pdf-extractor

🗄️ Database Migrations & Schema Management

Migration Strategy

Using Supabase Migrations:

# Create new migration
supabase migration new add_new_table

# Apply migrations
supabase db push

# Rollback migration
supabase db reset

Zero-Downtime Deployments:

  1. Add new columns as nullable
  2. Deploy code that handles both old and new columns
  3. Backfill data in background job
  4. Remove old columns in subsequent deployment

Extension Management

Required PostgreSQL Extensions:

-- Enable in Supabase Dashboard → SQL Editor
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "vector";
CREATE EXTENSION IF NOT EXISTS "ltree";

🔄 Job Recovery & Signal Handling

Job Persistence

The platform implements automatic job recovery for PDF processing:

Job States:

Recovery on Restart:

# Automatic on service startup
# Resumes jobs in 'processing' state
# Retries failed jobs up to max_retries

Graceful Shutdown:

# Service receives SIGTERM
# Completes current operations
# Persists job state
# Exits cleanly

# Timeout: 30 seconds before SIGKILL

📊 Performance Optimization & Scaling

Horizontal Scaling

MIVAA Service Scaling:

# docker-compose.yml
services:
  mivaa-service:
    deploy:
      replicas: 3  # Scale to 3 instances

Load Balancing:

upstream mivaa_backend {
    server mivaa-service:8000;
    server mivaa-service:8001;
    server mivaa-service:8002;
}

server {
    location / {
        proxy_pass http://mivaa_backend;
    }
}

Database Connection Pooling

Supabase Connection Pool:

# Set in MIVAA environment
DATABASE_POOL_SIZE=20
DATABASE_POOL_TIMEOUT=30

Caching Strategy

Application-Level Caching:

// Production caching configuration
caching: {
  enabled: true,
  ttl: 3600000,        // 1 hour
  maxSize: 1000,       // 1000 items
  strategy: 'lru'      // Least Recently Used
}

🚨 Monitoring & Alerting

Metrics Collection

Key Metrics to Monitor:

Sentry Configuration:

// Frontend monitoring
Sentry.init({
  dsn: process.env.VITE_SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: 1.0,
  integrations: [
    new Sentry.Replay({
      maskAllText: true,
      blockAllMedia: true,
    }),
  ],
});

Alert Thresholds

alertThresholds: {
  errorRate: 0.05,        // 5% error rate
  responseTime: 2000,     // 2 seconds
  memoryUsage: 0.7,       // 70% memory
  cpuUsage: 0.8,          // 80% CPU
}

🔐 Security Hardening

API Rate Limiting

# MIVAA Service environment
RATE_LIMIT_REQUESTS=50
RATE_LIMIT_WINDOW=60  # per minute

Security Headers

# nginx.conf
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "DENY";
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header Content-Security-Policy "default-src 'self'";

Secrets Rotation

Rotation Schedule:

Rotation Process:

  1. Generate new secret
  2. Update in secret manager
  3. Deploy with new secret
  4. Verify functionality
  5. Revoke old secret

🌐 Edge Functions Deployment

Supabase Edge Functions

Deploy Function:

# Create new function
supabase functions new my-function

# Deploy to production
supabase functions deploy my-function --project-ref bgbavxtjlbvgplozizxu

Environment Variables:

# Set in Supabase Dashboard → Edge Functions → Secrets
supabase secrets set JWT_SECRET_KEY=your_secret

🔗 Related Documentation