Files
docs/deployments/services/email/Proxmox Mail Gateway.md
T
nicole 74d1ce6e5d
Automatic Documentation Deployment / Sync Docs to https://kb.bunny-lab.io (push) Successful in 7s
Add deployments/services/email/Proxmox Mail Gateway.md
2026-07-08 16:26:49 -06:00

18 KiB

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

Purpose

The purpose of this document is to illustrate how to place Proxmox Mail Gateway in front of an existing Mailcow email server for inbound SMTP filtering.

This document assumes that Mailcow has already been deployed using the companion Mailcow deployment document, and that Mailcow is already functional for mailbox hosting, webmail, SMTP submission, IMAP, POP3, and certificate handling.

!!! note "Assumptions" It is assumed that you are deploying Proxmox Mail Gateway into an existing homelab or small production environment where Mailcow is already deployed internally.

This document uses the following example IP addresses:

```text
Proxmox Mail Gateway: 192.168.3.15
Mailcow Server:        192.168.3.61
Mail Hostname:         mail.bunny-lab.io
Mail Domain:           bunny-lab.io
```

The intent is for Proxmox Mail Gateway to filter inbound SMTP traffic before delivering accepted mail to Mailcow.

Target Mail Flow

Before deploying Proxmox Mail Gateway, inbound SMTP traffic is sent directly to Mailcow:

Internet
  ↓
pfSense WAN :25
  ↓
Mailcow 192.168.3.61:25

After deploying Proxmox Mail Gateway, inbound SMTP traffic should be sent to PMG first:

Internet
  ↓
pfSense WAN :25
  ↓
Proxmox Mail Gateway 192.168.3.15:25
  ↓
Mailcow 192.168.3.61:25

!!! note "Inbound Filtering Only" This document only covers inbound SMTP filtering.

Outbound mail flow, DKIM signing, SMTP submission, IMAP, POP3, webmail, and Mailcow certificates should remain unchanged for now.

What PMG Will Handle

Proxmox Mail Gateway will handle:

Inbound SMTP on port 25
Spam filtering
Virus filtering
Mail gateway tracking
Quarantine handling
Delivery of accepted inbound mail to Mailcow

Mailcow will continue to handle:

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

!!! warning "Do Not Move Everything at Once" For the first deployment, only move inbound SMTP port 25 to Proxmox Mail Gateway.

Do not change outbound mail routing, DKIM signing, or authenticated submission until inbound mail flow has been confirmed stable.

Firewall / NAT Configuration

Update the firewall rules so that inbound SMTP traffic is sent to Proxmox Mail Gateway instead of directly to Mailcow.

Change this:

WAN :25 -> Mailcow 192.168.3.61:25

To this:

WAN :25 -> Proxmox Mail Gateway 192.168.3.15:25

Using the example IP addresses in this document:

WAN :25 -> 192.168.3.15:25

Leave the existing 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

Web traffic should remain on the existing reverse proxy path:

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

!!! warning "Do Not Move Mail Client Ports to PMG" Do not forward IMAP, POP3, SMTPS, Submission, or ManageSieve ports to Proxmox Mail Gateway.

Proxmox Mail Gateway should handle inbound SMTP gateway traffic. Mailcow should still handle mailbox access and authenticated mail client traffic.

DNS Configuration

Your public MX record should continue pointing to the public mail hostname.

Example:

bunny-lab.io MX 10 mail.bunny-lab.io

The mail hostname should continue pointing to the public WAN IP:

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

The firewall then controls where inbound SMTP traffic is delivered internally:

pfSense WAN :25 -> PMG 192.168.3.15:25

!!! note "DNS Does Not Need to Change" The public DNS records do not need to point directly to the internal PMG IP.

DNS should continue pointing to the public WAN IP. The firewall NAT rule determines whether port `25` goes to Mailcow or PMG.

Initial PMG Login

After installing Proxmox Mail Gateway, log into the web interface:

https://192.168.3.15:8006

Use the root credentials configured during installation.

!!! note "Certificate Warning" You may receive a browser certificate warning when accessing the PMG web interface by IP address. This is expected unless a trusted certificate has already been configured for the PMG management interface.

Confirm PMG Can Reach Mailcow

Before changing public NAT, confirm that PMG can reach Mailcow on SMTP port 25.

From the PMG shell, run:

nc -vz 192.168.3.61 25

A successful result should look similar to:

(UNKNOWN) [192.168.3.61] 25 (smtp) open

!!! note "Reverse DNS Warning" When testing with nc, you may see a message like this:

```text
inverse host lookup failed: Unknown host
```

This does not necessarily indicate a problem.

If the final result still shows port `25` as open, SMTP connectivity to Mailcow is working.

Confirm Mailcow's SMTP Banner

From the PMG shell, connect directly to Mailcow on SMTP port 25:

nc 192.168.3.61 25

You should receive an SMTP banner from Mailcow.

Example:

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

After confirming the banner, type:

quit

Then press Enter.

!!! note "Mailcow SMTP Banner" Mailcow commonly presents itself as Postcow.

This is expected and confirms that Mailcow's SMTP service is responding.

Configure PMG SMTP Ports

In the Proxmox Mail Gateway web interface, navigate to:

Configuration > Mail Proxy > Ports

Confirm the following value:

External SMTP Port: 25

For this inbound-only deployment, external mail servers should connect to PMG on port 25.

!!! note "Internal SMTP Port" Proxmox Mail Gateway also has an internal SMTP port, which is commonly used for outbound filtering from an internal mail server.

This document does not use outbound filtering yet, so do not change outbound mail routing at this stage.

Configure Relay Domains

In the Proxmox Mail Gateway web interface, navigate to:

Configuration > Mail Proxy

Then select the:

Relay Domains

tab.

!!! note "PMG Tab Layout" PMG may open the Mail Proxy section on the Relaying tab by default.

`Relay Domains` is a tab inside the Mail Proxy configuration area, not a separate left-side menu item.

Add the mail domain that PMG should accept mail for:

bunny-lab.io

This tells PMG that it is allowed to receive mail for the domain.

!!! warning "Do Not Skip Relay Domains" If the domain is not listed as a relay domain, PMG may reject inbound mail because it does not know that it is responsible for accepting mail for that domain.

Configure Mailcow as the Default Relay

In the Proxmox Mail Gateway web interface, navigate to:

Configuration > Mail Proxy > Relaying

Configure the default relay as follows:

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

This tells PMG to deliver accepted inbound mail directly to Mailcow.

PMG 192.168.3.15
  ↓
Mailcow 192.168.3.61:25

!!! note "Why Disable MX Lookup?" PMG should not perform a public MX lookup for your own domain when delivering mail internally.

Since Mailcow is the internal destination server, PMG should deliver directly to `192.168.3.61`.

!!! note "No Smarthost for Inbound-Only" For this inbound-only deployment, leave Smarthost unset or set to none.

Smarthost configuration is normally used for outbound relay behavior, which is not being configured in this document.

Configure Mailcow to Trust PMG

Because inbound mail will now arrive at Mailcow from PMG, Mailcow should be configured 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

When adding the PMG IP as a forwarding host, Mailcow may ask whether spam filtering should be enabled for that forwarding host.

For this design, set the spam filter option to:

Inactive

!!! note "Why This Matters" Without this step, Mailcow may see PMG as the immediate sender for inbound mail.

Trusting PMG helps Mailcow correctly interpret forwarded mail and reduces the chance of incorrect spam handling or delivery problems.

!!! note "Why Spam Filtering Is Inactive" PMG is intended to be the primary inbound spam and virus filtering system.

Setting the Mailcow forwarding-host spam filter to `Inactive` avoids double-filtering mail that PMG has already inspected.

Leave Outbound Mail Unchanged

For this first deployment, do not change outbound mail flow.

Mailcow should continue sending outbound mail the same way it did before PMG was introduced.

Mailcow 192.168.3.61
  ↓
Internet

Do not configure Mailcow to relay outbound mail through PMG yet.

!!! recommendation "Stage the Deployment" First, confirm that inbound mail filtering works correctly.

After inbound mail flow is stable, outbound filtering can be planned as a separate change.

Leave DKIM, SPF, and DMARC Unchanged

For this inbound-only deployment, leave the existing DKIM, SPF, and DMARC configuration unchanged.

Mailcow should continue handling outbound signing if it was already doing so.

DKIM:  Mailcow / existing configuration
SPF:   Existing public DNS record
DMARC: Existing public DNS record

!!! warning "Do Not Move DKIM Yet" Do not move DKIM signing to Proxmox Mail Gateway during the inbound-only phase.

DKIM applies to outbound mail, and this document is only moving inbound SMTP filtering.

Filtering Policy

With this design, PMG should be the primary inbound spam and virus filtering system.

Recommended behavior:

PMG = inbound SMTP filtering, tracking, quarantine
Mailcow = mailbox hosting, authentication, webmail, IMAP, POP3, SMTP submission

!!! recommendation "Simplify Filtering" Avoid making Mailcow and PMG both aggressively quarantine inbound mail at the same time.

Let PMG own the inbound edge filtering role so message tracking and quarantine behavior are easier to understand.

Change pfSense NAT for Inbound SMTP

After PMG and Mailcow have both been configured, update the pfSense NAT rule for inbound SMTP.

Change this:

WAN :25 -> Mailcow 192.168.3.61:25

To this:

WAN :25 -> PMG 192.168.3.15:25

Do not change the other Mailcow port forwards.

These should remain pointed at Mailcow:

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

Web traffic should remain on the existing Traefik path:

80  -> Traefik
443 -> Traefik

!!! warning "This Is the Actual Cutover" Changing the NAT target for WAN :25 is the point where external mail servers begin hitting PMG instead of Mailcow directly.

Make sure PMG relay domains, default relay, and Mailcow forwarding host settings are configured before applying this change.

Testing Inbound SMTP

From an external system, test that port 25 is reachable:

nc -vz mail.bunny-lab.io 25

Or:

telnet mail.bunny-lab.io 25

You should see that port 25 is open.

If using telnet, you should receive an SMTP banner from the gateway system.

!!! note "Testing From Inside the Network" Internal testing may not accurately represent public mail flow if NAT reflection or split-horizon DNS is involved.

Test from an external network when possible.

!!! note "If External Port Testing Is Not Available" If you do not have a reliable external system to test SMTP connectivity from, send a real test message from an outside mailbox instead.

Good test sources include:

```text
Gmail
Outlook.com
iCloud
Proton Mail
Work email hosted outside Mailcow
```

Then verify that the message appears in:

```text
PMG > Tracking Center
```

and that it is delivered into the Mailcow mailbox.

Testing Inbound Mail Delivery

Send a message from an external mailbox to a mailbox hosted on Mailcow.

Example:

External Gmail / Outlook / work mailbox / other provider
  ↓
mail.bunny-lab.io
  ↓
pfSense WAN :25
  ↓
PMG 192.168.3.15
  ↓
Mailcow 192.168.3.61
  ↓
User mailbox

Then review logs in both systems.

In Proxmox Mail Gateway, check:

Tracking Center

In Mailcow, check:

System > Logs

or review the relevant Postfix and Dovecot logs from the Mailcow interface.

A successful delivery should show something similar in PMG:

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

This confirms that PMG accepted the inbound message and relayed it to Mailcow.

Testing Mail Client Access

After the inbound SMTP cutover, confirm that normal mail clients still work.

Test at least one mobile client and one desktop client if available.

Confirm that you can still:

Receive mail over IMAP
Send mail using SMTP submission
Access webmail / Roundcube / Mailcow UI

The following service paths should remain unchanged:

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

!!! note "Outbound Mail Should Still Work" For this inbound-only deployment, outbound mail should still flow directly from Mailcow using the same behavior that existed before PMG was introduced.

