KumoMTA and KumoProxy
Deployment Files
Nginx Reverse Proxy

Nginx Reverse Proxy

Use Nginx in front of KumoMTA when you want TLS termination, bearer-token authentication, request size limits, and a simple deny-by-default public surface.

The recommended shape is:

public HTTPS :443
  Nginx validates bearer token
  Nginx proxies /api/inject/v1 to 127.0.0.1:8000/api/inject/v1
  Nginx proxies /metrics to 127.0.0.1:8000/metrics
  Nginx returns 404 for everything else

Where it lives

Install on the KumoMTA host:

/etc/nginx/conf.d/mta.yourdomain.com.conf

The TLS certificate should cover mta.yourdomain.com.

Sanitized server shape

map $http_authorization $auth_ok {
    default                              0;
    "Bearer <PING8_INJECTION_TOKEN>"     1;
}
 
server {
    listen 443 ssl http2;
    server_name mta.yourdomain.com;
 
    ssl_certificate     /etc/letsencrypt/live/mta.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mta.yourdomain.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
 
    add_header Strict-Transport-Security "max-age=31536000" always;
    client_max_body_size 25m;
 
    location = /api/inject/v1 {
        if ($auth_ok = 0) {
            return 401 '{"error":"unauthorized"}\n';
        }
 
        proxy_pass http://127.0.0.1:8000/api/inject/v1;
        proxy_set_header Host $host;
        proxy_set_header Authorization "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 30s;
    }
 
    location = /metrics {
        if ($auth_ok = 0) {
            return 401;
        }
 
        proxy_pass http://127.0.0.1:8000/metrics;
        proxy_set_header Authorization "";
    }
 
    location / {
        return 404;
    }
}
 
server {
    listen 80;
    server_name mta.yourdomain.com;
 
    location /.well-known/acme-challenge/ {
        root /var/www/letsencrypt;
    }
 
    location / {
        return 301 https://$host$request_uri;
    }
}

Why Nginx handles auth

KumoMTA can run an HTTP listener directly, but a reverse proxy gives you a smaller public interface:

  • TLS certificates live in one familiar layer.
  • Bearer-token comparison happens before KumoMTA sees the request.
  • The KumoMTA listener can bind to 127.0.0.1.
  • /metrics can share the same authentication model.
  • Unknown paths are denied by default.

KumoMTA's official HTTP listener docs explain the listener options and trusted-host behavior: KumoMTA HTTP listeners (opens in a new tab).

PING8 fields

Use these values in the PING8 KumoMTA connection screen:

PING8 fieldValue
Base URLhttps://mta.yourdomain.com
Injection path/api/inject/v1
Metrics URLhttps://mta.yourdomain.com/metrics
Auth modeBearer token
Auth secret<PING8_INJECTION_TOKEN>
TLS verificationEnabled

Security checks

  1. https://mta.yourdomain.com/api/inject/v1 without the bearer token returns 401.
  2. https://mta.yourdomain.com/metrics without the bearer token returns 401.
  3. Unknown paths return 404.
  4. KumoMTA does not listen publicly on port 8000.
  5. Port 80 is used only for ACME and HTTP-to-HTTPS redirect.
  6. The injection token is not present in shell history or source control.

Common mistakes

  • Exposing KumoMTA's HTTP listener directly on 0.0.0.0.
  • Forgetting to clear the upstream Authorization header after Nginx validates it.
  • Using a TLS certificate for mail.yourdomain.com when the endpoint is mta.yourdomain.com.
  • Setting client_max_body_size too low for real messages.
  • Making /metrics public without authentication.