Files
docs/deployments/services/email/Proxmox Mail Gateway.md
T
nicole c6f37bd9d2
Automatic Documentation Deployment / Sync Docs to https://kb.bunny-lab.io (push) Successful in 7s
Update deployments/services/email/Proxmox Mail Gateway.md
2026-07-09 14:42:31 -06:00

15 KiB


tags:

  • Proxmox Mail Gateway
  • PMG
  • Mailcow
  • Email
  • SMTP
  • Gateway
  • Spam Filtering

Proxmox Mail Gateway Inbound Filtering for Mailcow

Purpose

This document defines the procedure for placing Proxmox Mail Gateway in front of an existing Mailcow server for inbound SMTP filtering.

PMG will handle inbound SMTP inspection before delivering accepted mail to Mailcow.

This document covers inbound SMTP filtering only.

It does not move:

  • Outbound SMTP delivery
  • DKIM signing
  • SMTP submission
  • IMAP
  • POP3
  • ManageSieve
  • Mailcow certificates
  • Mailcow web access
  • Roundcube access

Assumptions

Mailcow is already deployed and functional.

Mailcow already handles:

  • Mailbox hosting
  • User authentication
  • Webmail
  • Mailcow admin interface
  • IMAP
  • POP3
  • SMTP submission
  • Outbound delivery
  • DKIM signing
  • TLS certificates for mail.bunny-lab.io

Example environment:

Proxmox Mail Gateway: 192.168.3.15
Mailcow Server:        192.168.3.61
Mail Hostname:         mail.bunny-lab.io
Mail Domain:           bunny-lab.io
Firewall:              pfSense
Reverse Proxy:         Traefik

!!! warning "Inbound SMTP Only" Only move public inbound SMTP port 25 to PMG during this stage.

Do not move mail client ports, outbound relay behavior, DKIM signing, or Mailcow web access.

Architecture

Existing Mail Flow

Internet
  |
  v
pfSense WAN :25
  |
  v
Mailcow 192.168.3.61:25

Target Mail Flow

Internet
  |
  v
pfSense WAN :25
  |
  v
PMG 192.168.3.15:25
  |
  v
Mailcow 192.168.3.61:25

Final Service Ownership

PMG
  - Inbound SMTP on port 25
  - Spam filtering
  - Virus filtering
  - Tracking Center
  - Quarantine
  - Delivery of accepted inbound mail to Mailcow

Mailcow
  - Mailbox hosting
  - User authentication
  - Webmail
  - Mailcow admin interface
  - IMAP
  - POP3
  - SMTP submission
  - Outbound mail delivery
  - DKIM signing
  - TLS certificates for mail.bunny-lab.io

Traefik
  - Public HTTP
  - Public HTTPS
  - Mailcow / Roundcube frontend routing

DNS

Public DNS remains unchanged.

bunny-lab.io MX 10 mail.bunny-lab.io
mail.bunny-lab.io A <Public WAN IP>

The public DNS records continue pointing to the WAN IP.

The firewall determines where inbound SMTP is delivered internally.

pfSense WAN :25 -> PMG 192.168.3.15:25

!!! note "DNS Does Not Point to PMG Directly" The public MX and A records do not point to the internal PMG IP.

NAT controls the internal SMTP destination.

Firewall and NAT Design

Only public inbound SMTP changes.

Change this:

WAN :25 -> Mailcow 192.168.3.61:25

To this:

WAN :25 -> PMG 192.168.3.15:25

Leave Mailcow client access ports pointed directly at Mailcow.

WAN :465  -> Mailcow 192.168.3.61:465
WAN :587  -> Mailcow 192.168.3.61:587
WAN :993  -> Mailcow 192.168.3.61:993
WAN :995  -> Mailcow 192.168.3.61:995
WAN :110  -> Mailcow 192.168.3.61:110
WAN :143  -> Mailcow 192.168.3.61:143
WAN :4190 -> Mailcow 192.168.3.61:4190

Leave web traffic on the existing reverse proxy path.

WAN :80  -> Traefik :80
WAN :443 -> Traefik :443

!!! warning "Do Not Move Mail Client Ports to PMG" PMG is an SMTP gateway.

Do not forward IMAP, POP3, SMTPS, Submission, or ManageSieve ports to PMG.

Initial PMG Access

Access the PMG management interface.

https://192.168.3.15:8006

Use the root credentials configured during PMG installation.

!!! note "Certificate Warning" Browser certificate warnings are expected when accessing PMG by IP address unless a trusted certificate has already been configured for the management interface.

Pre-Cutover Connectivity Checks

Confirm PMG can reach Mailcow on SMTP port 25.

Run from the PMG shell:

# Confirm PMG can reach Mailcow SMTP
nc -vz 192.168.3.61 25

Expected result:

(UNKNOWN) [192.168.3.61] 25 (smtp) open

Reverse DNS warnings are not automatically failures.

inverse host lookup failed: Unknown host

If port 25 still reports as open, SMTP connectivity is working.

Confirm Mailcow presents an SMTP banner.

# Connect from PMG directly to Mailcow SMTP
nc 192.168.3.61 25

Expected banner:

220-mail.bunny-lab.io ESMTP Postcow
220 mail.bunny-lab.io ESMTP Postcow

Exit the SMTP session.

quit

!!! note "Mailcow SMTP Banner" Mailcow commonly identifies its SMTP service as Postcow.

That is expected.

PMG Mail Proxy Ports

In PMG, navigate to:

Configuration > Mail Proxy > Ports

Confirm:

External SMTP Port: 25

No outbound filtering is configured during this stage.

!!! note "Internal SMTP Port" PMG also has an internal SMTP port used for outbound filtering from an internal mail server.

This deployment does not use outbound PMG filtering yet.

PMG Relay Domains

In PMG, navigate to:

Configuration > Mail Proxy > Relay Domains

Add the accepted mail domain.

bunny-lab.io

This authorizes PMG to accept mail for the domain.

!!! warning "Relay Domains Are Required" If the domain is missing from Relay Domains, PMG may reject inbound mail because it is not configured as responsible for that domain.

PMG Default Relay

In PMG, navigate to:

Configuration > Mail Proxy > Relaying

Configure Mailcow as the default relay.

Default Relay:      192.168.3.61
Relay Port:         25
Relay Protocol:     smtp
Disable MX Lookup:  Yes
Smarthost:          none

Target internal relay path:

PMG 192.168.3.15
  |
  v
Mailcow 192.168.3.61:25

!!! note "Disable MX Lookup" PMG should deliver accepted inbound mail directly to the internal Mailcow server.

It should not perform public MX lookup for the local mail domain.

!!! note "No Smarthost" Leave Smarthost unset or set to none for inbound-only filtering.

Smarthost configuration is used for outbound relay behavior.

Mailcow Forwarding Host

Configure Mailcow to trust PMG as a forwarding host.

In Mailcow, navigate to:

System > Configuration Dropdown > Options > Forwarding Hosts Dropdown

Add the PMG IP address.

192.168.3.15

Set the forwarding-host spam filter option to:

Inactive

!!! note "Forwarding Host Behavior" After cutover, Mailcow sees PMG as the immediate SMTP source for inbound mail.

Trusting PMG allows Mailcow to interpret forwarded mail correctly.

!!! note "Spam Filtering Placement" PMG is the primary inbound spam and virus filtering system.

Leave Mailcow forwarding-host spam filtering inactive to avoid double-filtering messages already inspected by PMG.

Outbound Mail

Leave outbound mail unchanged.

Mailcow 192.168.3.61
  |
  v
Internet

Do not configure Mailcow to relay outbound mail through PMG during this stage.

Do not change:

Relayhost
Outbound firewall rules
DKIM signing
SPF record
DMARC record

!!! warning "Do Not Move DKIM" DKIM signing applies to outbound mail.

This document only moves inbound SMTP filtering.

Filtering Policy

Initial filtering ownership:

