Http to https redirect with v2. ends in 404 for http

I followed: https://blog.containo.us/traefik-2-0-docker-101-fc2893944b9d
to setup http redirection for my docker service:

My traefik yml looks like:

  traefik:
    # The official v2.0 Traefik docker image
    image: traefik:v2.0.1
    # Enables the web UI and tells Traefik to listen to docker
    command:
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--providers.docker"
      - "--api.insecure=true"
      - "--log.level=DEBUG"
      - "--global.sendAnonymousUsage=true"
      - "--providers.docker.exposedbydefault=false"
      - "--certificatesresolvers.le.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.le.acme.email=tom@email.com"
      - "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.le.acme.tlschallenge=true"
    ports:
      - "80:80"
      - "443:443"
      # The Web UI (enabled by --api)
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock
    labels:
      # middleware redirect
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      # global redirect to https
      - "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"

In my service.yml I have:

   labels:
      - "traefik.enable=true"
      - "traefik.http.routers.doctorbeeweb.rule=Host(`mydomain.org`)"
      - "traefik.http.routers.doctorbeeweb.entrypoints=websecure"
      - "traefik.http.routers.doctorbeeweb.tls=true"
      - "traefik.http.routers.doctorbeeweb.tls.certresolver=le"

I see the "https"-version of my web applciation. The dashboard is also shown.
But for the "http"-version I get "404 page not found" without any log in traefik-docker-logs.

Still one remark regarding https://blog.containo.us/traefik-2-0-docker-101-fc2893944b9d
The blog mentions:
"traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"
The full yml at github shows:
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"

redirs vs. http-catchall I tried both but no difference.

Take a look at this.
I couldn't get your link working for redirection but I changed it from global onto the application and it worked

1 Like

I'm experiencing the same issue. I can't get a global redirect to work.

My thought is, that the regular expression, doesn't work for me, since I'm using service.home.domain.tld instead of service.domain.tld.

Don't worry about the port bend. I'm sitting behind a router that redirects the ports correctly. I just can't use the default ports on that machine, since they're in use by my NAS Software and other services locally. SSL Certs, accessing via https etc.everyhting works fine.

traefik docker-compose.yml: (As you can see, I even tried to match the host/service to no avail)

version: '3.5'

services:
  traefik:
    image: traefik:2.0.2
    container_name: traefik
    command:
      - --log.level=DEBUG
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.le.acme.email=MAIL
      - --certificatesresolvers.le.acme.storage=/acme.json
      - --certificatesResolvers.le.acme.dnsChallenge.provider=cloudflare
      - --certificatesresolvers.le.acme.dnschallenge=true
      - --providers.docker=true
      - --api
      - --providers.docker.exposedByDefault=false
      - --providers.file.filename=/etc/traefik/rules.yml
      - --providers.file.watch=true
    environment:
      CF_API_EMAIL: "MAIL"
      CF_API_KEY: "CFKEY"
    ports:
      - "81:80"
      - "8099:8080"
      - "444:443"
    networks:
      - web
    labels:
      # Dashboard
      - "traefik.http.routers.traefik.rule=Host(`api.home.domain.tld`)"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls.certresolver=le"
      - "traefik.http.routers.traefik.entrypoints=websecure"

      # Dashboard auth
      # insert here

      # middleware redirect
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"

      # global redirect to https
      - "traefik.http.routers.redirs.entrypoints=web"
#      - "traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.redirs.rule=Host(`whoami.home.domain.tld`)"
      - "traefik.http.routers.redirs.middlewares=redirect-to-https@docker"

    volumes:
#     - ./traefik.toml:/etc/traefik/traefik.toml
      - ./rules.yml:/etc/traefik/rules.yml
      - ./acme.json:/acme.json
      - /var/run/docker.sock:/var/run/docker.sock
      - traefik_data:/tmp

networks:
  web:
    external: true

volumes:
  traefik_data:

whoami docker-compose.yml

version: "2"

services:
  whoami:
    image: jwilder/whoami
    container_name: "whoami"
    labels:
      - traefik.enable=true
