Current situation

Mailcow and Traefik are installed as described in the excellent instructions of goneuland.de for mailcow. The only drawback of this guide is that after adding an email domain you still have to make manual adjustments in the docker-compose.override.yml file and mailcow has to be redeployed via docker-compose afterwards. The workaround is that an extra container generates the Traefik configuration from the Mailcow database and makes it available as an Http provider.

Http Provider

The dynamic Traefik configuration is generated by a small Flask webapp. The code can be found here: https://github.com/olqs/mailcow-traefik-cert-helper

Docker Compose and new container

In the file “docker-compose.override.yml” you have to change two things.

First, comment out all entries that configure SSL termination, or delete them. The Traefik router that does this is called nginx-mailcow-secure.

Services:
  nginx-mailcow:
    Labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx-mailcow.entrypoints=http"
      - "traefik.http.routers.nginx-mailcow.rule=HostRegexp('{host:(autodiscover|autoconfig|webmail|mail|email).+}')"
      - "traefik.http.middlewares.nginx-mailcow-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.nginx-mailcow.middlewares=nginx-mailcow-https-redirect"
# - "traefik.http.routers.nginx-mailcow-secure.entrypoints=https"
# - "traefik.http.routers.nginx-mailcow-secure.rule=Host('mail.worli.info')" ###### specify your FQDN here #####
# - "traefik.http.routers.nginx-mailcow-secure.tls=true"
# - "traefik.http.routers.nginx-mailcow-secure.tls.domains [0] .main=mail.worli.info" ###### adjust to your FQDN from above #####
# - "traefik.http.routers.nginx-mailcow-secure.tls.domains [0] .sans=imap.worli.info, smtp.worli.info, pop3.worli.info" ## Customize domain ##
# - "traefik.http.routers.nginx-mailcow-secure.service=nginx-mailcow"
# - "traefik.http.routers.nginx-mailcow-secure.tls.certresolver=http"
      - "traefik.http.services.nginx-mailcow.loadbalancer.server.port=80"
      - "traefik.docker.network=proxy"
    Networks:
      proxy:

Add the container that provides the configuration, the database password is taken with the configuration from the mailcow.conf:

  mailcow-traefik-cert-helper:
    image: olqs/mailcow-traefik-cert-helper
    container_name: mailcowdockerized_mailcow-traefik-cert-helper
    restart: unless-stopped
    Networks:
      proxy:
        Aliases:
          - mailcow-traefik-cert-helper
      mailcow-network:
        Aliases:
          - mailcow-traefik-cert-helper
    environment:
      - MYSQL_DATABASE_PASSWORD=${DBPASS}

Adjust static Traefik configuration

Extend the configuration point “providers” with the Http provider.

Provider:
  Docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: "./dynamic_conf.yml"
    watch: true
  http:
    endpoint: http://mailcowdockerized_mailcow-traefik-cert-helper:5000/

Certdumper Container

The certdumper container used in the instructions has the possibility to either extract all certificates generated in Traefik or a manually maintained list of certificates from the acme.json. In addition, mailcow must have a file “domains” in the certificate folders that are generated, which contains a space-separated list of all domains for which the certificate is valid.

The container image was adapted by me so that the “domains” file is created and you can now specify via an environment variable that only domains that start with a defined text are exported. For the code changes, I created a pull request, but at the time of article creation, that was not yet accepted. My customized source code can be found here: https://github.com/olqs/traefik-certs-dumper

  certdumper:
    image: olqs/traefik-certs-dumper
    container_name: mailcowdockerized_traefik_certdumper
    restart: unless-stopped
    network_mode: none
    command: --restart-containers mailcowdockerized_postfix-mailcow_1.mailcowdockerized_dovecot-mailcow_1
    Volumes:
      # mount the folder which contains Traefik's 'acme.json' file
      # in this case Traefik is started from its own docker-compose in .. /traefik
      - /data/traefik:/traefik:ro
      #mount mailcow's SSL folder
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/assets/ssl:/output:rw
    environment:
      # only change this, if you're using another domain for mailcow's web frontend compared to the standard config
      - DOMAIN_STARTS_WITH=mail

In the “certdumper” section of the “docker-compose.override.yml” adjust the points “image” and “environment”.

Restart Mailcow and Traefik

Finally, Traefik must now be restarted and Mailcow re-deployed. The commands must be adapted to the environment and are only exemplary.

user@host:~$sudo -i
host:/mailcow # docker-compose down && docker-compose up -d
host:/mailcow # docker stop traefik && docker start traefik

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.