PMG     = primary inbound SMTP filtering, tracking, quarantine
Mailcow = mailbox hosting, authentication, webmail, mail client access

Avoid configuring both PMG and Mailcow to aggressively quarantine the same inbound mail stream.

!!! note "Keep Filtering Boring" PMG should own edge filtering first.

Mailcow should continue owning mailbox and client access behavior.

SMTP NAT Cutover

After PMG relay domains, PMG default relay, and Mailcow forwarding host settings are configured, update the pfSense NAT rule.

Change:

WAN :25 -> Mailcow 192.168.3.61:25

To:

WAN :25 -> PMG 192.168.3.15:25

Do not change the remaining Mailcow port forwards.

465  -> 192.168.3.61
587  -> 192.168.3.61
993  -> 192.168.3.61
995  -> 192.168.3.61
143  -> 192.168.3.61
110  -> 192.168.3.61
4190 -> 192.168.3.61

Do not change the Traefik web path.

80  -> Traefik
443 -> Traefik

!!! warning "Cutover Point" Changing WAN :25 is the actual inbound mail cutover.

External SMTP servers will begin connecting to PMG instead of Mailcow directly.

Validation

External SMTP Reachability

From an external system:

# Confirm public SMTP is reachable
nc -vz mail.bunny-lab.io 25

Alternative:

# Confirm public SMTP banner using telnet
telnet mail.bunny-lab.io 25

Expected result:

Port 25 open
SMTP banner returned by gateway

!!! note "Internal Testing Limitations" Internal tests may not represent public mail flow if NAT reflection or split-horizon DNS is involved.

Prefer external testing.

If external port testing is unavailable, send real mail from an outside provider.

Usable external sources:

Gmail
Outlook.com
iCloud
Proton Mail
Work mailbox hosted outside Mailcow

Inbound Delivery

Send an external message to a Mailcow-hosted mailbox.

Expected path:

External mailbox
  |
  v
mail.bunny-lab.io
  |
  v
pfSense WAN :25
  |
  v
PMG 192.168.3.15
  |
  v
Mailcow 192.168.3.61
  |
  v
User mailbox

Check PMG:

PMG > Tracking Center

Expected PMG status:

Status: accepted/delivered
Relay:  192.168.3.61[192.168.3.61]:25

Check Mailcow:

System > Logs

or review the relevant Mailcow Postfix and Dovecot logs.

Mail Client Access

Confirm normal mail client behavior remains unchanged.

Test:

IMAP receive
SMTP submission send
Mobile mail client access
Desktop mail client access
Webmail / Roundcube access
Mailcow UI access

Expected service paths:

IMAPS:      993 -> Mailcow
Submission: 587 -> Mailcow
SMTPS:      465 -> Mailcow
Web:        443 -> Traefik -> Mailcow

Confirm outbound mail still works by replying from a Mailcow-hosted mailbox to the external sender.

PMG Queues

Check PMG queues after test delivery.

PMG > Queues

Expected state:

Queue empty or near-empty after delivery

Queue status confirms PMG is not silently holding or deferring mail because of relay, DNS, or delivery errors.

Validation Checklist

  • Public MX record points to mail.bunny-lab.io
  • mail.bunny-lab.io resolves to the correct public WAN IP
  • DNS records are unchanged
  • PMG can reach Mailcow on 192.168.3.61:25
  • Mailcow SMTP banner is visible from PMG
  • PMG external SMTP port is 25
  • PMG has bunny-lab.io configured as a relay domain
  • PMG default relay points to 192.168.3.61
  • PMG relay port is 25
  • PMG relay protocol is smtp
  • PMG internal delivery has MX lookup disabled
  • PMG smarthost is unset or none
  • Mailcow trusts 192.168.3.15 as a forwarding host
  • Mailcow forwarding-host spam filter is Inactive
  • Firewall forwards WAN :25 to 192.168.3.15:25
  • Firewall still forwards mail client ports directly to Mailcow
  • Traefik still handles Mailcow / Roundcube web traffic
  • Inbound test mail appears in PMG Tracking Center
  • PMG Tracking Center shows accepted/delivered
  • PMG log shows delivery to 192.168.3.61:25
  • Inbound test mail is delivered to the Mailcow mailbox
  • PMG queue is empty after delivery
  • Mobile email client still works
  • Desktop email client still works
  • Webmail still works
  • Replying outbound from Mailcow still works
  • DKIM behavior is unchanged
  • SPF record is unchanged
  • DMARC record is unchanged
  • Outbound mail routing is unchanged

Troubleshooting

Inbound Mail Never Reaches PMG

Verify NAT.

WAN :25 -> 192.168.3.15:25

Verify inbound port 25 is not blocked by the ISP.

From an external system:

# Test public SMTP reachability
nc -vz mail.bunny-lab.io 25

If external testing is unavailable, send a real external test message and check:

PMG > Tracking Center

PMG Receives Mail but Does Not Deliver to Mailcow

Verify PMG relay settings.

Default Relay:      192.168.3.61
Relay Port:         25
Relay Protocol:     smtp
Disable MX Lookup:  Yes

Verify Mailcow SMTP is reachable from PMG.

# Test Mailcow SMTP from PMG
nc -vz 192.168.3.61 25

Confirm the Mailcow SMTP banner.

# Inspect Mailcow SMTP banner from PMG
nc 192.168.3.61 25

Expected banner:

220-mail.bunny-lab.io ESMTP Postcow
220 mail.bunny-lab.io ESMTP Postcow

PMG Shows Reverse DNS Warning for Mailcow

A warning like this is not automatically a failure:

inverse host lookup failed: Unknown host

If the connection still reports port 25 as open, SMTP connectivity is working.

Mailcow Rejects Mail from PMG

Verify Mailcow trusts PMG as a forwarding host.

192.168.3.15

Verify the recipient domain exists in Mailcow.

bunny-lab.io

Verify the recipient mailbox or alias exists in Mailcow.

Mail Clients Stop Working

Verify only inbound SMTP port 25 was moved to PMG.

These ports should still forward directly to Mailcow:

465
587
993
995
110
143
4190

Expected service ownership:

PMG     -> inbound SMTP gateway only
Mailcow -> client access and mailbox services

Roundcube or Mailcow Web UI Stops Working

Verify web traffic was not moved to PMG.

Expected path:

WAN :80  -> Traefik :80
WAN :443 -> Traefik :443

PMG should not replace Traefik for Mailcow or Roundcube web access.

Outbound Mail Stops Working

Outbound mail should not change during this deployment.

Verify no changes were made to:

Mailcow relayhost
Outbound firewall behavior
DKIM signing
SPF record
DMARC record
Public DNS records

Spam Filtering Behavior Is Confusing

Use one primary inbound filtering authority.

Recommended initial state:

PMG     = primary inbound edge spam filter
Mailcow = mailbox hosting and client access

Avoid dual aggressive quarantine policies until basic mail flow is stable.

Confirmed Final State

After Stage 1, the environment should operate as follows:

Inbound SMTP:
Internet -> pfSense WAN :25 -> PMG 192.168.3.15:25 -> Mailcow 192.168.3.61:25

Outbound SMTP:
Mailcow -> Internet

Mail Client Access:
Clients -> Mailcow

Webmail / Roundcube:
Internet -> Traefik -> Mailcow

The only public NAT behavior changed is:

WAN :25

Unchanged components:

DNS records
DKIM behavior
SPF record
DMARC record
Outbound mail routing
SMTP submission
IMAP
POP3
ManageSieve
Mailcow certificates
Traefik web routing
Mailcow / Roundcube web access

Deployment Status

This document completes Stage 1 of the PMG deployment.

Stage 1: Inbound filtering only
Stage 2: Optional outbound filtering

At the end of Stage 1:

PMG     = inbound SMTP filtering only
Mailcow = mailboxes, webmail, authenticated submission, certificates, DKIM, outbound delivery, user-facing mail services