简体   繁体   English

Traefik Proxy 后面的 Mailcow 设置导致 https 证书错误

[英]Mailcow setup behind Traefik Proxy causes https certificate error

I am trying to setup the mailcow installation behind Traefik proxy.我正在尝试在Traefik代理后面设置mailcow安装。 Apparently, Traefik proxy is not able to recognize the nginx-mailcow container in its network and hence does not create a certificate for https connection.显然,Traefik 代理无法识别其网络中的nginx-mailcow容器,因此不会为https连接创建证书。 so when I bring up the mailcow service using docker-compose up , I can access the mailcow services but on insecure connection (http) and browser warns that connection is not secure.因此,当我使用docker-compose up mailcow 服务时,我可以访问 mailcow 服务,但连接不安全(http)并且浏览器警告连接不安全。

When I check my acme.json file from Traefik : I can not find any certificate related to mailcow domain ie, mail.tld.com there.当我从Traefik检查我的acme.json文件时:我找不到任何与 mailcow 域相关的证书,即那里的mail.tld.com

I have the following setup:我有以下设置:

Logs of affected containers:受影响容器的日志:

Traefik Container Logs: Traefik容器日志:

time="2020-04-18T13:40:35+02:00" level=error msg="accept tcp [::]:80: use of closed network connection" entryPointName=http
time="2020-04-18T13:40:35+02:00" level=error msg="accept tcp [::]:443: use of closed network connection" entryPointName=https
time="2020-04-18T13:40:35+02:00" level=error msg="close tcp [::]:80: use of closed network connection" entryPointName=http
time="2020-04-18T13:40:35+02:00" level=error msg="close tcp [::]:443: use of closed network connection" entryPointName=https
time="2020-04-18T13:40:35+02:00" level=error msg="Cannot connect to docker server context canceled" providerName=docker
time="2020-04-18T13:40:37+02:00" level=info msg="Configuration loaded from file: /traefik.yml"
time="2020-04-19T00:27:31+02:00" level=error msg="service \"nginx-mailcow\" error: unable to find the IP address for the container \"/mailcowdockerized_nginx-mailcow_1\": the server is ignored" container=nginx-mailcow-mailcowdockerized-5f3a25b43c42fd85df675d2d9682b6053501844c2cfe15b7802cf918df138025 providerName=docker
time="2020-04-19T00:33:32+02:00" level=error msg="service \"nginx-mailcow\" error: unable to find the IP address for the container \"/mailcowdockerized_nginx-mailcow_1\": the server is ignored" providerName=docker container=nginx-mailcow-mailcowdockerized-f4d41ee79e382b413e04b039b5fc91e1c6217c78740245c8666373fe2d6a9b23
2020/04/19 00:39:44 reverseproxy.go:445: httputil: ReverseProxy read error during body copy: unexpected EOF
time="2020-04-19T00:50:32+02:00" level=error msg="service \"nginx-mailcow\" error: unable to find the IP address for the container \"/mailcowdockerized_nginx-mailcow_1\": the server is ignored" providerName=docker container=nginx-mailcow-mailcowdockerized-915f80e492c2c22917d0af81add1dde15577173c82cc928b0b6101c8a260adc5
time="2020-04-19T00:58:43+02:00" level=error msg="service \"nginx-mailcow\" error: unable to find the IP address for the container \"/mailcowdockerized_nginx-mailcow_1\": the server is ignored" container=nginx-mailcow-mailcowdockerized-852985c4efc48559ca3568b1829e31b46eb9f968fc328a8566e3dc6ab6f1af21 providerName=docker
time="2020-04-19T02:02:39+02:00" level=error msg="Error while Peeking first byte: read tcp 172.21.0.2:80->208.91.109.90:55153: read: connection reset by peer"
time="2020-04-19T08:11:32+02:00" level=error msg="service \"nginx-mailcow\" error: unable to find the IP address for the container \"/mailcowdockerized_nginx-mailcow_1\": the server is ignored" providerName=docker container=nginx-mailcow-mailcowdockerized-840ef4db0ccc9fa84038dc7a52133779926dba4c51554516c17404ede80a2c01

The contents of Traefik docker-compose.yml : Traefik docker-compose.yml的内容:

version: '3'

services:
  traefik:
    image: traefik:v2.1
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    ports:
      - 80:80
      - 443:443
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/traefik.yml:ro
      - ./data/acme.json:/acme.json
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=http"
      - "traefik.http.routers.traefik.rule=Host(`traefik.tld.com`)"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=admin:pass"
      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
      - "traefik.http.routers.traefik-secure.entrypoints=https"
      - "traefik.http.routers.traefik-secure.rule=Host(`traefik.tld.com`)"
      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.tls=true"
      - "traefik.http.routers.traefik-secure.tls.certresolver=http"
      - "traefik.http.routers.traefik-secure.service=api@internal"

networks:
  proxy:
    external: true

Contents of traefik.yml (I used.yml instead of.toml) traefik.yml 的内容(我用.yml 代替.toml)

api:
    dashboard: true

entryPoints:
    http:
        address: ":80"
    https:
        address: ":443"

providers:
    docker:
        endpoint: "unix:///var/run/docker.sock"
        exposedByDefault: false

certificatesResolvers:
    http:
        acme:
            email: myemail@tld.com
            storage: acme.json
            httpChallenge:
                entryPoint: http

Just to point out, with this setup of Traefik , certificates are generated automatically for other services like gitlab .需要指出的是,通过Traefik的这种设置,会为其他服务(如gitlab )自动生成证书。 For that, I just correctly labelled the gitlab service and assigned the Traefik network to it and Traefik service would recognize the gitlab service and generates the certificate in acme.json but sadly not for nginx-mailcow .为此,我只是正确地标记了gitlab服务并将Traefik网络分配给它, Traefik服务将识别gitlab服务并在acme.json nginx-mailcow中生成证书。

The contents of my docker-compose.override.yml for mailcow:我的docker-compose.override.yml的内容为 mailcow:

version: '2.1'

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.tld.com`)" 
      - "traefik.http.routers.nginx-mailcow-secure.tls=true"
      - "traefik.http.routers.nginx-mailcow-secure.service=nginx-mailcow"
      - "traefik.http.services.nginx-mailcow.loadbalancer.server.port=80"
      - "traefik.docker.network=proxy"
    networks:
      proxy:

  certdumper:
      image: humenius/traefik-certs-dumper
      container_name: traefik_certdumper
      network_mode: none
      command: --restart-containers mailcowdockerized_postfix-mailcow_1,mailcowdockerized_dovecot-mailcow_1
      volumes:
        - /opt/containers/traefik/data:/traefik:ro
        - /var/run/docker.sock:/var/run/docker.sock:ro
        - ./data/assets/ssl:/output:rw
      environment:
        - DOMAIN=tld.com 

networks:
  proxy:
    external: true

The contents of my nginx-mailcow service in docker-compose.yml我的nginx-mailcow服务在docker-compose.yml中的内容

version: '2.1'
services:
     ...
    nginx-mailcow:
      depends_on:
        - sogo-mailcow
        - php-fpm-mailcow
        - redis-mailcow
      image: nginx:mainline-alpine
      dns:
        - ${IPV4_NETWORK:-172.22.1}.254
      command: /bin/sh -c "envsubst < /etc/nginx/conf.d/templates/listen_plain.template > /etc/nginx/conf.d/listen_plain.active &&
        envsubst < /etc/nginx/conf.d/templates/listen_ssl.template > /etc/nginx/conf.d/listen_ssl.active &&
        envsubst < /etc/nginx/conf.d/templates/server_name.template > /etc/nginx/conf.d/server_name.active &&
        envsubst < /etc/nginx/conf.d/templates/sogo.template > /etc/nginx/conf.d/sogo.active &&
        envsubst < /etc/nginx/conf.d/templates/sogo_eas.template > /etc/nginx/conf.d/sogo_eas.active &&
        . /etc/nginx/conf.d/templates/sogo.auth_request.template.sh > /etc/nginx/conf.d/sogo_proxy_auth.active &&
        . /etc/nginx/conf.d/templates/sites.template.sh > /etc/nginx/conf.d/sites.active &&
        nginx -qt &&
        until ping phpfpm -c1 > /dev/null; do sleep 1; done &&
        until ping sogo -c1 > /dev/null; do sleep 1; done &&
        until ping redis -c1 > /dev/null; do sleep 1; done &&
        until ping rspamd -c1 > /dev/null; do sleep 1; done &&
        exec nginx -g 'daemon off;'"
      environment:
        - HTTPS_PORT=${HTTPS_PORT:-443}
        - HTTP_PORT=${HTTP_PORT:-80}
        - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
        - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
        - TZ=${TZ}
        - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
      volumes:
        - ./data/web:/web:ro
        - ./data/conf/rspamd/dynmaps:/dynmaps:ro
        - ./data/assets/ssl/:/etc/ssl/mail/:ro
        - ./data/conf/nginx/:/etc/nginx/conf.d/:rw
        - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro
        - sogo-web-vol-1:/usr/lib/GNUstep/SOGo/
      ports:
        - "${HTTPS_BIND:-0.0.0.0}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}"
        - "${HTTP_BIND:-0.0.0.0}:${HTTP_PORT:-80}:${HTTP_PORT:-80}"
      restart: always
      networks:
        mailcow-network:
          aliases:
            - nginx

....

I have also tried comment out ports in nginx-mailcow service but the problem persists.我也尝试在nginx-mailcow服务中注释掉端口,但问题仍然存在。 My current mailcow.conf changes:我当前的mailcow.conf更改:

HTTP_BIND=127.0.0.1
HTTP_PORT=8080
HTTPS_BIND=127.0.0.1
HTTPS_PORT=8443

SKIP_LETS_ENCRYPT=y
SKIP_CLAMD=y

Reproduction of said bug:重现所述错误:

I setup the traefik proxy first (see contents above).我首先设置了 traefik 代理(参见上面的内容)。 Once the Traefik is up and running (I also tested for other services and it works fine in generating a certificate).一旦 Traefik 启动并运行(我还测试了其他服务,它可以正常生成证书)。 Now first I cloned the mailcow repository.现在首先我克隆了 mailcow 存储库。 Then I run ./generate_config.sh to generate mailcow.conf file.然后我运行./generate_config.sh来生成mailcow.conf文件。 As input to generate_config.sh I provide my domain name ie, mail.tld.com作为 generate_config.sh 的输入,我提供了我的域名,即mail.tld.com

Then I comment out the ports in docker-compose.yml file because I do not want to use port 80 and 443 for nginx-mailcow as these ports are already being used by Traefik .然后我注释掉docker-compose.yml文件中的端口,因为我不想为nginx-mailcow使用端口 80 和 443,因为Traefik已经在使用这些端口。

Then I create a docker-compose.override.yml (see contents above) to add additional configs to nginx-mailcow service (traefik labels, traefik network).然后我创建了一个docker-compose.override.yml (见上面的内容)来添加额外的配置到nginx-mailcow服务(traefik 标签,traefik 网络)。 The override file also contain the certdumper service which would copy https certificate from acme.json to mailcow services.覆盖文件还包含certdumper服务,该服务会将 https 证书从 acme.json 复制到 mailcow 服务。

Then, I change the following two variables in mailcow.conf :然后,我在mailcow.conf中更改以下两个变量:

SKIP_LETS_ENCRYPT=y
SKIP_CLAMD=y

Finally, I run the mailcow using docker-compose up -d .最后,我使用docker-compose up -d运行mailcow In browser, if check https://mail.tld.com => It warns that connection is insecure.在浏览器中,如果检查https://mail.tld.com => 它警告连接不安全。 If I check acme.json .如果我检查acme.json I find no certificate for mail.tld.com .我找不到mail.tld.com的证书。

System information:系统信息:

+-------------------------------------------------+---------------------------------+
|                    Question                     |             Answer              |
+-------------------------------------------------+---------------------------------+
| My operating system                             | linux x86_64 Ubuntu 18.04.1 LTS |
| Is Apparmor, SELinux or similar active?         | No                              |
| Virtualization technlogy                        | KVM                             |
| Server/VM specifications (Memory, CPU Cores)    | 16GB, 6 cores                   |
| Docker Version (docker version)                 | 19.03.8                         |
| Docker-Compose Version (docker-compose version) | 1.25.4, build 8d51620a          |
| Reverse proxy (custom solution)                 | Traefik                         |
+-------------------------------------------------+---------------------------------+

If you need more information, I would be happy to provide.如果您需要更多信息,我很乐意提供。 Any help will be much appreciated.任何帮助都感激不尽。 Thank you.谢谢你。

Finally I was able to solve the problem after investing many hours in reading the Traefik Documentation.在投入大量时间阅读 Traefik 文档后,我终于解决了这个问题。 I made tiny mistake in assigning proxy labels to the nginx-mailcow service.我在为 nginx-mailcow 服务分配代理标签时犯了一个小错误。 The solution is below.解决方案如下。

I forgot to mention certificate resolver and I had to expose the port which I now added as follows:我忘了提到证书解析器,我不得不公开我现在添加的端口,如下所示:

services:
  nginx-mailcow:
    expose:
      - "8080"
    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.example.com`)" 
      - "traefik.http.routers.nginx-mailcow-secure.tls=true"
      - "traefik.http.routers.nginx-mailcow-secure.certresolver=http"
      - "traefik.http.routers.nginx-mailcow-secure.service=nginx-mailcow"
      - "traefik.http.services.nginx-mailcow.loadbalancer.server.port=8080"
      - "traefik.docker.network=proxy"
    networks:
      proxy:

  certdumper:
    image: humenius/traefik-certs-dumper
    container_name: traefik_certdumper
    network_mode: none
    command: --restart-containers mailcowdockerized_postfix-mailcow_1,mailcowdockerized_dovecot-mailcow_1
    volumes:
      - <path_to_acme.json_file_dir>:/traefik:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/assets/ssl:/output:rw
    environment:
      - DOMAIN=example.com 

