How to configure Automatic HTTPS with LetsEncript for different domains ( a.com & b.com), not subdomains

Hi!

I have a the next docker infrastructure:

  • Traefik v2.0 as a reverse proxy
  • Nginx as a web server
  • Wordpress multisite as an app with two sites: Site1 and Site2
  • 2 FQDN: domainA.com ($DOMAIN_A) and domainB.com ($DOMAIN_B)

All of this dockerized and deployed through docker-compose and I managed to route domainA to Site1, and domainB to Site2 working flawlessly

Now, for the HTTPS I did follow traefik's doc(v2) for automatic SSL with Let's Encrypt and achieved that Site1 was served as https://domainA (Site1)

The problem is that I'm trying to replicate the same configuration for for domainB (Site2), but It's been impossible

Is this even possible with automatic HTTPS?

All the related doc/post I find googling it are about a domains/subdomains with wildcards.

Anyone with the same problem?

Given the configuration below... Am I doing something wrong?

Thanks in advance

TRAEFIK

# Traefik container declared in docker-compose.yml
traefik:
    container_name: traefik
    image: "traefik:2.1"
    restart: "always"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik.yml:/etc/traefik/traefik.yml
    networks:
      - "traefik_network"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`traefik.$DOMAIN_A`)"
      - "traefik.http.routers.api.entrypoints=http"
      - "traefik.http.routers.api.service=api@internal"
  nginx:
    container_name: nginx
    image: nginx:1.15.12-alpine
    restart: unless-stopped
    expose:
      - 80
    volumes:     
      - ./nginx-conf:/etc/nginx/conf.d
    networks:
      - traefik_network
      - webserver_network
    labels:
      - "traefik.enable=true"

      - "traefik.http.routers.domain_a_no_secured.entrypoints=http"
      - "traefik.http.routers.domain_a_no_secured.rule=Host(`${DOMAIN_A}`)" 
      - "traefik.http.routers.domain_a_secured.entrypoints=https"
      - "traefik.http.routers.domain_a_secured.rule=Host(`${DOMAIN_A}`)" 
      - "traefik.http.routers.domain_a_secured.tls.certresolver=myresolver"
    
      - "traefik.http.routers.domain_b_no_secured.entrypoints=http"
      - "traefik.http.routers.domain_b_no_secured.rule=Host(`${DOMAIN_B}`)" 
      - "traefik.http.routers.domain_b_secured.entrypoints=https"
      - "traefik.http.routers.domain_b_secured.rule=Host(`${DOMAIN_B}`)" 
      - "traefik.http.routers.domain_b_secured.tls.certresolver=myresolver"

TRAEFIK STATIC CONFIGURATION FILE

#file traefik.yml
entryPoints:
  http:
    address: ":80"
  https:
    address: ":443"
providers:
  docker:
    exposedByDefault: false

certificatesResolvers:
 myresolver:
   acme:
     email: my.emaila@gmail.com
     storage: "/letsencrypt/acme.json"
     httpChallenge:
       entryPoint: http

NGINX

nginx:
    container_name: nginx
    image: nginx:1.15.12-alpine
    restart: unless-stopped
    expose:
      - 80
    volumes:     
      - ./nginx-conf:/etc/nginx/conf.d
    networks:
      - traefik_network
      - webserver_network
    labels:
      - "traefik.enable=true"

      - "traefik.http.routers.domain_a_no_secured.entrypoints=http"
      - "traefik.http.routers.domain_a_no_secured.rule=Host(`domaina.com`,`www.domaina.com`)" 
      - "traefik.http.routers.domain_a_secured.entrypoints=https"
      - "traefik.http.routers.domain_a_secured.rule=Host(`domaina.com`,`www.domaina.com`)" 
      - "traefik.http.routers.domain_a_secured.tls.certresolver=myresolver"
    
      - "traefik.http.routers.domain_b_no_secured.entrypoints=http"
      - "traefik.http.routers.domain_b_no_secured.rule=Host(`domainb.com`,`www.domainb.com`)" 
      - "traefik.http.routers.domain_b_secured.entrypoints=https"
      - "traefik.http.routers.domain_b_secured.rule=Host(`domainb.com`,`www.domainb.com`)" 
      - "traefik.http.routers.domain_b_secured.tls.certresolver=myresolver"

Thanks @einer

So just to be sure, with your solution, the traefik.yml static configuration file should look similar to this?

#file traefik.yml
entryPoints:
  http:
    address: ":80"
  https:
    address: ":443"
providers:
  docker:
    exposedByDefault: false

certificatesResolvers:
 domain_a-resolver:
   acme:
     email: my.email@gmail.com
     storage: "/letsencrypt/acme.json"
     httpChallenge:
       entryPoint: http
 domain_b-resolver:
   acme:
     email: my.email@gmail.com
     storage: "/letsencrypt/acme.json"
     httpChallenge:
       entryPoint: http

Right?

I'm giving it a try, and I let you know

One more question,
Did you put the same email? or has to be a different email per certificateResolver?

You don't need to use different certificates resolvers.

Hi @ldez

Don't understand what you mean

Could you provide an example of how to do it properly without using different certificate resolvers?

could you provide your logs?

Because the configuration from your first post seems good.

In my case the domains are hosted by different providers. I couldn't figure out how to specify two providers in the context of a single resolver but maybe I'm doing this wrong. Would be interesting to know what the correct way would be then (and how traefik would select the correct provider).

With the HTTP challenge or the TLS challenge, traefik don't need to know the DNS providers.

I see - at least one of my domains requires use of the dns-challenge. However, the OP clearly asked about http-challenges so I'll refrain from taking this thread further off-topic. Thanks for the clarification.

@ldez you hit bullseye with your suggestion:

I configured just one resolver for both domains, and take a deep look on the logs again .... and the problem was sitting there just waiting to be found:

level=error msg="Unable to obtain ACME certificate for domains \"domainb.com,www.domainb.com\": unable to generate a certificate for the domains [domainb.com www.domainb.com]: acme: Error -> One or more domains had a problem:\n[www.domainb.com] acme: error: 400 :: urn:ietf:params:acme:error:dns :: DNS problem: NXDOMAIN looking up A for www.domainb.com - check that a DNS record exists for this domain, url: \n" providerName=resolver01.acme routerName=domain_b_secured@docker rule="Host(`domainb.com`, `www.domainb.com`)"

Basically I had a DNS Record on my provider for http://domainb.com but not for WWW.domainb.com

I added it, and now I'm waiting for propagation to see if this was the culprit or not

I'll let you know

Thanks

Hi again!

My problem is solved!

I'm going to do a brief recap for "future hitchhikers":

  • Initial challenge was (see first post with config files)

    • Two different domains (domainA.com, domainB.com)
    • Configure automatic HTTPs through Traefik Routers / Middlewares with httpChallenge
    • Setup must work for both both www.domainX and domainX (without www)
  • Original problem encountered:

    • Using one resolver for both domains, put same configuration on both domains (A & B) but only one A was secured.
  • Causes and solutions:

    • Though I have to use different certificateResolvers

      • Wrong! Just one should be sufficient
      • After trying 2 different with no success I returned to one certificate Resolver
    • Though I have all DNS records correclty Setup

      • Wrong! I was missing a www.domainB DNS record
      • After adding the new DNS same problem was still there
    • Though I have exactly same configuration for both domains

      • Wrong! Label's order matters,
      • I copied the same labels (orders included) from domainA to domainB and Voila!

That was it!

Thanks @ldez and @einer for trying to help me on this