RTFM · Networking
HAProxy for MailDragon
Use HAProxy as a deliberate TCP edge for MailDragon when the mail server lives on a private server network or when one public edge host serves several backends. Keep SMTP and IMAP protocol ownership clear.

What HAProxy does for mail—and what it does not
HAProxy accepts a TCP connection on the public edge and opens a TCP connection to the MailDragon backend. It can make the backend private, concentrate public firewall rules on one edge host, and health-check the TCP path. It does not create MX records, sign DKIM, set PTR, or turn a blocked ISP port 25 into an available one.
Internet SMTP peer
│ TCP 25
▼
203.0.113.10 HAProxy edge
│ TCP 25 over the server network
▼
192.0.2.25 MailDragon / Postfix
Internet mail client
│ TCP 465, 587, or 993 as intentionally offered
▼
HAProxy edge
▼
MailDragon / Postfix or DovecotA proxy cannot compensate for an unsuitable sending address. Decide which public IP MailDragon uses for outbound SMTP and verify PTR and FCrDNS for that address before treating inbound proxying as a mail-deliverability solution.
Choose the smallest listener set
| Port | Purpose | Publish when |
|---|---|---|
| 25/TCP | Server-to-server SMTP | You accept Internet mail and the provider/ISP permits it. |
| 465/TCP | Submission with implicit TLS | You deliberately support this client submission method. |
| 587/TCP | Authenticated message submission, normally STARTTLS | Mail clients need submission. |
| 993/TCP | IMAP with implicit TLS | Users need IMAP mailbox access. |
| 143, 110, 995/TCP | Optional IMAP/POP variants | Only when MailDragon is configured to provide the specific protocol. |
Do not copy every port into HAProxy merely because mail software can support it. Confirm MailDragon's Postfix and Dovecot listeners first, then publish the smallest useful subset. An internal health check can prove TCP reachability but does not replace protocol-specific authentication and TLS tests.
A complete TCP pass-through configuration
This example leaves TLS with MailDragon. That is usually the clearest choice for SMTP and IMAP: HAProxy is a TCP transport edge, while Postfix and Dovecot present their own certificates and negotiate their own TLS. Replace the private backend address only after proving it is reachable from the proxy host.
# /etc/haproxy/haproxy.cfg
global
log /dev/log local0
defaults
mode tcp
log global
option tcplog
timeout connect 5s
timeout client 5m
timeout server 5m
frontend smtp_in
bind :25
default_backend mail_smtp
backend mail_smtp
server maildragon 192.0.2.25:25 check
frontend submission_implicit_tls
bind :465
default_backend mail_submission_implicit_tls
backend mail_submission_implicit_tls
server maildragon 192.0.2.25:465 check
frontend submission_starttls
bind :587
default_backend mail_submission_starttls
backend mail_submission_starttls
server maildragon 192.0.2.25:587 check
frontend imaps
bind :993
default_backend mail_imaps
backend mail_imaps
server maildragon 192.0.2.25:993 checkHAProxy's native command accepts -f for a configuration file and -c for a configuration check. Always use the check before reload. On a normal Saphira OpenRC host, the package provides /etc/haproxy/haproxy.cfg and the haproxy service; on a selected systemd installation, first prove the matching unit exists before using systemctl.
haproxy -c -f /etc/haproxy/haproxy.cfg
# OpenRC
rc-service haproxy restart
rc-service haproxy status
rc-update add haproxy default
# systemd only where the unit is installed
systemctl status haproxy.service
systemctl restart haproxy.serviceFirewall, DNS, and proof
The public firewall belongs on the HAProxy edge. The backend firewall should accept the selected mail ports only from the HAProxy server network, not from every client network. Public MX records point to the public mail hostname; that hostname resolves to the public edge address. The backend's private address never appears in public MX, A, AAAA, or PTR records.
# Edge: expected public listeners.
ss -lntp '( sport = :25 or sport = :465 or sport = :587 or sport = :993 )'
# Backend: expected private listeners.
ss -lntp '( sport = :25 or sport = :465 or sport = :587 or sport = :993 )'
# From an independent network.
dig +short MX example.test
dig +short A mail.example.test
openssl s_client -connect mail.example.test:465 -servername mail.example.test
openssl s_client -starttls smtp -connect mail.example.test:587 -servername mail.example.test- Connection refused at the edge: HAProxy is not listening, its firewall denies the port, or the router/provider has not delivered the connection.
- HAProxy accepts but cannot connect: test 192.0.2.25 from the edge, then check backend routing and firewall policy.
- TLS certificate name is wrong: TLS terminates at MailDragon in this design, so inspect the MailDragon certificate—not an HAProxy HTTP certificate setting.
- Mail is accepted but remote delivery is poor: test the actual outbound public sender with the reverse-DNS chapter; inbound HAProxy success is a different path.