services: haraka-inbound: image: ${HARAKA_IMAGE:-git.elektrine.com/elektrine/elektrine-haraka}:${HARAKA_IMAGE_TAG:-latest} # For local development, comment out image and uncomment build: # build: ../ ports: - "25:25" volumes: - ../logs:/app/logs - ../config:/app/config - ../config/dkim:/data/haraka/dkim - ../plugins:/app/plugins:ro - ../lib:/app/lib:ro - ../scripts:/app/scripts:ro - ssl-certs:/app/ssl environment: - NODE_ENV=production - HARAKA_ROLE=inbound-mx - HARAKA_API_KEY=${HARAKA_API_KEY:-} - PHOENIX_API_KEY=${PHOENIX_API_KEY:-} - PHOENIX_WEBHOOK_URL=${PHOENIX_WEBHOOK_URL:-} - PHOENIX_VERIFY_URL=${PHOENIX_VERIFY_URL:-} - PHOENIX_DOMAINS_URL=${PHOENIX_DOMAINS_URL:-} - REDIS_URL=${REDIS_URL:-redis://redis:6379} - ELEKTRINE_QUEUE_NAME=${ELEKTRINE_QUEUE_NAME:-elektrine:inbound} - ELEKTRINE_DLQ_NAME=${ELEKTRINE_DLQ_NAME:-elektrine:inbound:dlq} - HARAKA_DOMAIN=${HARAKA_DOMAIN:-mail.example.com} restart: unless-stopped networks: - haraka-network - main-app-network depends_on: - redis - clamav - spamassassin deploy: resources: limits: memory: 1G cpus: '2.0' healthcheck: test: ["CMD", "nc", "-z", "localhost", "25"] interval: 30s timeout: 10s retries: 5 start_period: 30s logging: driver: "json-file" options: max-size: "10m" max-file: "3" haraka-submission: image: ${HARAKA_IMAGE:-git.elektrine.com/elektrine/elektrine-haraka}:${HARAKA_IMAGE_TAG:-latest} volumes: - ../logs:/app/logs - ../config:/app/config - ../config/dkim:/data/haraka/dkim - ../plugins:/app/plugins:ro - ../lib:/app/lib:ro - ../scripts:/app/scripts:ro - ssl-certs:/app/ssl environment: - NODE_ENV=production - HARAKA_ROLE=submission - HARAKA_API_KEY=${HARAKA_API_KEY:-} - PHOENIX_API_KEY=${PHOENIX_API_KEY:-} - PHOENIX_VERIFY_URL=${PHOENIX_VERIFY_URL:-} - PHOENIX_DOMAINS_URL=${PHOENIX_DOMAINS_URL:-} - REDIS_URL=${REDIS_URL:-redis://redis:6379} - HARAKA_DOMAIN=${HARAKA_DOMAIN:-mail.example.com} restart: unless-stopped networks: - haraka-network - main-app-network depends_on: - redis deploy: resources: limits: memory: 768M cpus: '1.0' haraka-outbound: image: ${HARAKA_IMAGE:-git.elektrine.com/elektrine/elektrine-haraka}:${HARAKA_IMAGE_TAG:-latest} ports: - "127.0.0.1:${HARAKA_HTTP_BIND_PORT:-18080}:8080" volumes: - ../logs:/app/logs - ../config:/app/config - ../config/dkim:/data/haraka/dkim - ../plugins:/app/plugins:ro - ../lib:/app/lib:ro - ../scripts:/app/scripts:ro - ssl-certs:/app/ssl environment: - NODE_ENV=production - HARAKA_ROLE=outbound-relay - HARAKA_API_KEY=${HARAKA_API_KEY:-} - PHOENIX_API_KEY=${PHOENIX_API_KEY:-} - HARAKA_HTTP_API_KEY=${HARAKA_HTTP_API_KEY:-} - PHOENIX_WEBHOOK_URL=${PHOENIX_WEBHOOK_URL:-} - PHOENIX_VERIFY_URL=${PHOENIX_VERIFY_URL:-} - PHOENIX_DOMAINS_URL=${PHOENIX_DOMAINS_URL:-} - REDIS_URL=${REDIS_URL:-redis://redis:6379} - HARAKA_HTTP_PORT=8080 - HARAKA_HTTP_HOST=0.0.0.0 - HARAKA_DOMAIN=${HARAKA_DOMAIN:-mail.example.com} restart: unless-stopped networks: - haraka-network - main-app-network depends_on: - redis deploy: resources: limits: memory: 768M cpus: '1.0' healthcheck: test: [ "CMD", "node", "-e", "const key = process.env.HARAKA_HTTP_API_KEY || process.env.HARAKA_API_KEY || ''; const req = require('http').request('http://127.0.0.1:8080/status', { headers: key ? { 'x-api-key': key } : {} }, (res) => process.exit(res.statusCode === 200 ? 0 : 1)); req.on('error', () => process.exit(1)); req.end();" ] interval: 30s timeout: 10s retries: 5 start_period: 30s haraka-worker: image: ${HARAKA_IMAGE:-git.elektrine.com/elektrine/elektrine-haraka}:${HARAKA_IMAGE_TAG:-latest} command: ["node", "/app/scripts/elektrine-worker.js"] volumes: - ../logs:/app/logs - ../config:/app/config - ../config/dkim:/data/haraka/dkim - ../plugins:/app/plugins:ro - ../lib:/app/lib:ro - ../scripts:/app/scripts:ro environment: - NODE_ENV=production - HARAKA_ROLE=worker - HARAKA_API_KEY=${HARAKA_API_KEY:-} - PHOENIX_API_KEY=${PHOENIX_API_KEY:-} - PHOENIX_WEBHOOK_URL=${PHOENIX_WEBHOOK_URL:-} - PHOENIX_VERIFY_URL=${PHOENIX_VERIFY_URL:-} - PHOENIX_DOMAINS_URL=${PHOENIX_DOMAINS_URL:-} - REDIS_URL=${REDIS_URL:-redis://redis:6379} - ELEKTRINE_QUEUE_NAME=${ELEKTRINE_QUEUE_NAME:-elektrine:inbound} - ELEKTRINE_DLQ_NAME=${ELEKTRINE_DLQ_NAME:-elektrine:inbound:dlq} - WEBHOOK_MAX_RETRIES=${WEBHOOK_MAX_RETRIES:-5} - WEBHOOK_RETRY_BASE_MS=${WEBHOOK_RETRY_BASE_MS:-1000} restart: unless-stopped networks: - haraka-network - main-app-network depends_on: - redis redis: image: ${REDIS_IMAGE:-redis:7-alpine} command: - redis-server - --appendonly - yes - --appendfsync - everysec - --save - "900 1" - --save - "300 10" - --save - "60 10000" ports: - "127.0.0.1:6379:6379" volumes: - redis-data:/data restart: unless-stopped networks: - haraka-network healthcheck: test: ["CMD", "redis-cli", "PING"] interval: 30s timeout: 5s retries: 5 clamav: image: ${CLAMAV_IMAGE:-clamav/clamav:stable} ports: - "127.0.0.1:3310:3310" volumes: - clamav-data:/var/lib/clamav environment: - CLAMAV_NO_FRESHCLAM=false restart: unless-stopped networks: - haraka-network healthcheck: test: ["CMD", "/usr/local/bin/clamdcheck.sh"] interval: 60s timeout: 120s retries: 3 deploy: resources: limits: memory: 2G cpus: '1.0' spamassassin: image: ${SPAMASSASSIN_IMAGE:-dinkel/spamassassin:latest} ports: - "127.0.0.1:783:783" volumes: - spamassassin-data:/var/lib/spamassassin environment: - SA_UPDATE=1 restart: unless-stopped networks: - haraka-network deploy: resources: limits: memory: 512M cpus: '0.5' networks: haraka-network: driver: bridge main-app-network: external: true name: ${MAIN_APP_NETWORK:-docker_elektrine_network} volumes: redis-data: ssl-certs: clamav-data: spamassassin-data: