59

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"
      - "--certificatesresolvers.myhttpchallenge.acme.email=me@mail.com"
      - "--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"
Xiiryo
  • 3,021
  • 5
  • 31
  • 48

11 Answers11

71

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.

starball
  • 20,030
  • 7
  • 43
  • 238
Cellcore
  • 824
  • 6
  • 8
  • 4
    Just seeking clarification here - this redirects ALL traffic, for ALL services, and removes the need for redirect middlewares declared at service levels? Lets say, hypothetically, that i do that, and then I have a single service out of 5 that i want accessible via plain http, so no redirect here. Can i "skip" redirect for a single service then? – Christian W Nov 22 '20 at 11:03
  • @ChristianW good question; you should try it :) I guess it won’t work as it is a global redirect. – Cellcore Dec 07 '20 at 20:34
  • 2
    If this solution does not work for you with the result that the Traefik container itself does not start giving the error: `command traefik error: failed to decode configuration from flags: field not found, node: http` try to update the Traefik version to the latest available (with me **v2.0 gave the error**, but **with v2.3** now **everything works**) – MXT Jan 04 '21 at 17:22
  • 3
    Does this [break the let's encrypt `http` challenge](https://community.traefik.io/t/https-redirection-without-breaking-letsencrypt-http-challenge/11215/3)? – Pathros May 08 '22 at 04:10
23

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)

