Acquire TLS certificate for Poste io in Docker container

Hello!

I am using poste io as my mail server in Docker container. To acquire https LE certificate I have 3 options:

  • using poste io option to take a challenge (it throws in my case LEScript.ERROR: 500 { "type": "urn:ietf:params:acme:error:serverInternal", "detail": "Unable to update challenge", "status": 500 } or Verification timed out.
  • manually importing certificates (private, public parts of certificate and intermediate certificate) via Web GUI/
  • mapping keys to docker container from Traefik

Since I am beginner in Traefik (it's hard for me to figure out how to redirect properly /.well-known/ to fix problem with first option) I want to map certificates and keys to poste.io container, but after extracting certificates with this script I am getting only one certificate and one private key (I can't find public part of certificate).
openssl s_client says that poste io provides traefik's default cert (unsecure).

So, my question is: how can I pass LE TLS & HTTPS keys to my mail Docker container?

Here is my docker-compose config for poste io container.

version: "3"
services: 
  poste:
    image: "analogic/poste.io"
    container_name: "mail"
    restart: "always"
    volumes: 
      - "/etc/localtime:/etc/localtime:ro"
      - "/pathTo/mail/data:/data"
    hostname: "mail.domain.my"
    ports: 
        - '25:25' 
        - '465:465'  
        - '110:110'                                                                                                             
        - '143:143'                           
        - '587:587'            
        - '993:993'             
        - '995:995'  
        - '4190:4190'          
    environment:  
        - HTTPS=OFF
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.mail.rule=Host(`mail.domain.my`)"
      - "traefik.http.routers.mail.entrypoints=secure"
      - "traefik.http.routers.mail.tls=true"
      - "traefik.http.routers.mail.tls.certresolver=le"
      - "traefik.http.services.mail.loadbalancer.server.port=80"

    networks:
            - web
networks:
        web:
                external:
                        name: web

My traefik.yml:

#Define HTTP and HTTPS entrypoints
entryPoints:
  insecure:
    address: ":80"
  secure:
    address: ":443"

#Dynamic configuration will come from docker labels
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    network: "web"
    exposedByDefault: false 

#Enable acme with http file challenge
certificatesResolvers:
  le:
    acme:
      email: acme@domain.my
      storage: /acme.json
      httpChallenge:
        # used during the challenge
        entryPoint: insecure

api:
   dashboard: true

and docker-compose file for traefik container:

version: '3'
services:
  traefik:
    image: traefik:latest
    ports:
      - "80:80"
      - "443:443"
    networks:
            - web
    command:
            - "--certificatesresolvers.le.acme.tlschallenge=true"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /pathTo/traefik/traefik.yml:/etc/traefik/traefik.yaml:ro
      - /pathTo/traefik/acme.json:/acme.json
    labels:
      - "traefik.enable=true"
      
      # HTTP to HTTPS redirection
      - "traefik.http.routers.http_catchall.rule=HostRegexp(`{any:.+}`)"
      - "traefik.http.routers.http_catchall.entrypoints=insecure"
      - "traefik.http.routers.http_catchall.middlewares=https_redirect"
      - "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.https_redirect.redirectscheme.permanent=true"
      - "traefik.http.routers.traefik.rule=Host(`domain`)"
      - "traefik.http.routers.traefik.entrypoints=secure"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls.certresolver=le"
networks: 
  web: 
    external:
      name: "web" 

Thanks for any help.

I have figured out only what's wrong with first option. I don't have mapped /opt/www/.well-known to domain.my/.well-known so that's why I can't finish challenge.

So my questions now are:

  1. How can I redirect specific path (mail.domain.my/.well-known) to specified path in docker container (/opt/www/.well-known)?
  2. Where is stored public certificate in Traefik? I know how to bind private key and certificate, but I can't find public certificate.

Greetings @iriusturar and welcome.

To answer your questions, Traefik handles the intercept and processing of .well-known so long as it is configured to request certificates for that domain, which you've configured it (mail.domain.my) so this should "just work".

Certificates are stored in acme.json, and you can extract it from there once the challenge is processed through the Let's Encrypt API.

If you're having issues, please share the output of your debug logs. One thing worth noting is that you've established a global http->https redirect, while instructing the cert resolver to challenge against http - this is probably causing the issue. Consider changing the challenge to tls, or removing the redirect.

My browser says certificates provided to subdomain are fine (provided by LE, verified and valid), but when I am using openssl s_client -connect mail.domain.my it returns that:

CONNECTED(00000005)
depth=0 CN = TRAEFIK DEFAULT CERT
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = TRAEFIK DEFAULT CERT
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/CN=TRAEFIK DEFAULT CERT
   i:/CN=TRAEFIK DEFAULT CERT
---
Server certificate
-----BEGIN CERTIFICATE-----
[Removed for security reasons, as I am not sure if it should be visible for everyone]
-----END CERTIFICATE-----
subject=/CN=TRAEFIK DEFAULT CERT
issuer=/CN=TRAEFIK DEFAULT CERT
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 1438 bytes and written 289 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: [Removed as well]
    Session-ID-ctx: 
    Master-Key: [Removed too]
    TLS session ticket: [Removed too]

    Start Time: 1591709006
    Timeout   : 7200 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---

I am not sure why that certificate is present instead of LE, but I think that may impact on getting my mail messages to spam.

There is an option in Poste to map certificates as I said previously to container, but Traefik has only certificate and private key in acme.json and I need to that public key too. Do You know where can I get it?

This is likely because you're only handling the load balancing of the web (http) port, you'll need to proxy all the mail server ports and use HostSNI to ensure the non-http requests are routed. This is completely non-trivial, mail servers are complex beasts.

Anyways, the easiest path forward is extracting what you need from acme.json, which includes all you need to extract the public key from the existing certs. openssl - How to save public key from a certificate in .pem format - Stack Overflow

Sorry, I did a mistake in listing required files for mail server. Now, I am pasting required files from readme:

  • ca.crt
    Certification authority public keys (or "intermediate certificate"). There is
    "-----BEGIN CERTIFICATE-----" once or more times.

  • server.crt
    Your public key generated by your CA. It should have one "-----BEGIN CERTIFICATE-----"
    in it

  • server.key
    Your private key, it should have "-----BEGIN RSA PRIVATE KEY-----" in it

I don't have ca.crt file. Sorry for inconvenience and huge thanks for helping me with that.

ca.crt is stored in the json file -- see: https://stackoverflow.com/questions/47218529/store-traefik-lets-encrypt-certificates-not-as-json

as for server.crt, you should be able to generate that from the link I mentioned in the previous response. It's also worth noting that I've not done this before so I could be wrong, but it should be possible. If someone on else in the community they may be able to fill in the blanks. In any event, please let us know if you're able to generate the files you need.

_kc

1 Like