Skip to content

Latest commit

 

History

History
495 lines (363 loc) · 11.8 KB

File metadata and controls

495 lines (363 loc) · 11.8 KB

EmailEngine Docker Deployment Guide

This guide covers everything from local development to production deployment of EmailEngine using Docker.

Table of Contents

Quick Start

Prerequisites

  • Docker Engine 20.10.0+ and Docker Compose 2.0.0+
  • System Requirements:
    • Development: 4GB RAM minimum
    • Production: 8GB RAM minimum, 16GB+ recommended
  • Critical Notes:
    • No Docker resource limits are imposed
    • Redis has NO memory limit and uses 'noeviction' policy (database mode)
    • MUST monitor memory usage to prevent system OOM
  • Monitoring: Use docker stats and Redis INFO memory regularly

Development Setup

# Clone or download EmailEngine
git clone https://github.com/postalsys/emailengine.git
cd emailengine

# Start with development settings
cp .env.development .env
docker-compose up

Access EmailEngine at http://localhost:3000

Development mode features:

  • No authentication required
  • Services accessible from any network
  • Debug logging enabled
  • Minimal resource requirements

Production Setup (5 minutes)

# Use automated setup script
./setup-production.sh

# Or manually:
cp .env.production .env
nano .env  # Add secure passwords (see Configuration section)
docker-compose up -d

Production mode features:

  • Redis authentication required
  • Services bound to localhost only
  • Optimized logging and persistence
  • Health checks and resource limits

Configuration

EmailEngine uses a single docker-compose.yml that adapts based on environment variables in .env.

Environment Templates

File Purpose Security Use Case
.env.development Local development None Testing, development
.env.production Production deployment Full Live systems

Key Configuration Differences

Setting Development Production
Network Binding 0.0.0.0 (all interfaces) 127.0.0.1 (localhost only)
Redis Password None Required
Secret Key Default Must generate
Health Checks Relaxed Strict
Logging Debug Info
System Requirements Minimal Production-grade

Essential Production Variables

# Generate secure credentials
EENGINE_SECRET=$(openssl rand -hex 32)
REDIS_PASSWORD=$(openssl rand -base64 32)

# Configure in .env
EENGINE_SECRET=<generated-secret>
REDIS_PASSWORD=<generated-password>
EMAILENGINE_API_BIND=127.0.0.1  # Never expose directly

# Note: Redis has no memory limit and uses 'noeviction' policy
# This is intentional - EmailEngine uses Redis as a database

Production Deployment

Step 1: Server Preparation

# Create application directory
sudo mkdir -p /opt/emailengine
cd /opt/emailengine

# Copy files
# - docker-compose.yml
# - .env.production
# - setup-production.sh

# Generate credentials
./setup-production.sh

Step 2: Configure Reverse Proxy (Required)

Never expose EmailEngine directly to the internet. Use a reverse proxy with TLS.

Option A: Nginx

server {
    listen 443 ssl http2;
    server_name emailengine.example.com;

    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    # Security headers
    add_header Strict-Transport-Security "max-age=31536000" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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-Proto $scheme;

        # Long timeouts for email operations
        proxy_connect_timeout 600;
        proxy_read_timeout 600;
    }

    # WebSocket support
    location /socket.io/ {
        proxy_pass http://127.0.0.1:3000/socket.io/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

server {
    listen 80;
    server_name emailengine.example.com;
    return 301 https://$server_name$request_uri;
}

Option B: Caddy (Simpler)

emailengine.example.com {
    reverse_proxy localhost:3000
    header Strict-Transport-Security "max-age=31536000"
    header X-Frame-Options "SAMEORIGIN"
    header X-Content-Type-Options "nosniff"
}

Step 3: Firewall Configuration

# Only allow necessary ports
sudo ufw allow 22/tcp   # SSH
sudo ufw allow 80/tcp   # HTTP (redirect)
sudo ufw allow 443/tcp  # HTTPS
sudo ufw enable

# Verify internal services aren't exposed
sudo netstat -tuln | grep -E '3000|2525|9993'  # Should show 127.0.0.1 only

Step 4: Start Services

docker-compose up -d
docker-compose ps  # Verify all services are healthy

Operations & Maintenance

Monitoring

Health Checks

# Application health
curl http://localhost:3000/health

# Redis connectivity
docker-compose exec redis redis-cli -a "$REDIS_PASSWORD" ping

# Monitor resource usage (important: no limits are set)
docker stats --no-stream

# Continuous monitoring
docker stats

# Recent errors
docker-compose logs --tail=100 emailengine | grep ERROR

Key Metrics to Monitor

  • CPU usage < 80%
  • Memory usage < 90%
  • Redis memory usage < max configured
  • API response times
  • Queue lengths

Backup Strategy

Automated Backup Script

#!/bin/bash
# /opt/emailengine/backup.sh

BACKUP_DIR="/backup/emailengine"
DATE=$(date +%Y%m%d-%H%M%S)

# Load environment
source /opt/emailengine/.env

# Trigger Redis save
docker-compose exec -T redis redis-cli -a "$REDIS_PASSWORD" BGSAVE
sleep 5

# Backup data
docker run --rm \
  -v emailengine_redis-data:/data \
  -v $BACKUP_DIR:/backup \
  alpine tar czf /backup/redis-$DATE.tar.gz -C /data .

# Backup config
tar czf $BACKUP_DIR/config-$DATE.tar.gz .env docker-compose.yml

# Keep 30 days
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete

Add to crontab:

0 2 * * * /opt/emailengine/backup.sh

Updates

Update

# Pull latest version
docker-compose pull

# Rolling restart
docker-compose up -d --no-deps emailengine

# Verify
docker-compose logs --tail=50 emailengine

Rollback if Needed

# Specify previous version in .env
EMAILENGINE_VERSION=2.40.0
docker-compose up -d --no-deps emailengine

Performance Tuning

Important: EmailEngine is resource-intensive and will use available system resources.

System Requirements by Deployment Size

Accounts Min RAM Recommended RAM CPU Cores Workers
< 100 8GB 16GB 4 4
100-500 16GB 32GB 8 8
500-2000 32GB 64GB 16 16
2000+ 64GB 128GB+ 24+ 24

Configuration Guidelines

# Adjust in .env based on your needs:

# Number of worker processes (4-24)
EENGINE_WORKERS=8

# Redis configuration
# Redis is used as a DATABASE, not a cache:
# - No memory limit is set (uses available system memory)
# - Eviction policy is 'noeviction' to prevent data loss
# - Monitor usage: docker-compose exec redis redis-cli INFO memory

Performance Notes

  • EmailEngine will automatically use available CPU and RAM
  • No artificial limits are imposed by default
  • Redis operates as a database with no memory limits and no eviction
  • Workers should match CPU cores (minimum 4, maximum 24)

Monitoring Recommendations

Since resource limits are not enforced:

  1. Critical: Monitor Redis memory usage regularly
    docker-compose exec redis redis-cli INFO memory
  2. Use system monitoring tools (htop, top, docker stats)
  3. Set up alerts for high memory usage (especially important for Redis)
  4. Ensure sufficient swap space as a safety measure
  5. Consider using monitoring solutions like Prometheus + Grafana

Troubleshooting

Common Issues

Services Won't Start

# Check configuration
docker-compose config

# Verify .env file
grep -E "EENGINE_SECRET|REDIS_PASSWORD" .env

# Check ports
netstat -tuln | grep -E '3000|2525|9993'

High Memory Usage

# Check actual memory usage (no container limits set)
docker stats --no-stream

# Check Redis memory (critical - Redis has no memory limit)
docker-compose exec redis redis-cli -a "$REDIS_PASSWORD" INFO memory

# Redis memory metrics to monitor:
# - used_memory_human: Total memory used by Redis
# - used_memory_rss_human: Memory used from OS perspective
# - mem_fragmentation_ratio: Should be close to 1.0

# If memory usage is too high, you may need to:
# 1. Add more RAM to the system
# 2. Scale horizontally (multiple EmailEngine instances)
# 3. Review and optimize EmailEngine configuration

Connection Issues

# Test Redis connection
docker-compose exec emailengine redis-cli -h redis -a "$REDIS_PASSWORD" ping

# Check logs
docker-compose logs --tail=100 redis
docker-compose logs --tail=100 emailengine

Performance Issues

# Enable debug logging temporarily
docker-compose exec emailengine sh -c 'export EENGINE_LOG_LEVEL=debug'
docker-compose restart emailengine

# Check slow operations
docker-compose exec redis redis-cli -a "$REDIS_PASSWORD" SLOWLOG GET 10

Recovery Procedures

Restore from Backup

# Stop services
docker-compose down

# Restore data
docker run --rm \
  -v emailengine_redis-data:/data \
  -v /backup:/backup \
  alpine tar xzf /backup/redis-latest.tar.gz -C /data

# Start services
docker-compose up -d

Security Checklist

Before Production

  • Strong EENGINE_SECRET (32+ characters)
  • Strong REDIS_PASSWORD (32+ characters)
  • Services bound to localhost only
  • Reverse proxy with TLS configured
  • Firewall enabled (ports 80/443 only)
  • Backup automation configured
  • Memory monitoring in place (critical - Redis has no limits)
  • Log rotation enabled
  • Sufficient system RAM for Redis growth
  • Swap space configured as safety measure

Ongoing Security

  • Rotate API keys quarterly
  • Update Docker images monthly
  • Review access logs weekly
  • Test backup restoration monthly
  • Security scan quarterly

Quick Reference

Essential Commands

# Status
docker-compose ps
docker-compose logs --tail=50

# Restart
docker-compose restart emailengine

# Stop/Start
docker-compose stop
docker-compose start

# Full restart
docker-compose down
docker-compose up -d

# Update
docker-compose pull
docker-compose up -d

# Backup
docker-compose exec redis redis-cli -a "$REDIS_PASSWORD" BGSAVE

File Locations

  • Configuration: /opt/emailengine/.env
  • Compose file: /opt/emailengine/docker-compose.yml
  • Redis data: Docker volume emailengine_redis-data
  • Logs: docker-compose logs

Environment Switching

# To development
cp .env.development .env
docker-compose restart

# To production
cp .env.production .env
# Edit .env with secure values
docker-compose restart

Support