#      - traefik.http.middlewares.whoami-https.redirectscheme.scheme=https
#      - traefik.http.routers.whoami-http.entrypoints=web
#      - traefik.http.routers.whoami-http.rule=Host(`whoami.home.domain.tld`)
#      - traefik.http.routers.whoami-http.middlewares=whoami-https@docker

      - traefik.http.routers.whoami.entrypoints=websecure
      - traefik.http.routers.whoami.rule=Host(`whoami.home.domain.tld`)
      - traefik.http.routers.whoami.tls=true
      - traefik.http.routers.whoami.tls.certresolver=le


      - traefik.http.services.whoami.loadbalancer.server.port=8000
    networks:
      - web
    restart: unless-stopped

networks:
  web:
    external: true

Accessing the http version throws me a 404 and the debug log of traffic does not show any kind of access on that entrypoint/router.

traefik debug.log (hope its not too reducted)

Starting traefik ... done
Attaching to traefik
traefik    | time="2019-10-15T16:26:07Z" level=info msg="Configuration loaded from flags."
traefik    | time="2019-10-15T16:26:07Z" level=info msg="Traefik version 2.0.2 built on 2019-10-09T19:26:05Z"
traefik    | time="2019-10-15T16:26:07Z" level=debug msg="Static configuration loaded {\"global\":{\"checkNewVersion\":true},\"serversTransport\":{\"maxIdleConnsPerHost\":200},\"entryPoints\":{\"web\":{\"address\":\":80\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":10000000000},\"respondingTimeouts\":{\"idleTimeout\":180000000000}},\"forwardedHeaders\":{}},\"websecure\":{\"address\":\":443\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":10000000000},\"respondingTimeouts\":{\"idleTimeout\":180000000000}},\"forwardedHeaders\":{}}},\"providers\":{\"providersThrottleDuration\":2000000000,\"docker\":{\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host(`{{ normalize .Name }}`)\",\"swarmModeRefreshSeconds\":15000000000},\"file\":{\"watch\":true,\"filename\":\"/etc/traefik/rules.yml\"}},\"api\":{\"dashboard\":true},\"log\":{\"level\":\"DEBUG\",\"format\":\"common\"},\"certificatesResolvers\":{\"le\":{\"acme\":{\"email\":\"MAIL\",\"caServer\":\"https://acme-v02.api.letsencrypt.org/directory\",\"storage\":\"/acme.json\",\"keyType\":\"RSA4096\",\"dnsChallenge\":{\"provider\":\"cloudflare\"}}}}}"
traefik    | time="2019-10-15T16:26:07Z" level=info msg="\nStats collection is disabled.\nHelp us improve Traefik by turning this feature on :)\nMore details on: https://docs.traefik.io/v2.0/contributing/data-collection/\n"
traefik    | time="2019-10-15T16:26:07Z" level=debug msg="No default certificate, generating one"
traefik    | time="2019-10-15T16:26:08Z" level=info msg="Starting provider aggregator.ProviderAggregator {}"
traefik    | time="2019-10-15T16:26:08Z" level=debug msg="Start TCP Server" entryPointName=web
traefik    | time="2019-10-15T16:26:08Z" level=debug msg="Start TCP Server" entryPointName=websecure
traefik    | time="2019-10-15T16:26:08Z" level=info msg="Starting provider *file.Provider {\"watch\":true,\"filename\":\"/etc/traefik/rules.yml\"}"
traefik    | time="2019-10-15T16:26:08Z" level=info msg="Starting provider *acme.Provider {\"email\":\"MAIL\",\"caServer\":\"https://acme-v02.api.letsencrypt.org/directory\",\"storage\":\"/acme.json\",\"keyType\":\"RSA4096\",\"dnsChallenge\":{\"provider\":\"cloudflare\"},\"ResolverName\":\"le\",\"store\":{},\"ChallengeStore\":{}}"
traefik    | time="2019-10-15T16:26:08Z" level=info msg="Testing certificate renew..." providerName=le.acme
traefik    | time="2019-10-15T16:26:08Z" level=info msg="Starting provider *docker.Provider {\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host(`{{ normalize .Name }}`)\",\"swarmModeRefreshSeconds\":15000000000}"
traefik    | time="2019-10-15T16:26:08Z" level=debug msg="Configuration received from provider file: {\"http\":{},\"tcp\":{},\"tls\":{}}" providerName=file
traefik    | time="2019-10-15T16:26:08Z" level=debug msg="Configuration received from provider le.acme: {\"http\":{},\"tls\":{}}" providerName=le.acme
traefik    | time="2019-10-15T16:26:08Z" level=debug msg="No default certificate, generating one"
traefik    | time="2019-10-15T16:26:08Z" level=debug msg="Provider connection established with docker 19.03.3 (API 1.40)" providerName=docker

// Filtering disabled Containers //

traefik    | time="2019-10-15T16:26:08Z" level=debug msg="Configuration received from provider docker: {\"http\":{},\"tcp\":{}}" providerName=docker
traefik    | time="2019-10-15T16:26:09Z" level=debug msg="Adding certificate for domain(s) whoami.home.domain.tld"

traefik    | time="2019-10-15T16:26:09Z" level=debug msg="No default certificate, generating one"
traefik    | time="2019-10-15T16:26:11Z" level=debug msg="Adding certificate for domain(s) whoami.home.domain.tld"

traefik    | time="2019-10-15T16:26:11Z" level=debug msg="No default certificate, generating one"
traefik    | time="2019-10-15T16:26:37Z" level=debug msg="Provider event received {Status:start ID:5de4666692a095f4c66559b684a3276fdc5363dcdfa6a7304bf0a63e37d47ca4 From:jwilder/whoami Type:container Action:start Actor:{ID:5de4666692a095f4c66559b684a3276fdc5363dcdfa6a7304bf0a63e37d47ca4 Attributes:map[com.docker.compose.config-hash:1f71bfe9bf9a3e93cf7ffaf99cd568d97652a4fce79f5026b8570ccc6e6cee17 com.docker.compose.container-number:1 com.docker.compose.oneoff:False com.docker.compose.project:whoami com.docker.compose.service:whoami com.docker.compose.version:1.23.2 image:jwilder/whoami name:whoami traefik.enable:true traefik.http.routers.whoami.entrypoints:websecure traefik.http.routers.whoami.rule:Host(`whoami.home.domain.tld`) traefik.http.routers.whoami.tls:true traefik.http.routers.whoami.tls.certresolver:le traefik.http.services.whoami.loadbalancer.server.port:8000]} Scope:local Time:1571156797 TimeNano:1571156797257080032}" providerName=docker

// Filtering disabled Containers //

traefik    | time="2019-10-15T16:26:37Z" level=debug msg="Configuration received from provider docker: {\"http\":{\"routers\":{\"whoami\":{\"entryPoints\":[\"websecure\"],\"service\":\"whoami\",\"rule\":\"Host(`whoami.home.domain.tld`)\",\"tls\":{\"certResolver\":\"le\"}}},\"services\":{\"whoami\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.18.0.3:8000\"}],\"passHostHeader\":true}}}},\"tcp\":{}}" providerName=docker
traefik    | time="2019-10-15T16:26:37Z" level=debug msg="Adding certificate for domain(s) whoami.home.domain.tld"

traefik    | time="2019-10-15T16:26:37Z" level=debug msg="No default certificate, generating one"
traefik    | time="2019-10-15T16:26:38Z" level=debug msg="Creating middleware" middlewareType=Pipelining entryPointName=websecure routerName=whoami@docker serviceName=whoami middlewareName=pipelining
traefik    | time="2019-10-15T16:26:38Z" level=debug msg="Creating load-balancer" entryPointName=websecure routerName=whoami@docker serviceName=whoami
traefik    | time="2019-10-15T16:26:38Z" level=debug msg="Creating server 0 http://172.18.0.3:8000" serverName=0 entryPointName=websecure routerName=whoami@docker serviceName=whoami
traefik    | time="2019-10-15T16:26:38Z" level=debug msg="Added outgoing tracing middleware whoami" entryPointName=websecure routerName=whoami@docker middlewareName=tracing middlewareType=TracingForwarder
traefik    | time="2019-10-15T16:26:38Z" level=debug msg="Creating middleware" entryPointName=websecure middlewareName=traefik-internal-recovery middlewareType=Recovery
traefik    | time="2019-10-15T16:26:38Z" level=debug msg="Try to challenge certificate for domain [whoami.home.domain.tld] founded in HostSNI rule" routerName=whoami rule="Host(`whoami.home.domain.tld`)" providerName=le.acme
traefik    | time="2019-10-15T16:26:38Z" level=debug msg="Looking for provided certificate(s) to validate [\"whoami.home.domain.tld\"]..." providerName=le.acme routerName=whoami rule="Host(`whoami.home.domain.tld`)"
traefik    | time="2019-10-15T16:26:38Z" level=debug msg="No ACME certificate generation required for domains [\"whoami.home.domain.tld\"]." providerName=le.acme routerName=whoami rule="Host(`whoami.home.domain.tld`)"
traefik    | time="2019-10-15T16:26:45Z" level=debug msg="Provider event received {Status:die ID:5de4666692a095f4c66559b684a3276fdc5363dcdfa6a7304bf0a63e37d47ca4 From:jwilder/whoami Type:container Action:die Actor:{ID:5de4666692a095f4c66559b684a3276fdc5363dcdfa6a7304bf0a63e37d47ca4 Attributes:map[com.docker.compose.config-hash:1f71bfe9bf9a3e93cf7ffaf99cd568d97652a4fce79f5026b8570ccc6e6cee17 com.docker.compose.container-number:1 com.docker.compose.oneoff:False com.docker.compose.project:whoami com.docker.compose.service:whoami com.docker.compose.version:1.23.2 exitCode:137 image:jwilder/whoami name:whoami traefik.enable:true traefik.http.routers.whoami.entrypoints:websecure traefik.http.routers.whoami.rule:Host(`whoami.home.domain.tld`) traefik.http.routers.whoami.tls:true traefik.http.routers.whoami.tls.certresolver:le traefik.http.services.whoami.loadbalancer.server.port:8000]} Scope:local Time:1571156805 TimeNano:1571156805986671916}" providerName=docker

// Filtering disabled Containers //

traefik    | time="2019-10-15T16:26:46Z" level=debug msg="Configuration received from provider docker: {\"http\":{},\"tcp\":{}}" providerName=docker
traefik    | time="2019-10-15T16:26:46Z" level=debug msg="Adding certificate for domain(s) whoami.home.domain.tld"

traefik    | time="2019-10-15T16:26:46Z" level=debug msg="No default certificate, generating one"
^CGracefully stopping... (press Ctrl+C again to force)
Stopping traefik ... done

Had the same problem. Defining the https middleware in docker-compose.yml didn't work out for me. Had to use .toml config files. Please let me know if you find a solution. Thx :slight_smile:

Hi Dan42,

would you be willing to share your .toml config? I even tried to do that, from a different thread, but I couldn't get it to work either.

This is a bummer for me so far.

Maybe I have to go back to the drawing board once and for all, since I noticed that the api/dashboard with https does not work either and throws an error 404, too.

Greetings
David

I took the configs from this post: https://community.containo.us/t/global-http-to-https-redirect-in-v2/1658/3. This post also mentions the possibility to add a global http redirect with labels to traefik container. But like I said, it didn't work out for me.

[http.routers]
  [http.routers.redirecttohttps]
    entryPoints = ["web"]
    middlewares = ["httpsredirect"]
    rule = "HostRegexp(`{host:.+}`)"
    service = "noop"

[http.services]
  [http.services.noop.loadBalancer]
    [[http.services.noop.loadBalancer.servers]]
      url = "http://192.168.0.1"

[http.middlewares]
  [http.middlewares.httpsredirect.redirectScheme]
    scheme = "https"
    permanent = true
1 Like

Thank you dan42. Your config snippet pushed me into the right direction. After adding everything to my rules.yml file (dynamic rules) it seemed to work after a while.

What was left was the issue with the not working dashboard so i went ahead, and moved EVERYTHING from the labels, that i had working, to a traefik.yml. This was done within minutes, and not considering two typos i had to debug, worked like a breeze.
Then I tried to implement the Dashboard from scratch again and got it working on the default settings, with ssl cert etc. pp. The icing on the cake, however, was that i found out that the dashboard autocreates entrypoint traefik on port 8080, when it does not yet exist. So i went ahead and added the entrypoint manually beforehand (and moved the port to 8099, since i need 8080 for unifi) and it kept working perfectly.

