Modoboa Mail Server on ProxMox with Caddy2 and a single IP

1. The problem I’m having:

I have a 1G/1G fibre internet service with a single Static IP Address. This is supplied by a Fibre SFP connected to a TP-Link 1G ER7206 Safe Stream Router that is the DHCP host and firewall for my server cluster. The cluster is a ProxMox PVE 7.3 environment that allows me to spin up large numbers of Ubuntu 22.04.2 VM’s using QEMU. One of those VM’s is configured as a Caddy V2 2.6.4 reverse proxy serving all the other web VM’s out to thru the single static IP address to the net, by way of a NAT router structure in the ER7206. There is only one of these permitted for Ports 80:443

This makes it possible to serve out multiple NextCloud servers and WordPress servers on several domain roots through a large number of DNS A record pointers to the same IP address and direct the traffic to each dedicated LAN IP as required. Caddy routes the traffic to the proper server in every case and manages the TLS 3 Certs for each server perfectly. The Router is configured to send all traffic between ports 80 and 443 to Caddy to sort the A record references to the appropriate server as required.

This was flawless until I added a Modoboa E-Mail server with Ports 25 routed in against an A record and an MX record and Port 587 out for Mail transmission. The Management interface for the latest Modoboa server and for that matter most current email servers is an HTTPS web interface. I have a dedicated routing for 25 and 587 to the Modoboa server

Both systems want to manage the LetsEncrypt Cert process and the embedded NginX system on the Modoboa server and Caddy are in conflict. The Caddy router rules the 80:443 world but doesn’t handle email traffic.

Modoboa does all of the mail traffic but doesn’t know how to deal with Caddy, and the NginX components fail and are a show stopper. NginX expects to manage the Cert process for the Modoboa server and when it cant access the HTTPS ports and LetsEncrypt it all fails.

Is there a way to configure Caddy 2 to pass the traffic to a third party server directly without hindering the process?

Pass all HTTP/HTTPS traffic to and from a defined DNS A/MX entry to a defined Internal IP as an instruction defined in the Caddyfile? This would solve my problem Immediately.

2. Error messages and/or full log output:

nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/mail.kaslovia.ca/fullchain.pem": BIO_new_file() failed (SSL: error:80000002:system library::No such file or directory:calling fopen(/etc/letsencrypt/live/mail.kaslovia.ca/fullchain.pem, r) error:10000080:BIO routines::no such file)
nginx: configuration file /etc/nginx/nginx.conf test failed

3. Caddy version:

Caddy 2.6.4 on Ubuntu 22.04.2 Server is the router VM for all traffic to the cluster between Ports 80 and 443

4. How I installed and ran Caddy:

a. System environment:

I have a 1G/1G fibre internet service with a single Static IP Address. TP-Link 1G ER7206 Safe Stream Router that is the DHCP host and firewall for my LAN.
The cluster is a ProxMox PVE 7.3 environment that allows me to spin up large numbers of Ubuntu 22.04.2 VM’s using QEMU. One of those VM’s is configured as a Caddy V2 2.6.4 reverse proxy serving all the other web VM’s out to thru the single static IP address to the net, by way of a NAT router structure in the ER7206.

b. Command:

d. My complete Caddy config:

This is a segment of the functioning Caddyfile with the failing mail.kaslovia.ca server at the bottom

#COMXPERTISE NEXTCLOUD 25.0.3 SITE
cloud.comxpertise.ca {
    reverse_proxy 192.168.0.109:80
}

#COMXPERTISE ERP DEMO SITE
erp.comxpertise.ca {
   reverse_proxy 192.168.0.136:80
}

#COMXPERTISE WEBSITE SERVER 1
comxpertise.ca { 
    reverse_proxy 192.168.0.114:80
}

#COMXPERTISE WEBSITE SERVER 2
www.comxpertise.ca {
    reverse_proxy 192.168.0.118:80
}

#KASLOVIA.NET Test Site
kaslovia.net {
   reverse_proxy 192.168.0.128:80
}   

#BOLT BATTERY Test Site
bolt.comxpertise.ca {
    reverse_proxy 192.168.0.122:80
}

# Cloud.kaslovia.ca 
cloud.kaslovia.ca {
    reverse_proxy 192.168.0.133:80
}    

# Mailserver Web Interface
mail.kaslovia.ca {
    reverse_proxy 192.168.0.117:80
}

5. Links to relevant resources:

1 Like

What you can do is add a site to handle http:// traffic for the /.well-known/acme-challenge/* paths to proxy it to your upstream, so that it can handle ACME HTTP challenges.

http://mail.kaslovia.ca {
	route {
		reverse_proxy /.well-known/acme-challenge/* 192.168.0.117:80
		redir https://{host}{uri} 308
	}
}

mail.kaslovia.ca {
	reverse_proxy 192.168.0.117:80
}

It needs to be done this way to ensure you retain HTTP->HTTPS redirects for other request paths.


The other, albeit more complicated option, is to use Caddy’s certs for your mail server instead of having two ACME clients in play. This is tricky because Caddy renews the certs every 90 days and its storage location may differ depending on which ACME CA is used (could be Let’s Encrypt or ZeroSSL).

The most reliable way to handle it would be to set up an event subscriber in Caddy to handle cert issuance events which would let you run an command to copy the cert/key to somewhere your mail server could pick it up from. See Global options (Caddyfile) — Caddy Documentation

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.