How to redirect http to https with Traefik 2.0 and Docker Compose labels?

DockerDocker ComposeTraefik

Docker Problem Overview


Please note that it is a Traefik V2 question. I had a solution on V1 but V2 is a total rewamp.

This above is supposed to redirect http://whoami.mysite.com to https://whoami.mysite.com.

  • The https is working nicely.
  • The http don't redirect to https and raise an error 404.

There is no other file. All is in this Docker-compose.yml for the moment since it is a test to prepare further deployement.

version: "3.3"

services:

  traefik:
    image: "traefik:v2.0"
    container_name: "traefik"
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web-secure.address=:443"
      - "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
      - "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web-secure"
      #- "--certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "[email protected]"
      - "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
    labels:
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "containous/whoami"
    container_name: "whoami"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.mysite.com`)"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.http.routers.whoami.middlewares=redirect-to-https@docker"
      - "traefik.http.routers.whoami-secured.rule=Host(`whoami.mysite.com`)"
      - "traefik.http.routers.whoami-secured.entrypoints=web-secure"
      - "traefik.http.routers.whoami-secured.tls=true"
      - "traefik.http.routers.whoami-secured.tls.certresolver=myhttpchallenge"

Docker Solutions


Solution 1 - Docker

I suggest to take a look here at the docs Entrypoint redirect 80 > 443

This worked for me and is the best solution if you want all traffic redirected from port 80 to 443.

--entrypoints.web.address=:80
--entrypoints.web.http.redirections.entryPoint.to=websecure
--entrypoints.web.http.redirections.entryPoint.scheme=https
--entrypoints.web.http.redirections.entrypoint.permanent=true
--entrypoints.websecure.address=:443

> NOTE: > > there are so many examples around. Just take a look at websecure. > > Sometimes it is written web-secure.

Hope that helps ;o)

Solution 2 - Docker

There is now a working solution in a tutorial from Gérald Croës at:

https://blog.containo.us/traefik-2-0-docker-101-fc2893944b9d

services:  
  traefik:  
    image: "traefik:v2.0.0"  
    # ...  
    labels:  
      # ...        
      # middleware redirect  
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"  
      # global redirect to https  
      - "traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"  
      - "traefik.http.routers.redirs.entrypoints=web"  
      - "traefik.http.routers.redirs.middlewares=redirect-to-https"  

Solution 3 - Docker

You don't need to configure the Traefik service itself. On Traefik you only need to have entrypoints to :443 (web-secure) and :80 (web)

Because Traefik only acts as entryPoint and will not do the redirect, the middleware on the target service will do that.

Now configure your target service as the following:

version: '2'
services:
  mywebserver:
    image: 'httpd:alpine'
    container_name: mywebserver
    labels:
      - traefik.enable=true
      - traefik.http.middlewares.mywebserver-redirect-web-secure.redirectscheme.scheme=https
      - traefik.http.routers.mywebserver-web.middlewares=mywebserver-redirect-web-secure
      - traefik.http.routers.mywebserver-web.rule=Host(`sub.domain.com`)
      - traefik.http.routers.mywebserver-web.entrypoints=web
      - traefik.http.routers.mywebserver-web-secure.rule=Host(`sub.domain.com`)
      - traefik.http.routers.mywebserver-web-secure.tls.certresolver=mytlschallenge
      - traefik.http.routers.mywebserver-web-secure.tls=true
      - traefik.http.routers.mywebserver-web-secure.entrypoints=web-secure
      # if you have multiple ports exposed on the service, specify port in the web-secure service
      - traefik.http.services.mywebserver-web-secure.loadbalancer.server.port=9000

So basically the flow goes like this:

Request: http://sub.domain.com:80 --> traefik (service) --> mywebserver-web (router, http rule) --> mywebserver-redirect-web-secure (middleware, redirect to https) --> mywebserver-web-secure (router, https rule) --> mywebserver (service)

Solution 4 - Docker

You just need to add the following to the traefik config, not application;

- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"

Here is the full yaml config of the traefik

version: "3.3"

services:

  traefik:
    image: "traefik:v2.5"
    container_name: "traefik"
    command:
      # - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      #- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "[email protected]"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"

    ports:
      - "443:443"
      - "80:80"
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

Example application

  whoami:
    image: "traefik/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`subdomain.domain.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=myresolver"

Solution 5 - Docker

I was searching for this answer when I was looking how to redirect everything to HTTPS via Traefik v2.2 and the best option for me was adding this ENV variables to Traefik and it automatically redirects all traffic to HTTPS.

TRAEFIK_ENTRYPOINTS_WEB_ADDRESS=:80
TRAEFIK_ENTRYPOINTS_WEBSECURE_ADDRESS=:443
TRAEFIK_ENTRYPOINTS_WEB_HTTP_REDIRECTIONS_ENTRYPOINT_TO=websecure

With this I have no need to add anything to the middleware. More information about that feature can be found in the official documentation.

Solution 6 - Docker

Ok, found... I assumed that middlewares could be declared at Traefik level but these have to be declared at service level.

This line :

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

Has to be in the labels of the whoami service.

Another point, that is not related to the problem described, is that the http challenge has to be done on port 80.

- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web-secure"

Remove the "secure" in "web-secure".

Solution 7 - Docker

It seems like the global setting is not being done with labels, but with the traefik command arguments. Your question is about labels, but maybe this solution will work for you too?

Here's what to do, according to the official docs under: https://docs.traefik.io/migration/v1-to-v2/#http-to-https-redirection-is-now-configured-on-routers

What used to be in v1:

# static configuration
defaultEntryPoints = ["web", "websecure"]

[entryPoints]
  [entryPoints.web]
    address = ":80"
    [entryPoints.web.redirect]
      entryPoint = "websecure"

  [entryPoints.websecure]
    address = ":443"
    [entryPoints.websecure.tls]

Now appears to be:

--entrypoints.web.address=:80
--entrypoints.web.http.redirections.entrypoint.to=websecure
--entrypoints.web.http.redirections.entrypoint.scheme=https
--entrypoints.websecure.address=:443
--providers.docker=true

Solution 8 - Docker

For kubernetes helm chart users on a recent version of traefik, you can use this in your traefik values file (tested on chart version 10.3.2 / traefik 2.5) to redirect ALL traffic to httpS

# values.yaml
ports:
  web:
    redirectTo: websecure

In case you need CRD updates (traefik 2.4 -> 2.5) use this gist

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionXiiryoView Question on Stackoverflow
Solution 1 - DockerCellcoreView Answer on Stackoverflow
Solution 2 - DockerMartin HryniewieckiView Answer on Stackoverflow
Solution 3 - DockerLarsView Answer on Stackoverflow
Solution 4 - DockerhbceylanView Answer on Stackoverflow
Solution 5 - DockerfperkView Answer on Stackoverflow
Solution 6 - DockerXiiryoView Answer on Stackoverflow
Solution 7 - DockerKalsanView Answer on Stackoverflow
Solution 8 - DockerCyril Duchon-DorisView Answer on Stackoverflow