# Global redirection: http to https
traefik.http.routers.http_catchall.rule: HostRegexp(`{host:.+}`)
traefik.http.routers.http_catchall.entrypoints: web
traefik.http.routers.http_catchall.middlewares: tohttps
I'm just wondering if there is any difference in such approaches or if they are equivalent from the functional point of view.
Side question: with the CLI option, is there a way to add also a rule for redirecting URLs like http(s)://www.foo.com to https://foo.com
and this is the middleware section of the Traefik container (labels):
# just for https, since Traefik redirects all http connections to https at the entrypoint level
traefik.http.middlewares.trim_www.redirectregex.regex: ^https://www\.(.+)
traefik.http.middlewares.trim_www.redirectregex.replacement: https://$${1}
traefik.http.middlewares.trim_www.redirectregex.permanent: true
But this configuration does not work. Where am I wrong?
command:
- --entrypoints.webinsecure.address=:80
# redirection to https
- --entrypoints.webinsecure.http.redirections.entrypoint.to=websecure
- --entrypoints.webinsecure.http.redirections.entrypoint.scheme=https
- --entrypoints.websecure.address=:443
labels:
# just for https, since Traefik redirects all http connections to https at the entrypoint level
traefik.http.middlewares.trim_www.redirectregex.regex: ^https://www\\.(.+)
traefik.http.middlewares.trim_www.redirectregex.replacement: https://$${1}
traefik.http.middlewares.trim_www.redirectregex.permanent: true
However I'm trying to use this strategy globally. I have one central Traefik container with this configuration:
docker-compose.yml (Traefik)
version: '3.7'
services:
# a cool reverse-proxy / load balancer
traefik:
# The official v2 Traefik docker image
image: traefik:v2.2.1
container_name: traefik
security_opt:
- no-new-privileges:true
restart: always
env_file:
# variables that will be passed to the container
- .provider.env
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock:ro
# tls-certificates path (TLS)
- ./letsencrypt:/letsencrypt
ports:
# http
- ${HTTP_PORT}:80
# https
- ${HTTPS_PORT}:443
command:
###########################################
# Static Configuration harnessing CLI #
###########################################
# Activate dashboard.
- --api.dashboard=true
# Log level set to traefik logs. (Default: ERROR)
- --log.level=${DEBUG_LEVEL}
# Enable Docker backend with default settings.
- --providers.docker=true
# Do not expose containers by default.
- --providers.docker.exposedbydefault=false
# Default Docker network used.
- --providers.docker.network=proxy
# --entrypoints.<name>.address for ports
# 80 (i.e., name = webinsercure)
- --entrypoints.webinsecure.address=:80
# redirection to https
- --entrypoints.webinsecure.http.redirections.entrypoint.to=websecure
- --entrypoints.webinsecure.http.redirections.entrypoint.scheme=https
# 443 (i.e., name = websecure)
- --entrypoints.websecure.address=:443
# DNS certificatesresolvers w/ Let's encrypt
# ACME V2 supports wildcard certificates.
# Wildcard certificates can only be generated through a DNS-01 challenge.
- --certificatesresolvers.leresolver.acme.dnschallenge=true
- --certificatesresolvers.leresolver.acme.dnsChallenge.provider=godaddy
- --certificatesresolvers.leresolver.acme.dnsChallenge.delayBeforeCheck=0
# Email address used for registration.
- --certificatesresolvers.leresolver.acme.email=${CERTIFICATES_EMAIL}
# Certificates storage
- --certificatesresolvers.leresolver.acme.storage=/letsencrypt/acme.json
# TLS certificatesresolvers w/ Let's encrypt (for other domains such as science4fun.org)
# See here: https://github.com/containous/traefik/issues/5632
# Use TLS challenge for `tlsleresolver`
- --certificatesresolvers.tlsleresolver.acme.tlschallenge=true
# Email address used for registration.
- --certificatesresolvers.tlsleresolver.acme.email=${CERTIFICATES_EMAIL}
# Certificates storage (not sure if you can store all the certs in the same file)
# Let's use a new one for the moment
- --certificatesresolvers.tlsleresolver.acme.storage=/letsencrypt/acme_tls.json
networks:
# This is the network over which Traefik communicates with other containers.
- proxy
labels:
################################################
# Dynamic configuration with Docker Labels #
################################################
# You can tell Traefik to consider (or not) this container by setting traefik.enable to true or false.
# We need it for the dashboard
traefik.enable: true
# Dashboard
traefik.http.routers.traefik.rule: Host(`traefik.foo.com`)
traefik.http.routers.traefik.service: api@internal
traefik.http.routers.traefik.tls.certresolver: leresolver
traefik.http.routers.traefik.tls.domains[0].main: foo.com
traefik.http.routers.traefik.tls.domains[0].sans: '*.foo.com'
traefik.http.routers.traefik.entrypoints: websecure
# Declaring the user list
#
# Note=all dollar signs in the hash need to be doubled for escaping.
# To create user:password pair, it's possible to use this command:
# echo $(htpasswd -nb user password) and then save user and password in
# the .env file
traefik.http.routers.traefik.middlewares: traefik-auth
traefik.http.middlewares.traefik-auth.basicauth.users: ${DASHBOARD_USERNAME}:${DASHBOARD_PASSWORD}
networks:
proxy:
external: true
... and I was trying to put there the logic for all non-www redirections, with a global fashion, without repeating it in all other services defined in other compose files (like you did with whoami in your example). Not sure if this is possible since we are working at the dynamic level.
my-test-app:
image: containous/whoami
networks:
# This is the network over which Traefik communicates with other containers.
- proxy
labels:
traefik.enable: true
traefik.http.routers.my-test-app.rule: Host(`foo.com`)
traefik.http.routers.my-test-app.entrypoints: websecure
traefik.http.routers.my-test-app.tls.certresolver: leresolver
traefik.http.routers.my-test-app.tls.domains[0].main: foo.com
traefik.http.routers.my-test-app.tls.domains[0].sans: '*.foo.com'
Please, note that, from the theoretical perspective , I shouldn't set explicitly "www.foo.com"-like rules in each router rule, since the global middleware (wwwtohttps) should strip www from requests. (Also in this answer, they do the same)
It appears to me that you are getting 404 on www.foo.com because there is no router rule that matches requests with this address (or you are not showing it in your post above). In order for router middleware to kick in, the request has to arrive to the router first, and yours does not.
There, they use 2 main routers to catch and redirect http:// and https://www requests, and a middleware to remove the www. In my example, as you pointed out, no router can handle requests with the www.
Since I want to remove www globally, I believe I'll replace entrypoint redirections with the 2 global routers + the middleware of the example. This avoids the need of specifying rules for both www and non-www per service router (e.g., whoami).