Bloggings

Back

Mailcow with Nginx reverse proxy

2025-04-19

Using other web services with Mailcow

This is roughly what I did to have an Nginx web server on the same machine as dockerized Mailcow

  1. Change the default http and https ports (for example 8080 and 8443)
    and set SKIP_LETS_ENCRYPT=y in /opt/mailcow-dockerized/mailcow.conf
  2. Restart Mailcow by executing
    cd /opt/mailcow-dockerized;docker compose restart
  3. Make sure the DNS entry mail.xxxxx.com points to the server
  4. Create the folder /var/www/mail.xxxxx.com
  5. Create the writable folder /var/www/mail.xxxxx.com/.well-known
  6. Edit /etc/nginx/sites-available/mail.xxxxx.com
  7. server { listen 80; server_name mail.xxxxx.com; root /var/www/mail.xxxxx.com; index index.html; location / { try_files $uri $uri/ =404; } }
  8. ln -s /etc/nginx/sites-available/mail.xxxxx.com
    /etc/nginx/sites-enabled/mail.xxxxx.com
  9. systemctl restart nginx
  10. Run certbot -d mail.xxxxx.com to add the mail.xxxxx.com certificate
  11. Re-edit /etc/nginx/sites-available/mail.xxxxx.com to
    include port 443 and the certificates like so:
  12. server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name mail.xxxxx.com; charset UTF-8; access_log /var/log/nginx/access.mail.xxxxx.com; error_log /var/log/nginx/error.mail.xxxxx.com; include snippets/error_pages.conf; ssl_certificate /etc/letsencrypt/live/mail.xxxxx.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mail.xxxxx.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams-2048.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_buffering off; include /etc/nginx/proxy_params; } } server { listen 80; listen [::]:80; server_name mail.xxxxx.com; return 301 https://mail.xxxxx.com$request_uri; }
  13. Test with nginx -t, if all is well run sudo systemctl restart nginx
  14. Pointing your browser to https://mail.xxxxx.com should show you the Mailcow login page.
  15. You can remove the folder /var/www/mail.xxxxx.com

Problem

The problem is that Mailcow can no longer use port 80 to update it's ssl certificates that are used by postfix and dovecot. Instead certbot puts them in /etc/letsencrypt/live, so I wrote the following script that tests if the certificates there and in mailcow are the same, if not copies them over and reloads mailcow. It runs from crontab twice daily.

#!/bin/bash file1="/etc/letsencrypt/live/mail.xxxxx.com/fullchain.pem" file2="/opt/mailcow-dockerized/data/assets/ssl/cert.pem" if cmp "$file1" "$file2" | grep "differ"; then # copy ssl files cp /etc/letsencrypt/live/mail.xxxxx.com/fullchain.pem \ /opt/mailcow-dockerized/data/assets/ssl/cert.pem cp /etc/letsencrypt/live/mail.xxxxx.com/privkey.pem \ /opt/mailcow-dockerized/data/assets/ssl/key.pem # reload mailcow /usr/bin/docker exec $(/usr/bin/docker ps -qaf \ name=postfix-mailcow) postfix reload /usr/bin/docker exec $(/usr/bin/docker ps -qaf \ name=dovecot-mailcow) dovecot reload fi

 


ยง