Lars
  • 736
  • 1
  • 8
  • 18
  • Not sure that's the requirement. The way you described it, it seems that the requests goes in traefik port 80 and the scheme gets changed to https before being forwarded to backend service. But the backend service doesn't do https termination, so that will fail. The idea would be to make an actual http redirect so that the request goes back to traefik on port 443 preserving the host. In Traefik v1 that was easily done via static configuration. – Andrei Dascalu Jan 07 '20 at 13:33
  • This works. This ought to be in the documentation. You just have to make a router for the http version and put the redirect middleware on that. – milosa Jan 26 '20 at 14:10
  • 1
    Thanks, works for me. The docs state "If you need to define the same route for both HTTP and HTTPS requests, you will need to define two different routers: one with the tls section, one without." so this makes sense. The redirection won't work if you're not defining a route for port 80. Docs here: https://doc.traefik.io/traefik/v2.2/routing/routers/#tls – badsyntax Jun 15 '21 at 16:33
  • Does this [break the let's encrypt `http` challenge](https://community.traefik.io/t/https-redirection-without-breaking-letsencrypt-http-challenge/11215/3)? – Pathros May 08 '22 at 04:11
  • [This post](https://techoverflow.net/2020/09/21/traefik-docker-compose-configuration-with-secure-dashboard-and-lets-encrypt/) has helped me as well – Pathros May 09 '22 at 16:10
21

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"  
RAM
  • 2,257
  • 2
  • 19
  • 41
  • 1
    Here is the docker-compose.yml from the article https://github.com/containous/blog-posts/blob/master/2019_09_10-101_docker/docker-compose-07.yml – TheOneRing Jan 22 '20 at 17:34
  • 1
    Note that having an existing *acme.json* can block the middleware from redirecting to HTTPS. Remove it if it already exists on Traefik start up. – AymDev Mar 22 '20 at 12:48
  • Does this [break the let's encrypt `http` challenge](https://community.traefik.io/t/https-redirection-without-breaking-letsencrypt-http-challenge/11215/3)? – Pathros May 08 '22 at 04:10
7

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"
      - "--certificatesresolvers.myresolver.acme.email=user@domain.com"
      - "--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"
hbceylan
  • 968
  • 10
  • 10
5

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.

nachtjasmin
  • 386
  • 4
  • 13
fperk
  • 51
  • 1
  • 2
  • Thank you, this is what I was looking for. I did not use ENV variables, but just added some lines to the static confugration: ``` [entryPoints] [entryPoints.web] address = ":80" [entryPoints.web.http] [entryPoints.web.http.redirections] [entryPoints.web.http.redirections.entryPoint] to = "websecure" scheme = "https" [entryPoints.websecure] address = ":443" ``` – Morgus Lethe Jun 18 '20 at 10:11
5

There are two options:

Either you can redirect ALL incoming traffic to HTTPS by adding the following to the static configuration of the Traefik container:

command:
- "--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"

Or you can redirect traffic to HTTPS for a single container by adding the following to the dynamic configuration of the application container:

labels:
- "traefik.enable=true"
- "traefik.http.middlewares.myapp-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.myapp-redirect.redirectscheme.permanent=true"
- "traefik.http.routers.myapp.middlewares=myapp-redirect"
- "traefik.http.routers.myapp.rule=Host(`myapp.localhost`)"
- "traefik.http.routers.myapp.entrypoints=web"
- "traefik.http.routers.myapp-secure.rule=Host(`myapp.localhost`)"
- "traefik.http.routers.myapp-secure.entrypoints=websecure"
- "traefik.http.routers.myapp-secure.tls=true"
- "traefik.http.routers.myapp-secure.tls.certresolver=le"
3

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".

Xiiryo
  • 3,021
  • 5
  • 31
  • 48
  • It's strange. I have redirection middleware declared on Traefik service and referred to from app service and it works. – Izydorr Oct 17 '19 at 13:09
  • With the previous code it seems to work but the http actually don't redirect to https. – Xiiryo Oct 17 '19 at 14:11
  • How do you refer to the Middleware from the app? – Xiiryo Oct 17 '19 at 14:11
  • In traefik service I have a label defining the middleware: `traefik.http.middlewares.https-only.redirectscheme.scheme=https` and in app service I have a labels: `traefik.http.routers.myapp.rule=Host(`${APP_HOST}`)`, `traefik.http.routers.myapp.entrypoints=web`, `traefik.http.routers.myapp.middlewares=https-only` – Izydorr Oct 22 '19 at 07:18
  • I'm not sure to get the whole picture. From my experience the Middleware is local to the app. Another point if that if you use labels you don't need to repeat dit in a configuration file. – Xiiryo Oct 22 '19 at 07:20
  • 1
    I have everything in labels. As I understand it, using middleware requires two labels: one for declaration/configuration (traefik.http.middlewares.https-only.redirectscheme.scheme=https) and then applying it to the service (traefik.http.routers.myapp.middlewares=https-only). The declaration may be located either in the app service or in treafik service for example - just like I do it. Notice that even if you declare a middlewawe in app service, you see it in dashboard together with other middlewares declared in other places. Maybe I'm wrong but I think you can use any of them in any service. – Izydorr Oct 24 '19 at 07:32
3

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
Kalsan
  • 822
  • 1
  • 8
  • 19
2

If you are use to configure traeffik by using the traefik.yml yaml file, you can do also in the v2 the next configuration:

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true
  websecure:
    address: ":443"

Two entrypoints, web is not secure, websecure implements https and has a certificate. The first one is redirected to the second one.

It is the equivalent that other questions but not using the cli or docker commands. Tested on the current latest version of traefik

King Midas
  • 1,442
  • 4
  • 29
  • 50
1

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

Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164
1

my docker-compose template for nginx

  nginx:
    image: nginx:alpine
    container_name: nginx
    restart: always
    labels:
            - "traefik.enable=true"
            - "traefik.http.services.nginx-service.loadbalancer.server.port=80"
              # http
            - "traefik.http.routers.nginx-http.entrypoints=web"
            - "traefik.http.routers.nginx-http.rule=Host(`example.com`)"
              # https
            - "traefik.http.routers.nginx-https.entrypoints=websecure"
            - "traefik.http.routers.nginx-https.rule=Host(`example.com`)"
            - "traefik.http.routers.nginx-https.tls.certresolver=production"
              # http to https
            - "traefik.http.middlewares.nginx-redirect.redirectscheme.scheme=https"
            - "traefik.http.middlewares.nginx-redirect.redirectscheme.permanent=true"
            - "traefik.http.routers.nginx-http.middlewares=nginx-redirect"
    networks:
      - web
networks:
  web:
    external: true

my traefik ssl section

  # LET'S ENCRYPT:
  # ---
  #
  staging:
    acme:
      email: example@mail.com  # TODO: Change this to your email
      storage: /ssl-certs/acme.json
      caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
      httpChallenge:
        entryPoint: web
  production:
    acme:
      email: exam@gmail.com  # TODO: Change this to your email
      storage: /ssl-certs/acme.json
      httpChallenge:
        entryPoint: web