Skip to main content
Version: 0.16

HAProxy

HAProxy is an open-source TCP and HTTP load balancer widely used in high-availability deployments. It supports health checks, TLS termination, connection persistence, and the Proxy Protocol.

Stalwart can sit behind HAProxy for any of its listener protocols. The example below uses TCP-passthrough on every port (HAProxy hands TLS to Stalwart untouched), but HAProxy can equally terminate TLS for HTTP traffic and forward plain HTTP to Stalwart's port 8080. Both patterns produce the same OAuth, OIDC, and JMAP discovery responses; see How discovery URLs are composed for details and set the STALWART_PUBLIC_URL variable to the URL clients reach HAProxy on whenever it differs from https://<defaultHostname> on port 443.

The send-proxy-v2 directive on each backend carries the original client IP and TLS status through to Stalwart, which accepts the Proxy Protocol header when the source address is listed in proxyTrustedNetworks on the SystemSettings singleton (found in the WebUI under Settings › Network › Services, Settings › Network › General) or in overrideProxyTrustedNetworks on the matching NetworkListener.

Configuration

# Global settings
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-options no-sslv3
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!DSS:!RC4
tune.ssl.default-dh-param 2048

# Default settings
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

# Frontend configuration for various ports
frontend ft_smtp
bind *:25
mode tcp
option tcplog
default_backend bk_smtp

frontend ft_imap
bind *:143
mode tcp
option tcplog
default_backend bk_imap

frontend ft_smtps
bind *:465
mode tcp
option tcplog
default_backend bk_smtps

frontend ft_imaps
bind *:993
mode tcp
option tcplog
default_backend bk_imaps

frontend ft_https
bind *:443
mode tcp
option tcplog
default_backend bk_https

# Backend configuration
backend bk_smtp
mode tcp
option tcplog
server stalwart_mail_smtp 127.0.0.1:10025 send-proxy-v2

backend bk_imap
mode tcp
option tcplog
server stalwart_mail_imap 127.0.0.1:10143 send-proxy-v2

backend bk_smtps
mode tcp
option tcplog
server stalwart_mail_smtps 127.0.0.1:10465 send-proxy-v2

backend bk_imaps
mode tcp
option tcplog
server stalwart_mail_imaps 127.0.0.1:10993 send-proxy-v2

backend bk_https
mode tcp
option tcplog
server stalwart_mail_https 127.0.0.1:10443 send-proxy-v2

# Enable HAProxy stats
listen stats
bind *:8404
stats enable
stats uri /stats
stats refresh 10s
stats admin if LOCALHOST
stats auth admin:admin