Software Engineering Blog

Tipps und Tricks aus dem Leben eines Systemadministrators.

Mailcow + Reverse-Proxy + Letsencrypt


This article is about how to use the great mailcow software behind a reverse-proxy with public certificates from the Let's Encrypt CA.

Problem Statement

For various services (smpt, imap, http) mailcow requires valid x509 certificates. To get these certificates, they integrated certbot to automatically retive them form letsencrypt. However, this requires mailcow's HTTP service to listen on IP:80/IP:443. This is not possible if another webserver (commonly nginx) is already listening on this port.

Proxy Mailcow's UI

In mailcow's configuration set the HTTPS port to a free one (e.g. 8443), bind to localhost and use a reverse proxy to map your mail-domain on port 443 to 8443 inside the container. Additionally, the acme-client has to be disabled by setting SKIP_LETS_ENCRYPT=y in mailcow.conf.

As the acme-client (letsencrypt) only supports validation on port 80, you have to run it outside the mailcow docker containers and exclude the path from the reverse-proxying. A sample nginx-config for this setup might look like this:


# url for letsencrypt
location ^~ /.well-known/acme-challenge/ {
  allow all;
  default_type "text/plain";
  # Path can be used for cert-validation on all domains
  root /www/html/sites/letsencrypt;


server {
    listen 80;
    listen [::]:80;
    server_name mx.<your-domain>.de;

    include /etc/nginx/letsencrypt_path;

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name mx.<your-domain>.de;

  ssl_certificate     /etc/letsencrypt/live/mx.<your-domain>.de/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/mx.<your-domain>.de/privkey.pem;

  include /etc/nginx/ssl.conf;

  location / {
    proxy_buffering off;

    include /etc/nginx/proxy_params;

The ssl.conf and proxy_params scripts contain some generic configuration, suitabel for most of my sites.

Copy Certificates to Mailcow

Given the setup above, you can already get a certificate for your domain. However, letsencrypt always places the certificate to the folder /etc/letsencrypt/live/. To use it inside mailcow, you have to copy it to the following location: <mailcow>/data/assets/ssl/ and name it cert.pem for the certificate and key.pem for the key.

Automate Renewal and Copy

As the certificates are usually issued for a short period (~three-month), this steps should be automated. Thereto, the post-hook of the certbot come in handy:

sudo certbot certonly --webroot -w /www/html/sites/letsencrypt -d mx.<your-domain>.de \
--post-hook "cp /etc/letsencrypt/live/mx.<your-domain>.de/fullchain.pem /opt/mailcow-dockerized/data/assets/ssl/cert.pem \
&& cp /etc/letsencrypt/live/mx.<your-domain>.de/privkey.pem /opt/mailcow-dockerized/data/assets/ssl/key.pem \
&& docker restart mailcowdockerized_postfix-mailcow_1"

This does the following:

  1. Obtain a certificate
  2. Copy cert + key to mailcow
  3. Restart mailcow-postfix docker container



Einen Kommentar schreiben

Bitte rechnen Sie 8 plus 3.

Ähnliche Beiträge


We reverse engineer a Dotnet Monitor in Windbg to see how it is internally implemented.


As SSDs are getting cheaper, low HDD / SSD ratios of 10/1 or better become an option. This article describes how to tune bcache for this scenario from an empirical perspective.