Prerequisites Checklist
Before starting your KumoMTA installation, verify:
- [ ] Ubuntu 22.04 LTS or RHEL 9+ (fresh install recommended)
- [ ] 4 CPU cores minimum, 8GB RAM (8 cores, 32GB for 500K+ emails/hour)
- [ ] 100GB+ NVMe SSD for message spool
- [ ] Minimum 2 dedicated sending IPs (4+ recommended for warmup rotation)
- [ ] Domain name with full DNS access (MX, TXT, DKIM)
- [ ] Reverse DNS (PTR) configured for each sending IP by your host
- [ ] Firewall: ports 25 (MX), 587 (submission), 465 (SMTPS), 8080 (API), 2000 (metrics)
Step 1: Ubuntu Server Preparation
# System update
sudo apt-get update && sudo apt-get upgrade -y
# Required packages
sudo apt-get install -y curl wget gnupg2 net-tools dnsutils telnet postfix
# Stop and disable Postfix (conflicts with KumoMTA on port 25)
sudo systemctl stop postfix
sudo systemctl disable postfix
# Configure firewall
sudo ufw allow 22/tcp # SSH
sudo ufw allow 25/tcp # SMTP MX
sudo ufw allow 587/tcp # Submission
sudo ufw allow 465/tcp # SMTPS
sudo ufw allow 8080/tcp # HTTP API
sudo ufw allow 2000/tcp # Prometheus metrics
sudo ufw enable
Step 2: Install KumoMTA
Option A: Official Package Repository (Recommended for Bare Metal)
# Add KumoMTA GPG key
curl -L https://packagecloud.io/kumomta/kumomta/gpgkey | sudo apt-key add -
# Add repository
echo "deb https://packagecloud.io/kumomta/kumomta/ubuntu jammy main" | sudo tee /etc/apt/sources.list.d/kumomta.list
# Install
sudo apt-get update
sudo apt-get install -y kumomta
# Verify
kumomta --version
Option B: Docker Installation (Recommended for Cloud Deployments)
# Pull official image
docker pull ghcr.io/kumomta/kumomta:latest
# Create directories
mkdir -p ~/kumomta/{etc,spool,logs,keys,tls}
# Run container
docker run -d \
--name=kumomta \
--restart=unless-stopped \
-p 25:2525 \
-p 587:2587 \
-p 465:2465 \
-p 8080:8080 \
-p 2000:2000 \
-v ~/kumomta/etc:/etc/kumomta \
-v ~/kumomta/spool:/var/spool/kumomta \
-v ~/kumomta/logs:/var/log/kumomta \
-v ~/kumomta/keys:/etc/kumomta/keys \
ghcr.io/kumomta/kumomta:latest
Option C: Kubernetes Helm Chart
# Add Helm repository
helm repo add kumomta https://charts.kumomta.com
helm repo update
# Install with production values
helm install kumomta kumomta/kumomta \
--namespace email-infra \
--create-namespace \
--values values-production.yaml
Production values-production.yaml:
replicaCount: 3
image:
repository: ghcr.io/kumomta/kumomta
tag: latest
pullPolicy: Always
resources:
requests:
cpu: 2
memory: 4Gi
limits:
cpu: 8
memory: 16Gi
service:
type: ClusterIP
ports:
smtp: 25
submission: 587
smtps: 465
api: 8080
metrics: 2000
persistence:
enabled: true
size: 50Gi
storageClass: fast-ssd
prometheus:
enabled: true
serviceMonitor: true
Step 3: Core Configuration File
Create /etc/kumomta/kumomta.conf:
-- KumoMTA Production Configuration
-- Reference: https://docs.kumomta.com
-- SMTP Listeners
kumo.start_smtp_listener {
listen = "[::]:25",
name = "mx",
-- Accept mail from anywhere (MX role)
}
kumo.start_smtp_listener {
listen = "[::]:587",
name = "submission",
auth_require_tls = true, -- AUTH required on submission port
}
-- HTTP API for message injection
kumo.start_http_listener {
listen = "[::]:8080",
trusted_hosts = { "127.0.0.1", "10.0.0.0/8", "172.16.0.0/12" },
}
-- Prometheus metrics (for Grafana)
kumo.start_http_listener {
listen = "[::]:2000",
trusted_hosts = { "127.0.0.1" },
}
-- DKIM Signing Configuration
kumo.configure_dkim_signing {
domain = "example.com",
selector = "mail",
key_file = "/etc/kumomta/keys/mail._domainkey.example.com.pem",
headers = { "From", "To", "Subject", "Date", "Message-ID" },
}
-- Logging
kumo.configure_log {
path = "/var/log/kumomta/kumomta.log",
level = "info",
}
Step 4: DKIM, SPF, and DMARC Setup
Generate DKIM Keys
# Generate 2048-bit DKIM key
openssl genrsa -out mail._domainkey.example.com.pem 2048
openssl rsa -in mail._domainkey.example.com.pem -pubout > mail._domainkey.example.com.txt
# Move to KumoMTA keys directory
sudo mv mail._domainkey.example.com.pem /etc/kumomta/keys/
sudo chmod 600 /etc/kumomta/keys/mail._domainkey.example.com.pem
# Set ownership
sudo chown kumomta:kumomta /etc/kumomta/keys/mail._domainkey.example.com.pem
DNS Records to Add
DKIM TXT Record (selector: mail._domainkey):
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEB...
SPF TXT Record:
v=spf1 ip4:203.0.113.0/24 ~all
DMARC TXT Record (_dmarc.example.com):
v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; pct=100
Verify your DKIM with:
dig TXT mail._domainkey.example.com +short
Step 5: Multi-Tenant Lua Configuration
KumoMTA's Lua scripting is its most powerful feature. This is how you implement per-tenant rate limiting and traffic shaping — something that requires external tools with Postfix or complex XML vMTA configuration with PowerMTA.
-- /etc/kumomta/policy.lua
-- Tenant configuration database (replace with your DB integration)
local TENANTS = {
["acme-corp"] = { limit = 50000, dkim_domain = "mail.acme.com" },
["startup-xyz"] = { limit = 5000, dkim_domain = "mail.startup.xyz" },
}
-- IP pool for warmup rotation
local IP_POOL = {
"203.0.113.1",
"203.0.113.2",
"203.0.113.3",
"203.0.113.4",
}
-- Per-tenant sending limits
kumo.on("smtp_server_greeting", function(domain, meta)
local tenant = meta.tenant or "anonymous"
local config = TENANTS[tenant]
if config then
kumo.limit_sending(tenant, config.limit, { per = "minute" })
kumo.set_sending_ip(IP_POOL[1]) -- Primary IP
else
kumo.limit_sending("anonymous", 100, { per = "minute" })
end
end)
-- Dynamic throttling on 4xx responses (adaptive warmup)
kumo.on("smtp_delivery_result", function(result, meta)
if result.code >= 420 and result.code < 430 then
-- ISP throttling detected
local tenant = meta.tenant or "default"
local current = get_tenant_limit(tenant)
set_tenant_limit(tenant, math.floor(current * 0.7))
log_warn("Adaptive throttling: " .. tenant .. " reduced to " .. math.floor(current * 0.7) .. "/min")
end
end)
-- DKIM signing per tenant
kumo.on("smtp_message_received", function(domain, meta)
local tenant = meta.tenant or "default"
local config = TENANTS[tenant]
if config and config.dkim_domain then
kumo.sign_dkim(config.dkim_domain, "mail", config.dkim_domain)
end
end)
Link this policy in your kumomta.conf:
kumo.load_policy_file("/etc/kumomta/policy.lua")
Step 6: Prometheus Monitoring Setup
KumoMTA exposes metrics at port 2000. Add this to your Prometheus config:
# /etc/prometheus/prometheus.yml
scrape_configs:
- job_name: 'kumomta'
static_configs:
- targets: ['kumomta-server:2000']
metrics_path: /metrics
scrape_interval: 15s
Key metrics to monitor in Grafana:
| Metric | Description | Alert Threshold |
|---|---|---|
kumomta_smtp_messages_received_total |
Total inbound messages | Rate > 10K/min |
kumomta_delivery_delivered_total |
Successfully delivered | Check % vs received |
kumomta_delivery_bounced_total |
Bounced messages | Bounce rate > 3% |
kumomta_queue_depth |
Messages in queue | > 10,000 |
kumomta_delivery_latency_seconds |
End-to-end latency | p95 > 30s |
Step 7: TLS Configuration
-- TLS 1.3 configuration (add to kumomta.conf)
kumo.configure_tls {
min_tls_version = "1.3",
ciphers = "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256",
prefer_server_ciphers = true,
}
-- SMTPS listener (port 465)
kumo.start_smtp_listener {
listen = "[::]:465",
name = "smtps",
tls = {
-- Generate self-signed cert for testing:
-- openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
cert_file = "/etc/kumomta/tls/server.crt",
key_file = "/etc/kumomta/tls/server.key",
},
}
Step 8: Production Testing
# Test SMTP connectivity
telnet localhost 25
EHLO test.example.com
250-Hello test.example.com
250-PIPELINING
250-8BITMIME
250-STARTTLS
250 AUTH PLAIN LOGIN
QUIT
# Test message injection via HTTP API
curl -X POST http://localhost:8080/v1/message \
-H "Content-Type: application/json" \
-d '{
"from": "test@example.com",
"to": "recipient@Gmail.com",
"subject": "KumoMTA Test",
"body": "Test message from KumoMTA"
}'
# Check metrics
curl http://localhost:2000/metrics | grep -E "^kumomta_"
# View logs
tail -f /var/log/kumomta/kumomta.log
Common Setup Mistakes
Mistake 1: Skipping IP Warmup
Fresh IPs need 8 weeks of gradual ramp. Configure warmup limits in Lua policy before sending any production volume. Gmail, Outlook, and Yahoo all monitor new IP behavior — a sudden volume spike triggers instant throttling or blacklisting.
Mistake 2: Missing DKIM Alignment
Your DKIM selector domain must align with your From domain. From: @example.com requires selector._domainkey.example.com (not selector._domainkey.subdomain.example.com).
Mistake 3: No Bounce Processing
Configure automatic suppression list updates from bounce codes. Hard bounces in your queue damage sender reputation with every ISP. Process them within hours, not days.
Mistake 4: Wrong Return-Path
Set a dedicated bounce domain (e.g., bounce@example.com) separate from your From domain. This enables proper SPF alignment and DMARC pass.
Mistake 5: Insufficient Connection Limits
KumoMTA's defaults are conservative. For high-volume sending, tune delivery_threads and max_connections_per_domain in your configuration.
FAQ
Q: Can I run KumoMTA and Postfix on the same server?
A: Yes, but on different ports. Set KumoMTA on port 25 for external MX and Postfix on 2525 for internal relay. Do not run both on port 25 simultaneously.
Q: How do I migrate from PowerMTA IP pool configuration to KumoMTA?
A: Convert your PMTA <virtual-mta> XML blocks to KumoMTA Lua tables. The logic is equivalent — PMTA's max-msg-rate maps to kumo.limit_sending(). See our KumoMTA vs PowerMTA migration guide for detailed configuration mapping.
Q: Does KumoMTA support SMTP AUTH on port 587?
A: Yes. Configure auth_require_tls = true on the submission listener. KumoMTA supports PLAIN, LOGIN, and CRAM-MD5 authentication mechanisms.
Q: What's the minimum viable server for KumoMTA?
A: 2 cores, 4GB RAM handles ~25,000 emails/hour comfortably. Production deployments should target 4+ cores and 8GB+ RAM.
Q: Can KumoMTA handle 100 million emails per day?
A: Yes. With horizontal scaling (multiple KumoMTA instances behind a load balancer), 100M/day is well within KumoMTA's throughput capabilities. We routinely see 150,000-200,000 messages/minute per core in sustained testing.
Next Steps
PostMTA's engineering team provides:
- Production KumoMTA deployment with your exact infrastructure
- PowerMTA to KumoMTA migration with IP reputation continuity
- DKIM/SPF/DMARC authentication audit and full compliance setup
- IP warmup management — full service until full volume
👉 Get a free KumoMTA setup consultation →
For related guides, see IP Warmup Strategies, Email Authentication Setup, and Open Source Email Infrastructure.
Reference: KumoMTA Official Documentation | KumoMTA GitHub Repository
Top comments (0)