Secondary domain(s) with redirect to primary domain

Hi there,
I have a docker-compose project with the following configuration for my service providing http at port 8080:

- "traefik.enable=true"
- "traefik.http.routers.proxy-secured.rule=Host(`host.domain.com`)"
- "traefik.http.routers.proxy-secured.entrypoints=websecure"
- "traefik.http.services.proxy-secured.loadbalancer.server.port=8080"
- "traefik.http.routers.proxy-secured.tls.certresolver=myhttpchallenge"
- "traefik.http.routers.web.rule=Host(`host.domain.com`)"
- "traefik.http.routers.web.entrypoints=web"
- "traefik.http.middlewares.redirect-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect-https.redirectscheme.permanent=true"
- "traefik.http.routers.web.middlewares=redirect-https@docker"

For my traefik v2 service I use the following config:

- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.myhttpchallenge.acme.email=my@email.com"
- "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"

That makes my http based service available via HTTPs / LetsEncrypt on the domain host.domain.com and HTTP-requests are automatically redirected to HTTPs which is exactly what I want.

I need to extend this setup to listen on an additional domain-name, let's assume it is secondary.domain.com. I also want HTTPs encryption via LetsEncrypt for this host name but I want to redirect everything targeting this domain to host.domain.com no matter if the request comes in over http (80) or https (443).
Is this possible?
If so, how can I achieve that?

With kind regards

Andreas

Hello,

I'm not sure about you want to do but:

version: '3.7'

services:
  web:
    image: traefik:v2.1.4
    command:
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.myhttpchallenge.acme.httpchallenge=true
      - --certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web
      - --certificatesresolvers.myhttpchallenge.acme.email=my@email.com
      - --certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt/:/letsencrypt/acme.json
    labels:
      traefik.enable: true

      traefik.http.routers.http-catchall.rule: hostregexp(`{host:.+}`)
      traefik.http.routers.http-catchall.entrypoints: web
      traefik.http.routers.http-catchall.middlewares: redirect-to-https@docker

      traefik.http.middlewares.redirect-to-https.redirectscheme.scheme: https

  whoami:
    image: containous/whoami
    labels:
      traefik.enable: true
      traefik.http.routers.proxy-secured.rule: Host(`host.domain.com`, `secondary.domain.com`)
      traefik.http.routers.proxy-secured.entrypoints: websecure
      traefik.http.routers.proxy-secured.tls.certresolver: myhttpchallenge

      traefik.http.services.proxy-secured.loadbalancer.server.port: 8080

Hi @ldez, thank you for your reply,
I will check your config example in my actual setup. However there are two things that from my understanding do not match my requirements:

=> Your http-catchall router would react on any HTTP request, correct? What I need instead is to listen only for the hostnames host.domain.com (A) and secondary.domain.com (B).

=> With the parameter

from your example the service would be available at both domain names with HTTPs which is fine so far. However I can't see that a request on B would be redirected to A which is a requirement in my case.

I apologize in case I did not understand your solution correct.
My requirements are in the last paragraph of my initial post. In other words:

  • I want my service to be available at A with automatic redirect from http to https (working).
  • I want all requests at B to be redirected to A for http and https.

With kind regards

Andreas

version: '3.7'

services:
  web:
    image: traefik:v2.1.4
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.myhttpchallenge.acme.httpchallenge=true
      - --certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web
      - --certificatesresolvers.myhttpchallenge.acme.email=my@email.com
      - --certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt/:/letsencrypt/acme.json

  whoami:
    image: containous/whoami
    labels:
      traefik.enable: true
      
      traefik.http.routers.proxy-secured.rule: Host(`host.domain.com`)
      traefik.http.routers.proxy-secured.entrypoints: websecure
      traefik.http.routers.proxy-secured.tls.certresolver: myhttpchallenge
      
      traefik.http.routers.rweb.rule: Host(`host.domain.com`)
      traefik.http.routers.rweb.entrypoints: web
      traefik.http.routers.rweb.middlewares: redirect_regex

      traefik.http.routers.rwebs.rule: Host(`secondary.domain.com`)
      traefik.http.routers.rwebs.entrypoints: websecure
      traefik.http.routers.rwebs.tls.certresolver: myhttpchallenge
      traefik.http.routers.rwebs.middlewares: redirect_regex

      traefik.http.middlewares.redirect_regex.redirectregex.regex: ^https?://(.*)\.domain\.com(.*)
      traefik.http.middlewares.redirect_regex.redirectregex.replacement: https://host.domain.com$${1}

      traefik.http.services.proxy-secured.loadbalancer.server.port: 8080  

Hi @ldez,
thank you very much for your updated config and sorry for coming back to this topic that late but I'm still struggling.

First thing I noticed was that I had to replace the colons ":" with equal signs "=" to make it work with the labels in my docker-compose.yml.

However, I get this error message when I try a docker-compose up:

ERROR: yaml.scanner.ScannerError: while scanning a double-quoted scalar
  in "./docker-compose.yml", line 158, column 15
found unknown escape character '.'
  in "./docker-compose.yml", line 158, column 91

Line 158 is this one:

- "traefik.http.middlewares.redirect_regex.redirectregex.regex=^https?://(.*)\.domain\.com(.*)"

I tried to escape the backslashes:

- "traefik.http.middlewares.redirect_regex.redirectregex.regex=^https?://(.*)\\.domain\\.com(.*)"

Then the error does not show up anymore. However, no routers, services or middlewares are registered and the site does not respond at the defined domains.

When I comment out the redirect_regex middleware and remove the references from rweb and rwebs the site is reachable under both domain names. Of course the redirect is missing.

Maybe I just can't figure out how to escape the regex correctly.
Any idea?

in YAML you can use both syntax to define the value of a map (labels are a map)

Syntax with - at the beginning of the line and = as separator between the key and the value:

myMap:
  - "key1=value1"
  - "key2=value2"
  - "key3=value3"

Syntax without - and with : as separator between the key and the value:

myMap:
  key1: value1
  key2: value2
  key3: value3

I prefer the second syntax because, for me, it's a better representation of the real type (a map).

Hi @ldez, thank you I was not aware of this. I would also prefer the second syntax, but it doesn't matter that much to me as long as it is consistant and words.

Anyways, do you have any idea why the yaml.scanner complained about the regex and how to escape it correctly?

I don't have any parsing issue with my previous example.

With quotes:

version: '3.7'

services:
  web:
    image: traefik:v2.1.4
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.myhttpchallenge.acme.httpchallenge=true
      - --certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web
      - --certificatesresolvers.myhttpchallenge.acme.email=my@email.com
      - --certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt/:/letsencrypt/acme.json

  whoami:
    image: containous/whoami
    labels:
      - "traefik.enable=true"
      
      - "traefik.http.routers.proxy-secured.rule=Host(`host.domain.com`)"
      - "traefik.http.routers.proxy-secured.entrypoints=websecure"
      - "traefik.http.routers.proxy-secured.tls.certresolver=myhttpchallenge"
      
      - "traefik.http.routers.rweb.rule=Host(`host.domain.com`)"
      - "traefik.http.routers.rweb.entrypoints=web"
      - "traefik.http.routers.rweb.middlewares=redirect_regex"

      - "traefik.http.routers.rwebs.rule=Host(`secondary.domain.com`)"
      - "traefik.http.routers.rwebs.entrypoints=websecure"
      - "traefik.http.routers.rwebs.tls.certresolver=myhttpchallenge"
      - "traefik.http.routers.rwebs.middlewares=redirect_regex"

      - "traefik.http.middlewares.redirect_regex.redirectregex.regex=^https?://(.*)\\.domain\\.com(.*)"
      - "traefik.http.middlewares.redirect_regex.redirectregex.replacement=https://host.domain.com$${2}"

      - "traefik.http.services.proxy-secured.loadbalancer.server.port=808
1 Like

Hi @ldez,
thank you very much, after updating the regex it basically worked. I just had to do two minor adjustments:

Replaced the line

- "traefik.http.routers.rweb.rule=Host(`host.domain.com`)"

with

- "traefik.http.routers.rweb.rule=Host(`host.domain.com`,`secondary.domain.com`)"

so that the redirect is also active for http:// on the second domain.

Replaced the line

      - "traefik.http.middlewares.redirect_regex.redirectregex.replacement=https://host.domain.com$${1}"

with

      - "traefik.http.middlewares.redirect_regex.redirectregex.replacement=https://host.domain.com$${2}"

so that the path after the domain is added to the redirect target instead of the hostname / domain prefix.

Other than that, your config works perfectly fine for me.
That's why I marked it as a solution.

Thank you very much!