├── docker-compose.yml ├── watcher.sh ├── Dockerfile ├── LICENSE └── README.md /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | certdumper: 5 | container_name: traefik_mailcow_cert_adapter 6 | image: jovobe/mailcow-traefik-acme-adapter:latest 7 | depends_on: 8 | - reverse-proxy 9 | restart: always 10 | volumes: 11 | - ./:/traefik:ro 12 | - /opt/mailcow-dockerized/data/assets/ssl:/ssl-share:rw 13 | - /var/run/docker.sock:/var/run/docker.sock:rw 14 | environment: 15 | - DOMAIN=your-domain-goes-here.tld 16 | -------------------------------------------------------------------------------- /watcher.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sleep 10s 4 | 5 | while true; do 6 | bash /dumpcerts.sh /traefik/acme.json /dump-target 7 | cp "/dump-target/private/${DOMAIN}.key" /ssl-share/key.pem 8 | cp "/dump-target/certs/${DOMAIN}.crt" /ssl-share/cert.pem 9 | rm -rf /dump-target/* 10 | postfix_c=$(docker ps -qaf name=postfix-mailcow) 11 | dovecot_c=$(docker ps -qaf name=dovecot-mailcow) 12 | nginx_c=$(docker ps -qaf name=nginx-mailcow) 13 | docker restart ${postfix_c} ${dovecot_c} ${nginx_c} 14 | inotifywait -e modify /traefik/acme.json 15 | done 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker:latest 2 | LABEL maintainer "Johan M. von Behren " 3 | 4 | # Installation 5 | RUN apk add --update \ 6 | && apk add --no-cache inotify-tools \ 7 | curl \ 8 | jq \ 9 | openssl \ 10 | util-linux \ 11 | bash \ 12 | tini \ 13 | && curl https://raw.githubusercontent.com/containous/traefik/v1.7/contrib/scripts/dumpcerts.sh -o /dumpcerts.sh \ 14 | && chmod +x /dumpcerts.sh \ 15 | && mkdir -p /dump-target /ssl-share 16 | 17 | COPY watcher.sh /watcher.sh 18 | 19 | RUN ["chmod", "+x", "/watcher.sh"] 20 | 21 | ENTRYPOINT ["/sbin/tini", "-g", "--"] 22 | 23 | # CMD /watcher.sh 2> /dev/null 24 | CMD /watcher.sh 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Johan M. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mailcow-traefik-acme-adapter 2 | An adapter to use [traefik](https://traefik.io/) generated acme certs in [mailcow](https://mailcow.email/). 3 | 4 | ## background 5 | traefik provides the possibility to automatically generate acme certs with [letsencrypt](https://letsencrypt.org/). These certs are stored in a proprietary format (located in a file called `acme.json`). Sadly mailcow does not offer a native solution to import certs from that format. This adapter is designed to fill that gap. It will look for new certs in the `acme.json`, export them and will send them to mailcow. 6 | 7 | ## how this adapter works 8 | 1. A watcher on the `acme.json` file is created 9 | 2. If the `acme.json` file changes, all including certs will be extracted inside the container 10 | 3. The cert and key from the configured domain will be copied to the configured location 11 | 4. All extracted certs inside the container are deleted 12 | 5. The relevant services from mailcow are restarted, to load the new certs 13 | 14 | ## setup with docker-compose 15 | Add the following service inside your `docker-compose.yml` and replace the config values: 16 | ```yaml 17 | certdumper: 18 | image: jovobe/mailcow-traefik-acme-adapter:latest 19 | container_name: traefik_mailcow_cert_adapter 20 | depends_on: 21 | # Here should be the name of your traefik service 22 | - name-of-traefik-service-goes-here 23 | # Here should be mailcow services that will be restarted after cert change 24 | - postfix-mailcow 25 | - dovecot-mailcow 26 | - nginx-mailcow 27 | restart: always 28 | volumes: 29 | # This volume mounts the traefik root folder into the container for access 30 | # to the `acme.json` file 31 | - /absolute/path/to/traefik-root:/traefik:ro 32 | 33 | # This volume mounts the mailcow ssl folder into the container. By default 34 | # this should be in your mailcow folder under "data/assets/ssl" 35 | - /absolute/path/to/mailcow-dockerized/data/assets/ssl:/ssl-share:rw 36 | 37 | # This volume mounts the docker socket into the container to enable docker 38 | # control from inside the container 39 | - /var/run/docker.sock:/var/run/docker.sock:rw 40 | environment: 41 | # This variable should contain the domain with which you are running 42 | # mailcow 43 | - DOMAIN=your-domain-goes-here.tld 44 | ``` 45 | --------------------------------------------------------------------------------