19 KiB
Enhanced Brief Processing System - Production Deployment Guide
Overview
This guide provides complete instructions for deploying the Enhanced Brief Processing System on an Ubuntu web server. The system consists of a React frontend and Python backend with real-time WebSocket communication.
Architecture: React Frontend → Apache Proxy → Python Backend (Quart/WebSocket) → AI Services
Prerequisites
System Requirements
- OS: Ubuntu 20.04 LTS or newer
- CPU: 4+ cores (8+ recommended for production)
- RAM: 8GB minimum (16GB+ recommended)
- Storage: 100GB+ SSD with high IOPS
- Network: Stable internet connection for AI API calls
Required Software
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install essential packages
sudo apt install -y python3.11 python3.11-venv python3.11-dev python3-pip
sudo apt install -y nodejs npm apache2 git curl wget unzip
sudo apt install -y build-essential libffi-dev libssl-dev
# Enable Apache modules
sudo a2enmod proxy proxy_http proxy_wstunnel rewrite ssl headers
Required API Keys
Before deployment, ensure you have:
- OpenAI API Key (for GPT-5 access)
- Anthropic API Key (for Claude models)
- Google AI API Key (for Gemini 2.5 Pro)
- LlamaCloud API Key (for document parsing)
- Microsoft Azure AD App Registration (for production authentication)
Step 1: Prepare Deployment Files
1.1 Create Deployment Directory
# Create deployment directory
sudo mkdir -p /var/www/html/brief-extractor
sudo chown -R $USER:www-data /var/www/html/brief-extractor
sudo chmod -R 755 /var/www/html/brief-extractor
1.2 Build Frontend
On your development machine:
# Navigate to frontend directory
cd frontend
# Set production environment
echo "VITE_API_BASE_URL=/api" > .env.production
# Build for production
npm ci
npm run build
# The built files will be in frontend/dist/
1.3 Copy Files to Server
Frontend Files (copy contents of frontend/dist/ to server):
# On your local machine, create deployment package
cd frontend/dist
tar -czf frontend-dist.tar.gz *
# Copy to server
scp frontend-dist.tar.gz user@your-server:/tmp/
# On server, extract frontend files
cd /var/www/html/brief-extractor
sudo tar -xzf /tmp/frontend-dist.tar.gz
sudo chown -R www-data:www-data /var/www/html/brief-extractor
Backend Files (copy these directories/files to server):
# Create backend directory
sudo mkdir -p /var/www/html/brief-extractor/backend
cd /var/www/html/brief-extractor/backend
# Copy these files/directories from your project:
# - core/ (entire directory)
# - server/ (entire directory)
# - prompts/ (entire directory)
# - run_server.py
# - requirements_enhanced.txt
# - server_requirements.txt
# - .env.example (rename to .env and configure)
# Example rsync command (adjust paths as needed):
rsync -av --exclude='venv' --exclude='node_modules' --exclude='frontend' --exclude='output' --exclude='__pycache__' /path/to/your/project/ user@your-server:/var/www/html/brief-extractor/backend/
Step 2: Backend Setup
2.1 Create Python Virtual Environment
cd /var/www/html/brief-extractor/backend
# Create virtual environment
python3.11 -m venv venv
# Activate virtual environment
source venv/bin/activate
# Upgrade pip
pip install --upgrade pip setuptools wheel
2.2 Install Python Dependencies
# Install core dependencies
pip install -r requirements_enhanced.txt
# Install web server dependencies
pip install -r server_requirements.txt
# Verify installation
python -c "import quart, anthropic, openai; print('Dependencies installed successfully')"
2.3 Configure Environment Variables
# Copy and edit environment file
cp .env.example .env
sudo nano .env
Production .env Configuration:
# Production Mode Settings
DEV_MODE=false
DEBUG=false
ENVIRONMENT=production
# Server Configuration
SERVER_HOST=127.0.0.1
SERVER_PORT=8000
SERVER_WORKERS=4
# Security Settings
SESSION_SECRET=your-cryptographically-strong-secret-here-min-32-chars
SECURE_COOKIES=true
CORS_ALLOWED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
# API Keys (REQUIRED)
OPENAI_API_KEY=sk-your-openai-api-key-here
ANTHROPIC_API_KEY=sk-ant-your-anthropic-api-key-here
GOOGLE_API_KEY=AIzaSy-your-google-api-key-here
LLAMACLOUD_API_KEY=llx-your-llamacloud-api-key-here
# Model Configuration
OPENAI_REASONING_EFFORT=medium
ANTHROPIC_MAX_TOKENS=64000
GOOGLE_MAX_OUTPUT_TOKENS=100000
# Processing Settings
DEFAULT_PRIMARY_MODELS=openai-gpt5,anthropic-sonnet4,google-gemini25
DEFAULT_CONSOLIDATION_MODEL=openai-gpt5
MAX_PROCESSING_COST_USD=10.00
MAX_CONCURRENT_JOBS=3
MAX_UPLOAD_SIZE_MB=200
FILE_RETENTION_HOURS=24
# Microsoft Azure AD (Production Authentication)
MSAL_CLIENT_ID=your-azure-app-client-id
MSAL_CLIENT_SECRET=your-azure-app-client-secret
MSAL_TENANT_ID=your-azure-tenant-id
MSAL_AUTHORITY=https://login.microsoftonline.com/your-tenant-id
MSAL_REDIRECT_URI=https://yourdomain.com/auth/callback
# Logging
LOG_LEVEL=INFO
LOG_FILE=/var/log/brief-extractor/app.log
2.4 Create Required Directories
# Create data directories
sudo mkdir -p /var/www/html/brief-extractor/backend/server/data/{uploads,outputs}
sudo mkdir -p /var/log/brief-extractor
# Set permissions
sudo chown -R $USER:www-data /var/www/html/brief-extractor/backend/server/data
sudo chmod -R 775 /var/www/html/brief-extractor/backend/server/data
sudo chown -R $USER:adm /var/log/brief-extractor
sudo chmod -R 755 /var/log/brief-extractor
2.5 Test Backend Installation
# Test the backend can start
cd /var/www/html/brief-extractor/backend
source venv/bin/activate
python -c "from server.app import create_app; print('Backend setup successful')"
Step 3: Create Systemd Service
3.1 Create Service File
sudo nano /etc/systemd/system/brief-extractor.service
Service Configuration:
[Unit]
Description=Enhanced Brief Processing System Backend
After=network.target
Wants=network-online.target
[Service]
Type=exec
User=www-data
Group=www-data
WorkingDirectory=/var/www/html/brief-extractor/backend
Environment=PATH=/var/www/html/brief-extractor/backend/venv/bin
EnvironmentFile=/var/www/html/brief-extractor/backend/.env
ExecStart=/var/www/html/brief-extractor/backend/venv/bin/python run_server.py
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
Restart=on-failure
RestartSec=10
# Security settings
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/www/html/brief-extractor/backend/server/data /var/log/brief-extractor /tmp
# Resource limits
LimitNOFILE=65536
LimitNPROC=4096
[Install]
WantedBy=multi-user.target
3.2 Configure Service Permissions
# Set proper ownership
sudo chown -R www-data:www-data /var/www/html/brief-extractor/backend
sudo chmod +x /var/www/html/brief-extractor/backend/run_server.py
# Reload systemd
sudo systemctl daemon-reload
# Enable service to start on boot
sudo systemctl enable brief-extractor.service
Step 4: Configure Apache Reverse Proxy
4.1 Configure Apache
sudo nano /etc/apache2/apache2.conf
Add this configuration to /etc/apache2/apache2.conf:
# Brief Extractor Virtual Host Configuration
<VirtualHost *:80>
ServerName yourdomain.com
ServerAlias www.yourdomain.com
DocumentRoot /var/www/html/brief-extractor
# Redirect HTTP to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>
<VirtualHost *:443>
ServerName yourdomain.com
ServerAlias www.yourdomain.com
DocumentRoot /var/www/html/brief-extractor
# SSL Configuration (configure with your certificates)
SSLEngine on
SSLCertificateFile /path/to/your/certificate.crt
SSLCertificateKeyFile /path/to/your/private.key
SSLCertificateChainFile /path/to/your/chain.crt
# Security Headers
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' wss://yourdomain.com https://api.openai.com https://api.anthropic.com https://generativelanguage.googleapis.com"
# Static files (React frontend)
<Directory /var/www/html/brief-extractor>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
# Handle React Router (SPA)
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/api
RewriteCond %{REQUEST_URI} !^/ws
RewriteRule . /index.html [L]
</Directory>
# Proxy API requests to backend
ProxyPreserveHost On
ProxyRequests Off
# API endpoints
ProxyPass /api/ http://127.0.0.1:8000/api/
ProxyPassReverse /api/ http://127.0.0.1:8000/api/
# Health check endpoint
ProxyPass /health http://127.0.0.1:8000/health
ProxyPassReverse /health http://127.0.0.1:8000/health
# WebSocket proxy
ProxyPass /ws/ ws://127.0.0.1:8000/ws/
ProxyPassReverse /ws/ ws://127.0.0.1:8000/ws/
# Logging
ErrorLog ${APACHE_LOG_DIR}/brief-extractor_error.log
CustomLog ${APACHE_LOG_DIR}/brief-extractor_access.log combined
# Optional: Rate limiting (requires mod_evasive)
# DOSHashTableSize 32768
# DOSPageCount 10
# DOSPageInterval 2
# DOSSiteCount 50
# DOSSiteInterval 2
# DOSBlockingPeriod 600
</VirtualHost>
4.2 Test and Restart Apache
# Test Apache configuration
sudo apache2ctl configtest
# Restart Apache
sudo systemctl restart apache2
Step 5: SSL/TLS Certificate Setup
5.1 Using Let's Encrypt (Recommended)
# Install Certbot
sudo apt install -y certbot python3-certbot-apache
# Obtain SSL certificate
sudo certbot --apache -d yourdomain.com -d www.yourdomain.com
# Test automatic renewal
sudo certbot renew --dry-run
5.2 Configure Auto-renewal
# Add cron job for certificate renewal
sudo crontab -e
# Add this line:
0 12 * * * /usr/bin/certbot renew --quiet
Step 6: Frontend Configuration for Production
6.1 Update Frontend Build Configuration
If you need to rebuild the frontend for production, update the environment:
# In frontend/.env.production
VITE_API_BASE_URL=https://yourdomain.com/api
VITE_WS_URL=wss://yourdomain.com/ws
VITE_MSAL_CLIENT_ID=your-azure-app-client-id
VITE_MSAL_TENANT_ID=your-azure-tenant-id
VITE_MSAL_AUTHORITY=https://login.microsoftonline.com/your-tenant-id
VITE_MSAL_REDIRECT_URI=https://yourdomain.com/auth/callback
6.2 Rebuild and Deploy Frontend (if needed)
# Rebuild frontend
cd frontend
npm run build
# Copy updated files to server
rsync -av dist/ user@your-server:/var/www/html/brief-extractor/
Step 7: Start and Monitor Services
7.1 Start the Backend Service
# Start the service
sudo systemctl start brief-extractor.service
# Check service status
sudo systemctl status brief-extractor.service
# Monitor logs in real-time
sudo journalctl -u brief-extractor.service -f
# Check if service is listening on port 8000
sudo ss -tulpn | grep :8000
7.2 Verify System Health
# Test backend health endpoint
curl -k https://yourdomain.com/health
# Test API endpoint
curl -k https://yourdomain.com/api/config/system
# Check Apache status
sudo systemctl status apache2
# View Apache logs
sudo tail -f /var/log/apache2/brief-extractor_access.log
sudo tail -f /var/log/apache2/brief-extractor_error.log
Step 8: Testing and Validation
8.1 Backend Testing
# Test Python backend directly
cd /var/www/html/brief-extractor/backend
source venv/bin/activate
python -c "
import asyncio
from server.app import create_app
print('Backend imports successful')
"
# Test environment variables
python -c "
import os
from dotenv import load_dotenv
load_dotenv()
print('Environment loaded:', bool(os.getenv('OPENAI_API_KEY')))
"
8.2 Frontend Access Testing
- Open browser and navigate to
https://yourdomain.com - Check console for any JavaScript errors
- Test authentication (login/logout flow)
- Upload a test document to verify full workflow
- Monitor WebSocket connection in browser developer tools
8.3 End-to-End Testing
- Authentication: Verify MSAL login works
- File Upload: Test document upload functionality
- Processing: Upload a test brief and verify processing
- Real-time Updates: Check WebSocket updates during processing
- Download Results: Verify CSV download works
- Cleanup: Test job deletion
Step 9: Production Monitoring and Maintenance
9.1 Log Monitoring
# Backend application logs
sudo journalctl -u brief-extractor.service -f
# Apache access logs
sudo tail -f /var/log/apache2/brief-extractor_access.log
# Apache error logs
sudo tail -f /var/log/apache2/brief-extractor_error.log
# System logs
sudo tail -f /var/log/syslog
9.2 Resource Monitoring
# Monitor system resources
htop
# Check disk usage
df -h
# Monitor network connections
sudo ss -tulpn | grep -E "(8000|80|443)"
# Check memory usage
free -h
9.3 Automated Cleanup
Create a cleanup script for old files:
sudo nano /usr/local/bin/brief-extractor-cleanup.sh
#!/bin/bash
# Cleanup old uploaded files and results
UPLOAD_DIR="/var/www/html/brief-extractor/backend/server/data/uploads"
OUTPUT_DIR="/var/www/html/brief-extractor/backend/server/data/outputs"
# Remove files older than 24 hours
find "$UPLOAD_DIR" -type f -mtime +1 -delete
find "$OUTPUT_DIR" -type f -mtime +1 -delete
# Log cleanup
echo "$(date): Cleaned up old files" >> /var/log/brief-extractor/cleanup.log
sudo chmod +x /usr/local/bin/brief-extractor-cleanup.sh
# Add to cron
sudo crontab -e
# Add: 0 2 * * * /usr/local/bin/brief-extractor-cleanup.sh
Step 10: Backup and Disaster Recovery
10.1 Backup Strategy
# Create backup script
sudo nano /usr/local/bin/brief-extractor-backup.sh
#!/bin/bash
BACKUP_DIR="/var/backups/brief-extractor"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
# Backup application files
tar -czf "$BACKUP_DIR/app_$DATE.tar.gz" -C /var/www/html brief-extractor
# Backup configuration
cp /etc/systemd/system/brief-extractor.service "$BACKUP_DIR/service_$DATE"
cp /etc/apache2/apache2.conf "$BACKUP_DIR/apache_$DATE.conf"
# Keep only last 7 days of backups
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete
echo "$(date): Backup completed" >> /var/log/brief-extractor/backup.log
10.2 Health Checks
# Create health check script
sudo nano /usr/local/bin/brief-extractor-healthcheck.sh
#!/bin/bash
# Health check script
SERVICE_NAME="brief-extractor"
HEALTH_URL="https://yourdomain.com/health"
LOG_FILE="/var/log/brief-extractor/healthcheck.log"
# Check service status
if ! systemctl is-active --quiet $SERVICE_NAME; then
echo "$(date): Service $SERVICE_NAME is not running" >> $LOG_FILE
systemctl restart $SERVICE_NAME
fi
# Check HTTP health endpoint
if ! curl -sf $HEALTH_URL > /dev/null; then
echo "$(date): Health check failed for $HEALTH_URL" >> $LOG_FILE
fi
Troubleshooting Guide
Common Issues and Solutions
-
Service Won't Start:
# Check service logs sudo journalctl -u brief-extractor.service -n 50 # Check file permissions sudo chown -R www-data:www-data /var/www/html/brief-extractor/backend # Verify Python virtual environment cd /var/www/html/brief-extractor/backend source venv/bin/activate python run_server.py -
Frontend Not Loading:
# Check Apache configuration sudo apache2ctl configtest # Verify file permissions sudo chown -R www-data:www-data /var/www/html/brief-extractor # Check SSL certificate sudo certbot certificates -
WebSocket Connection Issues:
# Check proxy configuration # Ensure mod_proxy_wstunnel is enabled sudo a2enmod proxy_wstunnel sudo systemctl restart apache2 -
Authentication Failures:
# Verify MSAL configuration # Check Azure AD app registration settings # Verify redirect URIs match -
File Upload Issues:
# Check upload directory permissions sudo chmod -R 775 /var/www/html/brief-extractor/backend/server/data/uploads # Check disk space df -h
Performance Optimization
-
Enable Gzip Compression:
# Add to Apache config LoadModule deflate_module modules/mod_deflate.so <Location /> SetOutputFilter DEFLATE </Location> -
Cache Static Assets:
# Add cache headers for static files <LocationMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg)$"> ExpiresActive On ExpiresDefault "access plus 1 month" </LocationMatch> -
Monitor Resource Usage:
- Install monitoring tools like htop, iotop
- Set up log rotation to prevent disk space issues
- Consider upgrading server resources based on usage patterns
Security Considerations
10.1 System Hardening
# Configure firewall
sudo ufw enable
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
# Disable unused services
sudo systemctl disable apache2-doc
# Regular security updates
sudo apt update && sudo apt upgrade -y
10.2 Application Security
- API Keys: Ensure all API keys are kept secure and rotated regularly
- File Validation: The system includes file type validation
- Authentication: MSAL provides secure authentication for production
- HTTPS: Always use HTTPS in production
- CORS: Configure CORS policies for your domain only
Conclusion
After completing these steps, your Enhanced Brief Processing System should be fully deployed and operational on your Ubuntu server. The system will:
- ✅ Serve the React frontend via Apache
- ✅ Proxy API calls to the Python backend
- ✅ Handle WebSocket connections for real-time updates
- ✅ Process documents using multiple AI models
- ✅ Provide secure authentication via Microsoft Azure AD
- ✅ Automatically start on system boot
- ✅ Include monitoring and logging capabilities
Next Steps:
- Configure monitoring and alerting
- Set up automated backups
- Test disaster recovery procedures
- Monitor costs and usage of AI services
- Consider scaling strategies for high-volume usage
For ongoing maintenance, monitor the logs regularly and keep the system updated with security patches.