Skip to main content

Redirect Scheme

Updated Feb 05, 2023 ·

Overview

When users visit your site with Http, the redirect scheme middleware sends them to the secure Https version.

  • Permanent redirects tell search engines this change is final.
  • Temporary redirects mean it might change later.

Redirects protect user data by forcing secure connections. They also help SEO by telling search engines which version to index.

Setting up Redirect Scheme

Set up a middleware with a name like test-redirect-scheme. Configure it to always use Https.

Example:

  - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"

This means all Http requests get redirected to Https with a permanent redirect status.

Lab: From Http to Https

In this lab, we will set up a redirect so users always connect to our app through the secure Https entry point.

  • Redirect one app service from Http to Https
  • Use separate routers for Http and Https
  • Apply middlewares like auth and rate limit only on the Https router

This redirect applies only to one service, keeping other services on Http. It gives more control and keeps Traefik changes safe and focused.

Setup a Public Cloud VM

It is recommended to perform this lab on a a VM with a public IP because you need to open port 80 to the internet.

  • Your DNS records must point to the VM’s public IP.
  • Let’s Encrypt can verify your site via HTTP without problems.

If you do this lab in your local Windows machine, it is likely that your machine has a private LAN IP like 192.168.x.x behind NAT.

You can definitely tweak your Windows machine’s firewall to allow inbound connections on port 80 (and 443), but this alone won’t fix the main problem if your router or network blocks/doesn’t forward that traffic.

To create a public cloud VM, you can use:

Make sure your EC2 security group allows inbound TCP traffic on:

  • Port 80 (HTTP)
  • Port 443 (HTTPS)
  • Port 8080 (Traefik dashboard)

After launching your VM, install the necessary tools. For example, on my EC2 instance, I run:

# Install Git 
sudo yum update -y && sudo yum install -y git

# Install Docker
sudo amazon-linux-extras enable docker
sudo yum install -y docker

# Start Docker service
sudo systemctl enable --now docker
sudo systemctl status docker

# Configure DOcker
sudo usermod -aG docker ec2-user && newgrp docker

# Install Docker compsoe
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# Configure permission
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

# Initialize Docker Swarm (needed for docker stack deploy):
docker swarm init

Prepare your Domain

Before using HTTPS with Traefik, make sure you have:

  • A domain name for testing
  • DNS records pointing to your DNS provider
  • A DNS provider supported by TraefikA DNS provider supported by Traefik

Check the supported providers list here: Traefik DNS Provider Integrations**

For example, my setup uses:

  • Domain from Namecheap
  • DNS hosted on DigitalOcean

After getting a domain, update its registrar settings so it points to your chosen DNS provider. If you're also using DigitalOcean, you can follow the steps here: Adding a Domain in DigitalOcean

NOTE: Make sure your domain is fully set up and pointing to your server before proceeding with the labs. Propagation can take up to 24–48 hours, sometimes longer depending on the registrar and TLD.

To verify, you can run:

dig NS yourdomain.com
dig A yourdomain.com

If you are using DigitalOcean name servers, you should see:

;; ANSWER SECTION:
yourdomain.com. 1800 IN NS ns1.digitalocean.com.
yourdomain.com. 1800 IN NS ns2.digitalocean.com.
yourdomain.com. 1800 IN NS ns3.digitalocean.com.

;; ANSWER SECTION:
yourdomain.com. 300 IN A 192.0.2.123

Set Up DNS Records

Once you've changed your domain’s nameservers to your DNS provider, the next step is to add your DNS records there.

Here are the DNS records I used. You can copy them but make sure to replace with your own domain details.

TypeHostnameValueTTL (seconds)
A*.joeden.sitepoints to 34.201.50.10030
Awww.joeden.sitepoints to 34.201.50.10030
Adashboard.joeden.sitepoints to 34.201.50.10030
Ajoeden.sitepoints to 34.201.50.10030

The IP 34.201.50.100 is my test machine's public IP. Point the DNS records to your machine's public IP.

The dashboard.joeden.site is used to access the Traefik dashboard.

You can also use shorthand names since they mean the same:

TypeHostnameValueTTL (seconds)
A*.joeden.sitepoints to 34.201.50.10030
Awwwpoints to 34.201.50.10030
Adashboardpoints to 34.201.50.10030
A@points to 34.201.50.10030

If you set this up in DigitalOcean, your DNS records should look like this:

TypeHostnameValueTTL (seconds)
NSjoeden.sitepoints to ns1.digitalocean.com30
NSjoeden.sitepoints to ns2.digitalocean.com30
NSjoeden.sitepoints to ns3.digitalocean.com30
A*.joeden.sitepoints to 34.201.50.10030
Awww.joeden.sitepoints to 34.201.50.10030
Adashboard.joeden.sitepoints to 34.201.50.10030
Ajoeden.sitepoints to 34.201.50.10030

Clone the Repository

Github repo: joseeden/labs-traefik

Login to the public cloud VM and clone the project repository from GitHub.

git clone https://github.com/joseeden/labs-traefik.git
cd labs-traefik/05-middleware/05-redirects

Project structure:

05-middleware
└── 05-redirects
├── .env
├── .gitignore
├── docker-compose.redirect.yml
├── traefik.dns.yml
└── usersfile

Create an API Token

To allow Traefik to update DNS records automatically, you’ll need a token from your DNS provider. In my setup, I'm using DigitalOcean as my DNS provider.

  1. Go to your DNS provider’s dashboard (e.g., DigitalOcean)
  2. Generate a new API token with DNS access
  3. Copy the token. This will be added to the Docker compose

This token is used by Traefik to prove domain ownership via the DNS challenge.

info

To generate the token in DigitalOcean please see Generate an API Token.

Create the .env file

Once you have the API token, create a .env:

.env
DO_AUTH_TOKEN=your_real_token_here

Create the Passwords

For this lab, we'll use basic authentication, so we need a safe way to store user passwords. Passwords must be hashed before adding them to the users file.

To create hashed passwords, install the tool htpasswd:

sudo apt install -y apache2-utils

Here are example user credentials. You can change them if you want:

UsernamePassword
johnsmithThr3@tl3u3lw!dN!QHt
janedoe@Ll!$szM3lLiND@h0oD

Generate a hash with this command:

htpasswd -nb johnsmith 'Thr3@tl3u3lw!dN!QHt' 

You should see output like:

johnsmith:$apr1$cipim6NJ$LK11Xtf0t92UvxjKCV8ii0

Do the same for each user.

Next, create a file named usersfile in the same folder as your Docker compose file. Put all hashed credentials here, one user per line:

johnsmith:$apr1$cipim6NJ$LK11Xtf0t92UvxjKCV8ii0
janedoe:$apr1$t65c7tuF$Qscp40RYl.Tq02pUnSv5r1

Add usersfile to your .gitignore file to keep it out of version control:

.gitignore
usersfile

This usersfile will be used in the Docker compose setup next.

Configure the Docker Compose File

In the Docker compose file:

  • The Http router listens on port 80 and only redirects requests to Https
  • The Https router listens on port 443 and handles the app service with full middlewares
  • Redirect middleware is set to permanent and forces Http to Https
  • TLS and letsencrypt are enabled on the Https router

This config sends all Http requests to the secure Https service, where all middleware runs.

info

Update your domain and DNS with your provider tokens

version: "3"

services:
traefik:
image: traefik:v2.3
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./letsencrypt:/letsencrypt
- ./traefik.dns.yml:/etc/traefik/traefik.yml
- ./usersfile:/usersfile:ro # <-- mount your users file here
environment:
- DO_AUTH_TOKEN=${DO_AUTH_TOKEN}
env_file:
- .env

# Catapp service
catapp:
image: mikesir87/cats:1.0
labels:
- "traefik.enable=true"
# Routers - Catapp HTTP
- "traefik.http.routers.catapp.rule=Host(`lab.yourdomain.com`)"
- "traefik.http.routers.catapp.entrypoints=web"
- "traefik.http.routers.catapp.middlewares=test-redirectscheme"
# Routers - Catapp HTTP Secure
- "traefik.http.routers.catapp-secure.rule=Host(`lab.yourdomain.com`)"
- "traefik.http.routers.catapp-secure.entrypoints=websecure"
- "traefik.http.routers.catapp-secure.tls.certresolver=myresolver"
- "traefik.http.routers.catapp-secure.middlewares=test-auth,test-compress,test-errorpages,test-ratelimit"
# Services - Catapp HTTP Secure
- "traefik.http.services.catapp-secure.loadbalancer.server.port=5000"
# Middleware - Redirect Scheme HTTP -> HTTPS
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
# Middleware BasicAuth using usersfile
- "traefik.http.middlewares.test-auth.basicauth.usersfile=/usersfile"
# Compress Middleware
- "traefik.http.middlewares.test-compress.compress=true"
# Error Pages Middleware
- "traefik.http.middlewares.test-errorpages.errors.status=400-599"
- "traefik.http.middlewares.test-errorpages.errors.service=error"
- "traefik.http.middlewares.test-errorpages.errors.query=/{status}.html"
# Rate Limit Middleware
- "traefik.http.middlewares.test-ratelimit.ratelimit.average=2"