Thanks Dan42 for your help. :wink:

PS: So my advice to everybody, when you got trouble with https redirect not working when using labels: switch to a dynamic rules file instead. Seems to work way better.

EDIT: One Question is left though: Why does the rule for the dashboard work on all entrypoints and not just websecure?

Greetings
David

I tried your solution at application level now for a subdomain.
Say my main domain is abcde.org my subdomain is now blog.abcde.org.

I have the blog-software ghost running in docker and the label in dthe docker-compose.yml for ghost looks like:

   labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.ghost-https.redirectscheme.scheme=https"
      - "traefik.http.routers.ghost-http.entrypoints=web"
      - "traefik.http.routers.ghost-http.rule=Host(`blog.abcde.org`)"
      - "traefik.http.routers.ghost-http.middlewares=ghost-https@docker"
      - "traefik.http.routers.ghost.entrypoints=websecure"
      - "traefik.http.routers.ghost.rule=Host(`blog.abcde.org`)"
      - "traefik.http.routers.ghost.tls=true"
      - "traefik.http.routers.ghost.tls.certresolver=le"

When I look in the traefik dash board all looks fine. But now I get PRIVACY ERROR in the web browser when I call https://blog.abcde.org --> Your connection is not private
All is still fine with https://abcde.org .
I also checked my acme.json. It has now TWO entries one for https://abcde.org and one for https://blog.abcde.org

What is wrong?

Works now. I had to comment out the test caserver from letsencrypt.

I was struggling with this same issue and I identified the issue from the original poster, so I wanted to share. It does work in Docker Compose, but with one caveat. The solution can be found here: HTTP to HTTPS Redirect Causing a 404

For me the solution was in link from post #2
Here is working docker-compose file with working redirection to nginx server (docker swarm)

version: "3.3"

services:
  traefik:
    image: "traefik:v2.2.1"
    command:
      - "--log.level=DEBUG"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--providers.docker=true"
      - "--api.insecure"
      - "--providers.docker.exposedbydefault=false"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=YOUR_EMAIL"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
      #swarm
      - "--providers.docker.swarmmode=true"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "/sites/letsencrypt:/letsencrypt"
   
    networks:
      - public
  
  SITE-container:
    image: nginx
    #command:
      #- --port=80
    volumes: 
        # volume on host machine MUST exist
        - /sites/SITE/www:/usr/share/nginx/html
    deploy:
      labels:
          # enable Traefik for container
          - "traefik.enable=true"
          # middleware to redirect trafic to https
          - "traefik.http.middlewares.SITE-https.redirectscheme.scheme=https"
          #" http-SITE" router to listen on "web" entrypoint
          - "traefik.http.routers.SITE-http.entrypoints=web"
          # hostname for the site on "SITE-http" router
          - "traefik.http.routers.SITE-http.rule=Host(`SITE.org`)"
          # tell the router to use redirect middleware defined above
          - "traefik.http.routers.SITE-http.middlewares=SITE-https@docker"
          # "SITE" router hostname
          - "traefik.http.routers.bio.rule=Host(`SITE.org`)"
          # where router should be listening
          - "traefik.http.routers.bio.entrypoints=websecure"
          # tell "SITE" router to terminate SSL requests
          - "traefik.http.routers.SITE.tls=true"
          # the router should use LetsEncrypt configuration defined in Traefik
          - "traefik.http.routers.SITE.tls.certresolver=myresolver"
          # necessary for docker
          - "traefik.http.services.SITE.loadbalancer.server.port=80"
    networks:
      - public
networks:
  public:
    driver: overlay
    attachable: true

You can duplicate the SITE section as many times as you want for different domains.
Only dashboard needs to be redirected to https...
The VOLUME needs to be created before deploying docker-compose file!!!
To deploy it copy docker-compose file to host machine with overlay network created

$ docker network create -d overlay --attachable my-attachable-overlay

and deploy with

$docker stack deploy -c docker-compose.yml <STACK NAME>

Hope it will help someone :wink: