Skip to content

Instantly share code, notes, and snippets.

@kekru
Last active October 16, 2024 09:52
Show Gist options
  • Save kekru/d088be6a3fa844089ae62d80c077bb38 to your computer and use it in GitHub Desktop.
Save kekru/d088be6a3fa844089ae62d80c077bb38 to your computer and use it in GitHub Desktop.
Traefik redirect / (root) to sub path with Docker labels

Traefik: redirect base or root path to a subpath

This is tested with Traefik 1.7

This is how to redirect the root or base path to a sub path in Traefik using Docker labels:
Goals

  • https://example.com -> https://example.com/abc/xyz/
  • https://example.com/ -> https://example.com/abc/xyz/
  • https://example.com/something -> no redirect

We will match <begin of line>https://<any chars but not slash AS group1><slash or nothing><end of line>
and replace it with https://<group1>/abc/xyz/.
In regex we have to escape a / character by \/. In docker-compose labels we need to escape again, so that it becomes \\\\/.
We also need to escape $ to $$ because of docker-compose.

labels:
  - "traefik.frontend.rule=Host:example.com"
  - "traefik.frontend.redirect.regex=^https:\\\\/\\\\/([^\\\\/]+)\\\\/?$$"
  - "traefik.frontend.redirect.replacement=https://$$1/abc/xyz/"
  - "traefik.port=80"
  - "traefik.enable=true"
@yunkuangao
Copy link

Thank you sincerely.

@kekru
Copy link
Author

kekru commented Apr 9, 2023

@idhamari sorry for late answer, but for me this is working:

services:

  traefik:
    image: "traefik:2.9.10"
    container_name: traefik
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  app1:
    image: traefik/whoami:v1.8.7
    container_name: app1
    scale: 1
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app1.entrypoints=web"
      - "traefik.http.routers.app1.rule=PathPrefix(`/app1`)"
      - "traefik.http.routers.app1.middlewares=add-context1"
      - "traefik.http.middlewares.add-context1.redirectregex.regex=^(.+/app1)$$"
      - "traefik.http.middlewares.add-context1.redirectregex.replacement=$$1/"
  app2:
    image: traefik/whoami:v1.8.7
    container_name: app2
    scale: 1
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app2.entrypoints=web"                  
      - "traefik.http.routers.app2.rule=PathPrefix(`/app2`)"
      - "traefik.http.routers.app2.middlewares=add-context2"
      - "traefik.http.middlewares.add-context2.redirectregex.regex=^(.+/app2)$$"
      - "traefik.http.middlewares.add-context2.redirectregex.replacement=$$1/"

Changes that I made:

  • removed Host(myexample.com), because you only have one host
  • changed add-context to add-context1 and add-context2 -> you need unique names and not reuse it between services
  • use PathPrefix instead of Path, so we can match /app1 and /app1/
  • easier regex: ^(.+/app1)$$ will match anything with ends with /app1
  • use image traefik/whoami:v1.8.7 instead of nginx only for easier testing

Try also to look at servername:8080 to see the traefik dashboard. There I could see that there was a problem using add-context in both services.
To evaluate regexes you can use https://regexr.com/

@y0nei
Copy link

y0nei commented Oct 7, 2023

anyone got it working for v3? It does an infinite redirect loop

@N-B-H
Copy link

N-B-H commented Mar 10, 2024

anyone got it working for v3? It does an infinite redirect loop

I had the same issue and spent pretty much a whole day to figure it out.
Simple redirect from my root directory to /de (or other subfolder whatsoever)

Valid for my-domain.com and www.my-domain.com, http and https.

For me, in my environment, self-hosted on coolify, this worked:


traefik.http.middlewares.redirect-to-de.redirectregex.regex=^(https?://(?:www\.)?my-domain\.com)/?$$
traefik.http.middlewares.redirect-to-de.redirectregex.replacement=$${1}/de

and the redirect-to-de middleware has to be added to each router. The full config is in my case:

traefik.enable=true
traefik.http.middlewares.gzip.compress=true
traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
traefik.http.middlewares.redirect-to-de.redirectregex.regex=^(https?://(?:www\.)?my-domain\.com)/?$$
traefik.http.middlewares.redirect-to-de.redirectregex.replacement=$${1}/de
traefik.http.middlewares.redirect-to-de.redirectregex.permanent=true
traefik.http.routers.http-0-mycontainer.entryPoints=http
traefik.http.routers.http-0-mycontainer.middlewares=redirect-to-https,redirect-to-de
traefik.http.routers.http-0-mycontainer.rule=Host(`my-domain.com`) && PathPrefix(`/`)
traefik.http.routers.http-0-mycontainer.service=http-0-mycontainer
traefik.http.routers.http-1-mycontainer.entryPoints=http
traefik.http.routers.http-1-mycontainer.middlewares=redirect-to-https,redirect-to-de
traefik.http.routers.http-1-mycontainer.rule=Host(`www.my-domain.com`) && PathPrefix(`/`)
traefik.http.routers.http-1-mycontainer.service=http-1-mycontainer
traefik.http.routers.https-0-mycontainer.entryPoints=https
traefik.http.routers.https-0-mycontainer.middlewares=gzip,redirect-to-de
traefik.http.routers.https-0-mycontainer.rule=Host(`my-domain.com`) && PathPrefix(`/`)
traefik.http.routers.https-0-mycontainer.service=https-0-mycontainer
traefik.http.routers.https-0-mycontainer.tls.certresolver=letsencrypt
traefik.http.routers.https-0-mycontainer.tls=true
traefik.http.routers.https-1-mycontainer.entryPoints=https
traefik.http.routers.https-1-mycontainer.middlewares=gzip,redirect-to-de
traefik.http.routers.https-1-mycontainer.rule=Host(`www.my-domain.com`) && PathPrefix(`/`)
traefik.http.routers.https-1-mycontainer.service=https-1-mycontainer
traefik.http.routers.https-1-mycontainer.tls.certresolver=letsencrypt
traefik.http.routers.https-1-mycontainer.tls=true
traefik.http.services.http-0-mycontainer.loadbalancer.server.port=80
traefik.http.services.http-1-mycontainer.loadbalancer.server.port=80
traefik.http.services.https-0-mycontainer.loadbalancer.server.port=80
traefik.http.services.https-1-mycontainer.loadbalancer.server.port=80


@pasquy73
Copy link

pasquy73 commented Oct 3, 2024

Hi, I'm not sure if is correct to add my question here, but I have a similar problem with Ingress (and Traefik). My Ingress works with this config:

- backend:
    service:
      name: scorpio
      port: 
        number: 9090
  path: /ngsi-ld
  pathType: Prefix 

using this request http://myservice.com/ngsi-ld/v1/entities?type=data. My scorpio backend manage all requests starting with prefix /ngsi-ld. Now, I want to use this new URL: http://myservice.com/api/v1/entities?type=data (i.e. replace /ngsi-ld with /api). I have to use path: /api in Ingress. How can I redirect requests to the backend (starting /ngsi-ld)?

@pasquy73
Copy link

pasquy73 commented Oct 4, 2024

I solved my problem. I used a Middleware k8s resource as follows:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: replace-api-with-ngsi-ld
  namespace: default  
spec:
  replacePathRegex:
    regex: "^/api(.*)"
    replacement: "/ngsi-ld$1"

then I had to add in my Ingress the annotation: traefik.ingress.kubernetes.io/router.middlewares: default-replace-api-with-ngsi-ld@kubernetescrd and set:

- backend:
    service:
      name: scorpio
      port: 
        number: 9090
  path: /api
  pathType: Prefix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment