mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
17 KiB
17 KiB
Phase 8 Email Client - Deployment Guide
Complete guide for deploying the Email Client Phase 8 system in development, staging, and production environments.
Quick Start
Development (Local)
# 1. Clone repository
git clone <repo-url>
cd emailclient
# 2. Setup environment
make env-setup
# 3. Start services (all containers)
make dev
# 4. View logs
make logs
# 5. Test health
make health
Access Points:
- Email Service API: http://localhost:5000
- PostgreSQL: localhost:5433 (user: emailclient, password: emailclient)
- Redis: localhost:6379
- Postfix SMTP: localhost:25
- Dovecot IMAP: localhost:143
Staging
# 1. Build production images
docker-compose -f docker-compose.yml build
# 2. Configure environment
cp deployment/docker/email-service/.env.example .env.staging
# Edit .env.staging with staging credentials
# 3. Start services
docker-compose --env-file .env.staging up -d
# 4. Run health checks
curl http://localhost:5000/health
Production
See Production Deployment section below.
System Architecture
Docker Compose Stack
┌──────────────────────────────────────────────────────────┐
│ Docker Network │
│ (emailclient-net) │
│ │
│ ┌────────────┐ ┌──────────┐ ┌─────────┐ │
│ │ Email │ │PostgreSQL│ │ Redis │ │
│ │ Service │──│ Database │ │ Cache │ │
│ │ (Flask) │ │ │ │ │ │
│ └────────────┘ └──────────┘ └─────────┘ │
│ ↑ ↑ ↑ │
│ └──────────────┴──────────────┘ │
│ │ │
│ ┌────────────┐ ┌───────────┐ ┌──────────────┐ │
│ │ Postfix │ │ Dovecot │ │ Celery │ │
│ │ SMTP │ │ IMAP/ │ │ Workers & │ │
│ │ Server │ │ POP3 │ │ Beat │ │
│ └────────────┘ └───────────┘ └──────────────┘ │
│ │
└──────────────────────────────────────────────────────────┘
Service Dependencies
email-service
├── depends_on: postgres (health check)
├── depends_on: redis (health check)
├── depends_on: postfix (health check)
└── depends_on: dovecot (health check)
celery-worker
├── depends_on: redis (health check)
└── depends_on: postgres (health check)
celery-beat
├── depends_on: redis (health check)
└── depends_on: postgres (health check)
dovecot
└── depends_on: postfix
postgres
(no dependencies)
redis
(no dependencies)
Deployment Scenarios
1. Development Environment
Setup:
- Single host with all services
- Development Flask server (hot reload)
- SQLite or PostgreSQL (local)
- Redis in-memory cache
- Postfix relay localhost
Configuration:
# Use docker-compose.override.yml for development overrides
# Flask runs in development mode with debug enabled
FLASK_ENV=development
FLASK_DEBUG=1
# Email goes to Mailpit (development mail UI)
# No actual SMTP relay to production mail servers
Commands:
make dev # Start all services
make logs # View logs
make test # Run tests
make db-reset # Reset database
make shell-app # Open shell in container
2. Staging Environment
Setup:
- Separate host(s) for staging
- Production gunicorn + workers
- PostgreSQL database
- Redis cache
- Postfix + Dovecot full stack
Configuration:
# Create staging environment file
cp deployment/docker/email-service/.env.example .env.staging
# Key differences from production:
FLASK_ENV=production # Use production Flask
GUNICORN_WORKERS=4 # Normal worker count
# Use self-signed certificates for testing
# Database can be PostgreSQL backup from production
# Staging email goes to test domain
POSTFIX_DOMAIN=staging.emailclient.local
Deployment:
# Build images
docker-compose build
# Start services with staging config
docker-compose --env-file .env.staging up -d
# Verify health
curl http://localhost:5000/health
# Run smoke tests
make test
3. Production Deployment
See dedicated section below.
Configuration Management
Environment Files
Development:
.env (local development, not committed)
Staging:
.env.staging (committed but with placeholder values)
Production:
# Use Docker secrets or environment management service
# Never commit to repository
.env.production (local only, .gitignore)
Secrets Management
Local Development:
# Store in .env (not committed)
JWT_SECRET=local-dev-key-only
ENCRYPTION_KEY=local-dev-key-only
Production (Options):
Option 1: Docker Secrets (Swarm)
# Create secret
docker secret create jwt_secret -
# Reference in compose
services:
email-service:
secrets:
- jwt_secret
environment:
JWT_SECRET_FILE: /run/secrets/jwt_secret
Option 2: Environment Service
# Use HashiCorp Vault, AWS Secrets Manager, Azure Key Vault
# Fetch secret at startup
eval "$(curl -s https://vault.example.com/v1/auth/token/lookup-self)"
docker run ... -e JWT_SECRET=$(vault read -field=value secret/email-service/jwt)
Option 3: Configuration Server
# Use Spring Cloud Config, Consul, or similar
# Email service fetches config at startup
docker run ... -e CONFIG_SERVER=https://config.example.com
Production Deployment
Prerequisites
- Docker 20.10+ installed on all nodes
- Docker Compose 2.0+ for orchestration
- PostgreSQL 13+ (managed service recommended)
- Redis 6.0+ (managed service recommended)
- TLS certificates for SMTP/IMAP
- Domain name (e.g., emailclient.production.example.com)
- Load balancer (nginx, HAProxy, or cloud provider LB)
Pre-Deployment Checklist
- Database backups configured and tested
- Secrets stored securely (Vault, AWS Secrets Manager, etc.)
- TLS certificates obtained and validated
- Monitoring/alerting configured (Datadog, New Relic, Prometheus)
- Log aggregation set up (ELK Stack, Splunk, CloudWatch)
- Rate limiting configured for expected traffic
- CORS origins configured to trusted domains only
- Database connection pooling optimized
- Security scan passed (container vulnerability scanning)
- Load testing completed and performance acceptable
- Disaster recovery plan documented and tested
- Runbooks created for common issues
- On-call rotation established
Deployment Procedure
Step 1: Infrastructure Setup
# 1a. Provision infrastructure
# - VM/cloud instance with 4+ CPU, 8+ GB RAM
# - Managed PostgreSQL database
# - Managed Redis cache
# - TLS certificate from Let's Encrypt or CA
# 1b. Install Docker & Docker Compose
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Verify
docker --version
docker-compose --version
Step 2: Deploy Application
# 2a. Clone repository
git clone <repo-url> /opt/emailclient
cd /opt/emailclient
# 2b. Configure production environment
cp deployment/docker/email-service/.env.example .env.production
# Edit .env.production with REAL production values:
# - Unique JWT_SECRET (generate: python -c "import secrets; print(secrets.token_urlsafe(32))")
# - Unique ENCRYPTION_KEY
# - Production PostgreSQL URL (managed service)
# - Production Redis URL (managed service)
# - Real TLS certificate paths
# - Production domain names
# 2c. Build images (or pull from registry)
docker-compose build
# 2d. Start services
docker-compose --env-file .env.production up -d
# 2e. Verify deployment
docker-compose ps
curl http://localhost:5000/health
Step 3: Post-Deployment Validation
# 3a. Check all services are healthy
docker-compose ps --format "table {{.Names}}\t{{.Status}}"
# 3b. Test database connectivity
docker-compose exec -T postgres \
psql -U emailclient -d emailclient_db -c "SELECT 1"
# 3c. Test Redis connectivity
docker-compose exec -T redis redis-cli ping
# 3d. Test email service API
curl http://localhost:5000/health
curl http://localhost:5000/api/accounts \
-H "X-Tenant-ID: default" \
-H "Authorization: Bearer $JWT_TOKEN"
# 3e. Check logs for errors
docker-compose logs --tail 50
Step 4: Configure Load Balancer
# /etc/nginx/sites-available/emailclient
upstream emailclient_backend {
server email-service:5000 weight=1;
server email-service-2:5000 weight=1;
server email-service-3:5000 weight=1;
}
server {
listen 80;
server_name emailclient.production.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name emailclient.production.example.com;
ssl_certificate /etc/letsencrypt/live/emailclient.production.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/emailclient.production.example.com/privkey.pem;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "1; mode=block" always;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=60r/m;
limit_req zone=api_limit burst=20 nodelay;
location / {
proxy_pass http://emailclient_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Tenant-ID $http_x_tenant_id;
# Connection settings
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffering
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
}
location /health {
access_log off;
proxy_pass http://emailclient_backend/health;
}
}
Step 5: Configure Monitoring
# prometheus.yml (example)
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'email-service'
static_configs:
- targets: ['localhost:5000']
metrics_path: '/metrics'
- job_name: 'postgres'
static_configs:
- targets: ['localhost:9187']
- job_name: 'redis'
static_configs:
- targets: ['localhost:9121']
# alerts.yml (example)
groups:
- name: email_service
rules:
- alert: EmailServiceDown
expr: up{job="email-service"} == 0
for: 1m
annotations:
summary: "Email service is down"
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
for: 5m
annotations:
summary: "High error rate detected"
- alert: DatabaseConnectivityIssue
expr: up{job="postgres"} == 0
for: 2m
annotations:
summary: "Database is unreachable"
Scaling Horizontally
For high-traffic deployments, scale horizontally across multiple nodes:
# docker-compose.scale.yml (example)
services:
email-service-1:
build: ./emailclient/deployment/docker/email-service
hostname: email-service-1
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
email-service-2:
build: ./emailclient/deployment/docker/email-service
hostname: email-service-2
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
email-service-3:
build: ./emailclient/deployment/docker/email-service
hostname: email-service-3
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- email-service-1
- email-service-2
- email-service-3
# Deploy scaled stack
docker-compose -f docker-compose.yml -f docker-compose.scale.yml up -d
# Scale to 5 instances
docker-compose -f docker-compose.yml -f docker-compose.scale.yml up -d --scale email-service=5
Maintenance
Backup Strategy
# Automated daily backup script
#!/bin/bash
BACKUP_DIR="/mnt/backups/emailclient"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
# Backup PostgreSQL
docker-compose exec -T postgres \
pg_dump -U emailclient emailclient_db | \
gzip > $BACKUP_DIR/db_$DATE.sql.gz
# Backup Redis
docker-compose exec -T redis \
redis-cli BGSAVE
docker cp emailclient-redis:/data/dump.rdb $BACKUP_DIR/redis_$DATE.rdb
# Cleanup old backups (keep 30 days)
find $BACKUP_DIR -name "db_*.sql.gz" -mtime +30 -delete
find $BACKUP_DIR -name "redis_*.rdb" -mtime +30 -delete
# Send to cloud storage
aws s3 sync $BACKUP_DIR s3://emailclient-backups/
echo "Backup completed: $BACKUP_DIR"
Add to crontab:
0 2 * * * /opt/emailclient/scripts/backup.sh
Log Rotation
# /etc/logrotate.d/emailclient
/var/lib/docker/volumes/email-service-logs/_data/* {
daily
rotate 30
compress
delaycompress
notifempty
create 0644 root root
sharedscripts
}
Updates & Patches
# 1. Pull latest code
git pull origin main
# 2. Build updated image
docker-compose build --no-cache email-service
# 3. Restart service (with health check grace period)
docker-compose up -d email-service
# 4. Verify health
sleep 15
curl http://localhost:5000/health
# 5. Check logs for errors
docker-compose logs --tail 50 email-service
Zero-Downtime Deployments
Using rolling restart with health checks:
# 1. Update code and rebuild
git pull origin main
docker-compose build
# 2. Rolling restart (one container at a time)
docker-compose up -d email-service # Restarts one instance
# Health check verifies it's back up before next
docker-compose up -d email-service # Restarts next instance
# Alternative: Use orchestration platform
# Kubernetes: kubectl rollout restart deployment/email-service
# Docker Swarm: docker service update --force-update email-service
Troubleshooting
Service Fails to Start
# Check logs
docker-compose logs email-service
# Verify dependencies
docker-compose ps
# Check environment variables
docker inspect emailclient-email-service | grep -A 20 "Env"
# Rebuild from scratch
docker-compose down
docker system prune -f
docker-compose build --no-cache
docker-compose up -d
Database Connection Issues
# Test connectivity
docker-compose exec -T email-service \
psql -h postgres -U emailclient -d emailclient_db -c "SELECT 1"
# Check connection logs
docker-compose logs postgres | grep connection
# Verify credentials
echo $DATABASE_URL
# Check network connectivity
docker-compose exec postgres \
netstat -tlnp | grep 5432
High Memory Usage
# Monitor memory
docker stats email-service
# Reduce worker count
GUNICORN_WORKERS=2 docker-compose up -d email-service
# Clear caches
docker-compose exec redis redis-cli FLUSHALL
Email Not Syncing
# Check Celery workers
docker-compose logs celery-worker
# Monitor task queue
docker-compose exec redis redis-cli LLEN celery
# Restart workers
docker-compose restart celery-worker celery-beat
# Check IMAP connectivity
docker-compose exec email-service \
python -c "from imapclient import IMAPClient; IMAPClient('dovecot').login('user', 'pass')"
Security Checklist
Production deployment must pass:
- All secrets use strong random values (>32 characters)
- TLS enabled for all connections (HTTPS, IMAPS, POP3S)
- Firewall rules restrict access to necessary ports only
- Container runs as non-root user
- Sensitive data not logged or exposed in errors
- Rate limiting configured to prevent abuse
- CORS origins limited to trusted domains
- Database credentials encrypted or in secrets manager
- Email credentials encrypted with strong key
- Regular security updates applied
- Security scanning enabled (container, dependency scanning)
- Monitoring and alerting configured
Support
- Issues: GitHub Issues
- Documentation: CLAUDE.md, Email Client Plan
- Contact: dev@metabuilder.local
Version
- Phase: 8 (Email Client Implementation)
- Created: 2026-01-24
- Last Updated: 2026-01-24