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

11

63

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"
Archimedes answered 12/10, 2019 at 17:29 Comment(0)
D
79

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.

Defrost answered 19/5, 2020 at 23:57 Comment(5)
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?Nestorius
@ChristianW good question; you should try it :) I guess it won’t work as it is a global redirect.Defrost
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)Hindi
Does this break the let's encrypt http challenge?Soporific
no, since traefik then creates internal router for PathPrefix(/.well-known/acme-challenge/) with high enough priority MaxInt32 github.com/traefik/traefik/blob/…Jamshid
C
26

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)

Cope answered 2/11, 2019 at 9:0 Comment(5)
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.Furey
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.Ding
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: doc.traefik.io/traefik/v2.2/routing/routers/#tlsSchism
Does this break the let's encrypt http challenge?Soporific
This post has helped me as wellSoporific
C
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"  
Conjugation answered 20/10, 2019 at 20:33 Comment(3)
Here is the docker-compose.yml from the article github.com/containous/blog-posts/blob/master/…Religiosity
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.Octavla
Does this break the let's encrypt http challenge?Soporific
P
10

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"
Patina answered 3/12, 2022 at 15:49 Comment(0)
P
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"
      - "[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"
Pergola answered 8/9, 2021 at 22:52 Comment(1)
with args you specified, it throws permission denied:/Lythraceous
H
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.

Humanize answered 10/4, 2020 at 18:3 Comment(1)
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" ```Reign
A
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".

Archimedes answered 12/10, 2019 at 18:49 Comment(6)
It's strange. I have redirection middleware declared on Traefik service and referred to from app service and it works.Much
With the previous code it seems to work but the http actually don't redirect to https.Archimedes
How do you refer to the Middleware from the app?Archimedes
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-onlyMuch
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.Archimedes
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.Much
S
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
Steelyard answered 12/9, 2020 at 9:16 Comment(0)
T
3

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

Torpid answered 16/5, 2023 at 15:22 Comment(0)
C
2

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

Cowrie answered 2/9, 2021 at 22:23 Comment(1)
More recent versions of the helm chart need to use ports.web.redirectTo.port as described in github.com/traefik/traefik-helm-chart/pull/934Holp
G
2

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: [email protected]  # 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: [email protected]  # TODO: Change this to your email
      storage: /ssl-certs/acme.json
      httpChallenge:
        entryPoint: web
Greggrega answered 3/12, 2022 at 12:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.