# Error Page service
error:
image: guillaumebriday/traefik-custom-error-pages
labels:
- "traefik.enable=true"
- "traefik.http.routers.error.rule=Host(`error.localhost`)"
- "traefik.http.routers.error.service=error"
- "traefik.http.services.error.loadbalancer.server.port=80"
# - traefik.frontend.rule=PathPrefixStrip:/wait
- "traefik.http.routers.error.entrypoints=web"

We also have the Traefik configuration in the traefik.dns.yml. Make sure to use your own email in the email: section.

api:
dashboard: true
insecure: true

providers:
docker:
exposedByDefault: false

log:
level: INFO

entryPoints:
web:
address: ":80"
websecure:
address: ":443"
traefik:
address: ":8080"

# Challenge DNS
certificatesResolvers:
myresolver:
acme:
email: josemanuelitoeden@gmail.com
storage: /letsencrypt/acme.json
dnsChallenge:
provider: digitalocean
delayBeforeCheck: 0

# Dashboard router
http:
routers:
traefik:
rule: Host(`dashboard.joeden.site`) # or use your domain + a subdomain
entryPoints:
- traefik
service: api@internal
# middlewares: # DO NOT DO IN PRODUCTION
# - auth # Disables the authentication

Deploy the Config

Before applying changes, make sure these files are in place:

└── 05-redirects
├── .env
├── .gitignore
├── docker-compose.redirect.yml
├── letsencrypt
│ └── test
├── traefik.dns.yml
└── usersfile

Manually load the .env before deploying:

set -a
source .env
set +a

Deploy the stack with the redirect config:

docker stack deploy -c docker-compose.redirect.yml traefik

Output:

Creating network traefik_default
Creating service traefik_error
Creating service traefik_traefik
Creating service traefik_catapp

Check running services:

docker service ls

Expected output:

ID             NAME              MODE         REPLICAS   IMAGE                                               PORTS
m02cx2dcaegp traefik_catapp replicated 1/1 mikesir87/cats:1.0
zaero8i61mnf traefik_error replicated 1/1 guillaumebriday/traefik-custom-error-pages:latest
t3fscw3uvxg9 traefik_traefik replicated 1/1 traefik:v2.3

Check the logs to verify that the certificate was issued:

docker service logs traefik_traefik

Look for DNS challenge messages and a successful certificate request:

Testing certificate renew..." providerName=myresolver.acme 

Testing

Open the dashboard in your browser:

http://dashboard.yourdomain.com:8080

Go to Services and make sure you see the catapp-secure service listed.

Click on the catapp-secure service and scroll down to Used by Routers. You should see two routers attached, with only the first router having TLS enabled.

Click on catapp@docker. This router has only the redirectscheme middleware and routes to catapp-service.

Go back to HTTP Routers and select catapp-secure@docker.

You should see the catapp-secure router with TLS enabled and multiple middlewares applied.

Finally, test the application in your browser. Use the HTTP address:

http://lab.yourdomain.com/ 

You will see it automatically redirect from HTTP to HTTPS, showing the Redirect middleware works.

Next, try entering invalid credentials. It should fail, confirming the BasicAuth middleware works.

Now use valid credentials. The login should succeed as expected.

Refresh the page several times. After a few refreshes, you will hit the rate limit and see the error page. This confirms the Rate Limit middleware and Error Page middleware work.

Finally, enter an invalid URL to see a professional 404 error page.

Cleanup

Delete the deployed stack:

docker stack rm traefik 

You can also delete the .env:

rm -f .env 

Go to your DNS provider and delete the API token.