A useful test is to reply from the Mailcow-hosted mailbox back to the original external sender.

Check PMG Queues

After sending and receiving test messages, confirm that PMG does not have messages stuck in queue.

In PMG, navigate to:

Queues

The queue should be empty or near-empty after the test message has delivered.

!!! note "Why Check the Queue?" Tracking Center confirms what happened to a specific message.

Queue status confirms PMG is not quietly holding or deferring messages because of a relay, DNS, or delivery issue.

Validation Checklist

Use the following checklist to confirm that PMG is correctly handling inbound mail flow:

  • Public MX record points to mail.bunny-lab.io
  • mail.bunny-lab.io resolves to the correct public WAN IP
  • PMG can reach Mailcow on 192.168.3.61:25
  • Mailcow SMTP banner is visible from PMG
  • Firewall forwards WAN :25 to 192.168.3.15:25
  • Firewall still forwards mail client ports directly to Mailcow
  • Traefik still handles web traffic for Mailcow / Roundcube
  • 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 set to 25
  • PMG has MX lookup disabled for internal delivery
  • Mailcow trusts PMG as a forwarding host
  • Mailcow forwarding-host spam filter is set to Inactive
  • Inbound test mail appears in PMG Tracking Center
  • PMG Tracking Center shows the test message as accepted/delivered
  • Expanded PMG log shows delivery to 192.168.3.61:25
  • Inbound test mail is delivered to the Mailcow mailbox
  • PMG mail queue is empty after delivery
  • Mobile email client still works
  • Desktop email client still works
  • Replying outbound from Mailcow still works
  • DNS records are unchanged
  • DKIM behavior is unchanged
  • SPF record is unchanged
  • DMARC record is unchanged
  • Outbound mail routing is unchanged

Troubleshooting

Inbound Mail Never Reaches PMG

Verify the firewall NAT rule:

WAN :25 -> 192.168.3.15:25

Also verify that the ISP is not blocking inbound port 25.

If external testing is unavailable, send a real test message from an outside mailbox and check:

PMG > Tracking Center

PMG Receives Mail but Does Not Deliver to Mailcow

Verify the PMG default relay configuration:

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

Also verify that Mailcow is listening on port 25 internally:

nc -vz 192.168.3.61 25

PMG Cannot Resolve Reverse DNS for Mailcow

When testing with nc, you may see:

inverse host lookup failed: Unknown host

This is not automatically a problem.

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

Mailcow Rejects Mail From PMG

Verify that Mailcow trusts PMG as a forwarding host:

192.168.3.15

Also verify that the recipient domain and mailbox exist in Mailcow.

Mail Clients Stop Working

Verify that only inbound SMTP port 25 was moved to PMG.

The following ports should still forward directly to Mailcow:

465
587
993
995
110
143
4190

Roundcube or Mailcow Web UI Stops Working

Verify that web traffic was not moved to PMG.

The existing web path should remain:

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

PMG should not replace Traefik for the Mailcow web frontend in this inbound-only deployment.

Outbound Mail Stops Working

Outbound mail should not be affected by this inbound-only deployment.

If outbound mail stops working, verify that no routing, relayhost, DKIM, SPF, DMARC, or outbound firewall changes were made.

Spam Filtering Seems Confusing

Decide which system is the primary inbound spam filter.

Recommended initial behavior:

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

Avoid making both systems aggressively quarantine inbound mail until basic mail flow is confirmed.

Confirmed Final State

After completing this deployment, the environment should behave 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 during this deployment was:

WAN :25

All other Mailcow service ports, DNS records, DKIM behavior, SPF, DMARC, outbound mail routing, and Traefik web routing were left unchanged.

Deployment Status

This document represents the first stage of a staged PMG deployment:

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

At the end of Stage 1, Proxmox Mail Gateway is responsible for inbound SMTP filtering only.

Mailcow continues to manage mailboxes, webmail, authenticated submission, certificates, DKIM signing, outbound delivery, and user-facing mail services.