For people who are setting up for the first time, I had to make some additional changes beforehand.对于第一次设置的人,我必须事先进行一些额外的更改。

  1. Firstly, when you run generate.sh file then in mailcow.conf file you need to make following changes:首先,当您运行 generate.sh 文件时,您需要在 mailcow.conf 文件中进行以下更改:

    HTTP_PORT=8080 HTTP_PORT=8080
    HTTP_BIND=127.0.0.1 HTTP_BIND=127.0.0.1

    HTTPS_PORT=8443 HTTPS_PORT=8443
    HTTPS_BIND=127.0.0.1 HTTPS_BIND=127.0.0.1

    SKIP_LETS_ENCRYPT=y SKIP_LETS_ENCRYPT=y
    SKIP_CLAMD=y SKIP_CLAMD=y

    We make these changes as we can not run mailcow nginx on the same ports as traefik.我们进行这些更改是因为我们无法在与 traefik 相同的端口上运行 mailcow nginx。

  2. Now as nginx-mailcow will be running on 8080 or 8443 so we need to expose one of these ports so traefik can talk to mailcow-nginx service.现在由于 nginx-mailcow 将在 8080 或 8443 上运行,所以我们需要公开这些端口之一,以便 traefik 可以与 mailcow-nginx 服务通信。 I already exposed port 8080 in the override compose file)我已经在覆盖撰写文件中公开了端口 8080)

  3. You also need to also adapt your loadbalancer port from 80 to 8080. (As I configured above)您还需要将负载均衡器端口从 80 调整为 8080。(正如我在上面配置的)
  4. You need to also tell which certificate resolver should it use.您还需要告诉它应该使用哪个证书解析器。 So you need to add this line in labels (I made this as well above in override config)所以你需要在标签中添加这一行(我在上面的覆盖配置中也做了这个)
  5. You have to make sure that your acme.json file (certificate file is accessible by certdumper service).您必须确保您的 acme.json 文件(证书文件可通过 certdumper 服务访问)。 So replace to actual path of acme.json directory path所以替换为acme.json目录路径的实际路径

I hope this helps.我希望这有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM