Error 404 on any web app using PathPrefix --> StripPrefix Middlewares

Hi everyone,
Currently setting up my second Traefik reverse proxy, I'm struggling with a 404 error on all web app forwarded by traefik.
Note that I am behind a company proxy on a server (RedHat) thus there are several modifications:

  • I'm using Podman instead of Docker
  • I couldn't make docker-socket-proxy to work so I ended up with a basicline added in the volume section:
    - /run/podman/podman.sock:/var/run/docker.sock:ro
  • I am provided by my company to use their tls certificate ( given as a .crt, .key and .pem)
  • I cannot expose my different webapps as prefix CNAMES, instead I must use forward slashes (e.g. mydomainname/portainer, mydonainname/traefik)

I have correclty setup up:

  • Traefik dashboard (have access in http at 8080)
  • htpasswd for my basic-auth middleware with Docker Secrets
  • TLS with the own company certificates
  • Automatic http-to-httpsredirection (using middleware)
  • correctly created different middlewares

I will provide you below with all the files for better understanding. Note that the problem I'm facing is not related to TLS as the error existed already using only http.

For every webapps I have setup (I'll take the example of linuxserver/code-server) I can access them at the basic opened port:
http://mydomainname:8443

but I cannot access them via traefik:
http://mydomainname/code
or
https://mydomainname/code

I get in any case a 404 error. This is the case for any other apps (traefik dashboard included).
Notice that when for some particular app, I decide to use middleware-basic-auth instead of no-auth, then I indeed have the login prompt that appears, and the authentification is successful (so htpasswd is well configured) and then back to 404.

Here is my compose.yml:

version: '3.3'

networks:
  t2_proxy:
    name: t2_proxy
    driver: bridge


secrets:
  htpasswd:
    file: $PODMANDIR/secrets/htpasswd
  code_server_hpwd:
    file: $PODMANDIR/secrets/code_server_hpwd


services:
  traefik:
    image: traefik:v2.11
    container_name: traefik
    restart: always
    user: root
    networks:
      - t2_proxy
    secrets:
      - htpasswd
    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host
      - target: 8080
        published: 8080
        protocol: tcp
        mode: host
    volumes:
      - $PODMANDIR/appdata/traefik/rules:/rules
      - $PODMANDIR/appdata/traefik/acme/acme.json:/acme.json
      - $PODMANDIR/appdata/traefik/traefik.log:/traefik.log
      - $PODMANDIR/appdata/traefik/certs:/certs
      - /run/podman/podman.sock:/var/run/docker.sock:ro
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--entrypoints.http.address=:80"
      - "--entrypoints.https.address=:443"
      - "--entrypoints.traefik.address=:8080"
      - "--entrypoints.https.http.tls.options=tls-opts@file"
      - "--api=true"
      - "--api.dashboard=true"
      - "--log=true"
      - "--log.level=DEBUG"
      - "--accessLog=false"
      - "--accessLog.filePath=/traefik.log"
      - "--accessLog.bufferingSize=100"
      - "--accessLog.filters.statusCodes=400-499"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=t2_proxy"
      - "--providers.docker.swarmMode=false"
      - "--providers.file.directory=/rules"
      - "--providers.file.watch=true"
      - "--serversTransport.insecureSkipVerify=true"
    environment:
      - HTPASSWD_FILE=/run/secrets/htpasswd
    labels:
      - "traefik.enable=true"
      # HTTP Routers
      - "traefik.http.routers.traefik-rtr.entrypoints=https"
      - "traefik.http.routers.traefik-rtr.rule=PathPrefix(`/traefik`)"
      # Servides - API
      - "traefik.http.routers.traefik-rtr.service=api@internal"
      # HTTP to HTTPS Redirect
      #- "traefik.http.routers.http-catchall.entrypoints=http"
      #- "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
      #- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
      #- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      # Middlewares
      - "traefik.http.routers.traefik-rtr.middlewares=chain-no-auth@file"

      

  portainer:
    container_name: portainer
    image: portainer/portainer-ce:latest
    restart: always
    networks:
      - t2_proxy
    ports:
      - 9000:9000 # http
      - 9443:9443 # https
    volumes:
      - $PODMANDIR/appdata/portainer/data:/data
      - /run/podman/podman.sock:/var/run/docker.sock:Z
    environment:
      - TZ=$TZ
    labels:
      - "traefik.enable=true"
      # HTTP Routers
      - "traefik.http.routers.portainer-rtr.entrypoints=https"
      - "traefik.http.routers.portainer-rtr.rule=PathPrefix(`/portainer`)"
      # HTTP Services
      - "traefik.http.routers.portainer-rtr.service=portainer-svc"
      - "traefik.http.services.portainer-svc.loadbalancer.server.port=9000"
      # Middlewares
      - "traefik.http.routers.portainer-rtr.middlewares=chain-no-auth@file"



  code-server:
    image: linuxserver/code-server:latest
    container_name: code-server
    restart: unless-stopped
    networks:
      - t2_proxy
    ports:
      - 8443:8443
    #secrets:
    #  - code_server_hpwd
    environment:
      - PUID=21051
      - PGID=21051
      - TZ=Europe/Zurich
      #- FILE__HASHED_PASSWORD=/run/secrets/code_server_hpwd
    volumes:
      - $PODMANDIR/appdata/code-server:/config
      - /home/tbs:/tbs
    labels:
      - "traefik.enable=true"
      # HTTP Routers
      - "traefik.http.routers.code-server-rtr.entrypoints=https"
      - "traefik.http.routers.code-server-rtr.rule=PathPrefix(`/code`)"
      # HTTP Services
      - "traefik.http.routers.code-server-rtr.service=code-server-svc"
      - "traefik.http.services.code-server-svc.loadbalancer.server.port=8443"
      # Middlewares
      - "traefik.http.routers.code-server-rtr.middlewares=chain-basic-auth@file"

appdata/traefik/rules/middlewares-chains.yml:

http:
  middlewares:
    chain-no-auth:
      chain:
        middlewares:
          - "middlewares-rate-limit@file"
          - "middlewares-https-redirectscheme@file"
          - "middlewares-secure-headers@file"
          
    chain-basic-auth:
      chain:
        middlewares:
          - "middlewares-rate-limit@file"
          - "middlewares-https-redirectscheme@file"
          - "middlewares-secure-headers@file"
          - "middlewares-basic-auth@file"

appdata/traefik/rules/middlewares.yml:

http:
  middlewares:
    middlewares-basic-auth:
      basicAuth:
        realm: "Traefik2 Basic Auth"
        usersFile: "/run/secrets/htpasswd" # be sure to mount the volume through docker-compose.yml

    middlewares-rate-limit:
      rateLimit:
        average: 100
        burst: 50

    middlewares-https-redirectscheme:
      redirectscheme:
        scheme: "https"
        permanent: true

    middlewares-secure-headers:
      headers:
        accessControlAllowMethods: ["GET", "OPTIONS", "PUT"]
        accessControlMaxAge: 100
        hostsProxyHeaders: ["X-Forwarded-Host"]
        stsSeconds: 63072000
        stsIncludeSubdomains: true
        stsPreload: true
        forceSTSHeader: true
        # customFrameOptionsValue: "allow-from https:example.com" # CSP takes care of this but may be needed for organizr.
        contentTypeNosniff: true
        browserXssFilter: true
        referrerPolicy: "same-origin"
        permissionsPolicy: "camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=()"
        customResponseHeaders:
          X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex,"
          server: ""

appdata/traefic/rules/tls-opts.yml:

tls:
  certificates:
    - certFile: "/certs/cert.pem"
      keyFile: "/certs/cert.pem"
      stores:
        - default
      
  options:
    tls-opts:
      minVersion: VersionTLS12
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
        - TLS_AES_128_GCM_SHA256
        - TLS_AES_256_GCM_SHA384
        - TLS_CHACHA20_POLY1305_SHA256
        - TLS_FALLBACK_SCSV
      curvePreferences:
        - CurveP521
        - CurveP384
      sniStrict: true

And traefik.logs:

time="2024-05-22T15:22:15Z" level=debug msg="Adding certificate for domain(s) hidden,hidden.corp.hidden.ch"
time="2024-05-22T15:22:15Z" level=debug msg="No default certificate, fallback to the internal generated certificate" tlsStoreName=default
time="2024-05-22T15:22:15Z" level=debug msg="Added outgoing tracing middleware api@internal" routerName=api@internal middlewareName=tracing middlewareType=TracingForwarder entryPointName=traefik
time="2024-05-22T15:22:15Z" level=debug msg="Added outgoing tracing middleware dashboard@internal" entryPointName=traefik routerName=dashboard@internal middlewareName=tracing middlewareType=TracingForwarder
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" middlewareType=StripPrefix entryPointName=traefik routerName=dashboard@internal middlewareName=dashboard_stripprefix@internal
time="2024-05-22T15:22:15Z" level=debug msg="Adding tracing to middleware" entryPointName=traefik routerName=dashboard@internal middlewareName=dashboard_stripprefix@internal
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" routerName=dashboard@internal middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex entryPointName=traefik
time="2024-05-22T15:22:15Z" level=debug msg="Setting up redirection from ^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$ to ${1}/dashboard/" middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex entryPointName=traefik routerName=dashboard@internal
time="2024-05-22T15:22:15Z" level=debug msg="Adding tracing to middleware" entryPointName=traefik routerName=dashboard@internal middlewareName=dashboard_redirect@internal
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" entryPointName=traefik middlewareType=Recovery middlewareName=traefik-internal-recovery
time="2024-05-22T15:22:15Z" level=debug msg="Added outgoing tracing middleware api@internal" middlewareType=TracingForwarder entryPointName=https routerName=traefik-rtr@docker middlewareName=tracing
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" entryPointName=https routerName=traefik-rtr@docker middlewareName=chain-no-auth@file middlewareType=Chain
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" middlewareName=middlewares-secure-headers@file middlewareType=Headers routerName=traefik-rtr@docker entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Setting up secureHeaders from {map[] map[X-Robots-Tag:none,noarchive,nosnippet,notranslate,noimageindex, server:] false [] [GET OPTIONS PUT] [] [] [] 100 false [] [X-Forwarded-Host] false false  map[] false 63072000 true true true false  true true    same-origin  camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=() false}" routerName=traefik-rtr@docker entryPointName=https middlewareName=middlewares-secure-headers@file middlewareType=Headers
time="2024-05-22T15:22:15Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[X-Robots-Tag:none,noarchive,nosnippet,notranslate,noimageindex, server:] false [] [GET OPTIONS PUT] [] [] [] 100 false [] [X-Forwarded-Host] false false  map[] false 63072000 true true true false  true true    same-origin  camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=() false}" middlewareType=Headers routerName=traefik-rtr@docker entryPointName=https middlewareName=middlewares-secure-headers@file
time="2024-05-22T15:22:15Z" level=debug msg="Adding tracing to middleware" entryPointName=https routerName=traefik-rtr@docker middlewareName=middlewares-secure-headers@file
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" routerName=traefik-rtr@docker middlewareName=middlewares-https-redirectscheme@file middlewareType=RedirectScheme entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Setting up redirection to https " routerName=traefik-rtr@docker middlewareName=middlewares-https-redirectscheme@file middlewareType=RedirectScheme entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" entryPointName=https routerName=traefik-rtr@docker middlewareName=middlewares-rate-limit@file middlewareType=RateLimiterType
time="2024-05-22T15:22:15Z" level=debug msg="Using IPStrategy" middlewareName=middlewares-rate-limit@file middlewareType=RateLimiterType entryPointName=https routerName=traefik-rtr@docker
time="2024-05-22T15:22:15Z" level=debug msg="Adding tracing to middleware" entryPointName=https routerName=traefik-rtr@docker middlewareName=middlewares-rate-limit@file
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" middlewareName=pipelining middlewareType=Pipelining entryPointName=https routerName=code-server-rtr@docker serviceName=code-server-svc
time="2024-05-22T15:22:15Z" level=debug msg="Creating load-balancer" routerName=code-server-rtr@docker serviceName=code-server-svc entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Creating server 0 http://10.89.1.192:8443" entryPointName=https routerName=code-server-rtr@docker serviceName=code-server-svc serverName=0
time="2024-05-22T15:22:15Z" level=debug msg="child http://10.89.1.192:8443 now UP"
time="2024-05-22T15:22:15Z" level=debug msg="Propagating new UP status"
time="2024-05-22T15:22:15Z" level=debug msg="Added outgoing tracing middleware code-server-svc" entryPointName=https middlewareType=TracingForwarder middlewareName=tracing routerName=code-server-rtr@docker
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" middlewareType=Chain entryPointName=https routerName=code-server-rtr@docker middlewareName=chain-basic-auth@file
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" entryPointName=https routerName=code-server-rtr@docker middlewareType=BasicAuth middlewareName=middlewares-basic-auth@file
time="2024-05-22T15:22:15Z" level=debug msg="Adding tracing to middleware" routerName=code-server-rtr@docker middlewareName=middlewares-basic-auth@file entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" entryPointName=https routerName=code-server-rtr@docker middlewareName=middlewares-secure-headers@file middlewareType=Headers
time="2024-05-22T15:22:15Z" level=debug msg="Setting up secureHeaders from {map[] map[X-Robots-Tag:none,noarchive,nosnippet,notranslate,noimageindex, server:] false [] [GET OPTIONS PUT] [] [] [] 100 false [] [X-Forwarded-Host] false false  map[] false 63072000 true true true false  true true    same-origin  camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=() false}" entryPointName=https routerName=code-server-rtr@docker middlewareName=middlewares-secure-headers@file middlewareType=Headers
time="2024-05-22T15:22:15Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[X-Robots-Tag:none,noarchive,nosnippet,notranslate,noimageindex, server:] false [] [GET OPTIONS PUT] [] [] [] 100 false [] [X-Forwarded-Host] false false  map[] false 63072000 true true true false  true true    same-origin  camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=() false}" routerName=code-server-rtr@docker middlewareName=middlewares-secure-headers@file middlewareType=Headers entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Adding tracing to middleware" entryPointName=https routerName=code-server-rtr@docker middlewareName=middlewares-secure-headers@file
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" routerName=code-server-rtr@docker middlewareName=middlewares-https-redirectscheme@file middlewareType=RedirectScheme entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Setting up redirection to https " entryPointName=https routerName=code-server-rtr@docker middlewareName=middlewares-https-redirectscheme@file middlewareType=RedirectScheme
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" entryPointName=https routerName=code-server-rtr@docker middlewareName=middlewares-rate-limit@file middlewareType=RateLimiterType
time="2024-05-22T15:22:15Z" level=debug msg="Using IPStrategy" entryPointName=https routerName=code-server-rtr@docker middlewareName=middlewares-rate-limit@file middlewareType=RateLimiterType
time="2024-05-22T15:22:15Z" level=debug msg="Adding tracing to middleware" routerName=code-server-rtr@docker middlewareName=middlewares-rate-limit@file entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" serviceName=portainer-svc middlewareName=pipelining middlewareType=Pipelining entryPointName=https routerName=portainer-rtr@docker
time="2024-05-22T15:22:15Z" level=debug msg="Creating load-balancer" entryPointName=https routerName=portainer-rtr@docker serviceName=portainer-svc
time="2024-05-22T15:22:15Z" level=debug msg="Creating server 0 http://10.89.1.191:9000" entryPointName=https routerName=portainer-rtr@docker serviceName=portainer-svc serverName=0
time="2024-05-22T15:22:15Z" level=debug msg="child http://10.89.1.191:9000 now UP"
time="2024-05-22T15:22:15Z" level=debug msg="Propagating new UP status"
time="2024-05-22T15:22:15Z" level=debug msg="Added outgoing tracing middleware portainer-svc" routerName=portainer-rtr@docker middlewareName=tracing middlewareType=TracingForwarder entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" routerName=portainer-rtr@docker middlewareName=chain-no-auth@file middlewareType=Chain entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" entryPointName=https middlewareName=middlewares-secure-headers@file middlewareType=Headers routerName=portainer-rtr@docker
time="2024-05-22T15:22:15Z" level=debug msg="Setting up secureHeaders from {map[] map[X-Robots-Tag:none,noarchive,nosnippet,notranslate,noimageindex, server:] false [] [GET OPTIONS PUT] [] [] [] 100 false [] [X-Forwarded-Host] false false  map[] false 63072000 true true true false  true true    same-origin  camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=() false}" routerName=portainer-rtr@docker entryPointName=https middlewareName=middlewares-secure-headers@file middlewareType=Headers
time="2024-05-22T15:22:15Z" level=debug msg="Setting up customHeaders/Cors from {map[] map[X-Robots-Tag:none,noarchive,nosnippet,notranslate,noimageindex, server:] false [] [GET OPTIONS PUT] [] [] [] 100 false [] [X-Forwarded-Host] false false  map[] false 63072000 true true true false  true true    same-origin  camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=() false}" middlewareType=Headers routerName=portainer-rtr@docker entryPointName=https middlewareName=middlewares-secure-headers@file
time="2024-05-22T15:22:15Z" level=debug msg="Adding tracing to middleware" routerName=portainer-rtr@docker middlewareName=middlewares-secure-headers@file entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" routerName=portainer-rtr@docker middlewareName=middlewares-https-redirectscheme@file middlewareType=RedirectScheme entryPointName=https
time="2024-05-22T15:22:15Z" level=debug msg="Setting up redirection to https " middlewareName=middlewares-https-redirectscheme@file middlewareType=RedirectScheme entryPointName=https routerName=portainer-rtr@docker
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" middlewareName=middlewares-rate-limit@file middlewareType=RateLimiterType entryPointName=https routerName=portainer-rtr@docker
time="2024-05-22T15:22:15Z" level=debug msg="Using IPStrategy" middlewareName=middlewares-rate-limit@file middlewareType=RateLimiterType entryPointName=https routerName=portainer-rtr@docker
time="2024-05-22T15:22:15Z" level=debug msg="Adding tracing to middleware" entryPointName=https routerName=portainer-rtr@docker middlewareName=middlewares-rate-limit@file
time="2024-05-22T15:22:15Z" level=debug msg="Creating middleware" entryPointName=https middlewareName=traefik-internal-recovery middlewareType=Recovery
time="2024-05-22T15:22:15Z" level=warning msg="No domain found in rule PathPrefix(`/code`), the TLS options applied for this router will depend on the SNI of each request" entryPointName=https routerName=code-server-rtr@docker
time="2024-05-22T15:22:15Z" level=warning msg="No domain found in rule PathPrefix(`/portainer`), the TLS options applied for this router will depend on the SNI of each request" entryPointName=https routerName=portainer-rtr@docker
time="2024-05-22T15:22:15Z" level=warning msg="No domain found in rule PathPrefix(`/traefik`), the TLS options applied for this router will depend on the SNI of each request" entryPointName=https routerName=traefik-rtr@docker
time="2024-05-22T15:22:27Z" level=debug msg="Authentication failed" middlewareName=middlewares-basic-auth@file middlewareType=BasicAuth
time="2024-05-22T15:22:35Z" level=debug msg="Authentication succeeded" middlewareName=middlewares-basic-auth@file middlewareType=BasicAuth
time="2024-05-22T15:22:39Z" level=debug msg="Authentication succeeded" middlewareName=middlewares-basic-auth@file middlewareType=BasicAuth
time="2024-05-22T15:22:46Z" level=debug msg="Authentication succeeded" middlewareName=middlewares-basic-auth@file middlewareType=BasicAuth
time="2024-05-22T15:22:51Z" level=debug msg="Authentication succeeded" middlewareType=BasicAuth middlewareName=middlewares-basic-auth@file

Thank you all for your time and your help!

You can’t just place web GUI apps under a path prefix, as they usually assume they are on root (/).

Even if you get the first page to load with stripprefix middleware, it will usually include absolute links (like /static/script.js), which won’t work with your path prefix.

The web app needs to enable some kind of "base path" setting to work with path prefix.

That’s why best practice is using (sub-) domains.

Indeed thanks for pointing this out, this is the problem.
I cannot use subomains at my company as it would imply bringing more url to the internal DNS (and cannot modify /etc/hosts on my machine as it necessitate admin priviledges).

I tried to use middlewares to strip the pathPrefix:


    strip-traefik-prefix:
      stripPrefix:
        prefixes:
          - "/traefik"  
    
    strip-portainer-prefix:
      stripPrefix:
        prefixes:
          - "/portainer"


    strip-code-prefix:
      stripPrefix:
        prefixes:
          - "/code"

and in the compose:

traefik:
  labels:
      - "traefik.http.routers.traefik-rtr.middlewares=strip-traefik-prefix@file,chain-no-auth@file"


portainer:
  labels:
      - "traefik.http.routers.portainer-rtr.middlewares=strip-portainer-prefix@file,chain-no-auth@file"


code-server:
  labels:
      - "traefik.http.routers.code-server-rtr.middlewares=strip-code-prefix@file,chain-no-auth@file"

but without real success as it depends on each apps.
--> I managed to make portainer work with this solution, traefik dashboard loads, but not every components of the page and code-server still gives a 404 error.
--> This is weird because even with the strip, the /portainer and the /traefik stay in the url path. Only /code is correctly removed ---> and this even if in the end only the portainer app is working (and still has /portainer in the url even tho I have the strip option)

I also tried different middlewares:

    replace-traefik-path:
      replacePathRegex:
        regex: "^/traefik/(.*)"
        replacement: "/$1"

    replace-portainer-path:
      replacePathRegex:
        regex: "^/portainer/(.*)"
        replacement: "/$1"

    replace-code-path:
      replacePathRegex:
        regex: "^/code/(.*)"
        replacement: "/$1"

But this is even worse, no apps work.

Except praying for each app to indivually to have some king of Base Path env variable,
Has anyone managed to find a consistent solution to this problem?

Yes, use (sub-) domains :wink:

Traefik Dashboard only works on /dashboard and also needs /api.


You could use an external DNS for (sub-) domains, use a different domain. That DNS can even resolve to private IPs not reachable on the Internet - if it’s for internal use only.

If only I could this is such a pain to be forced to use PathPrefixes....

So I finally made it working for code-server, portainer and traefik dashboard. It is only trial and error.
For anyone attempted to pursue with pathprefix, I give you below my working configurations:

For any web apps you will need to setup a strip-prefix middleware. This removes the prefix to make the app backend believes it is at the root path.

  • For Traefik Dashboard and api endpoints, don't forget to add Host(`$DOMAINNAME`) this was the problem for me. + the strip middleware
  • For Portainer, the strip middleware made it work
  • For linuxserver/code-server, the working endpoint is at /code/ so you need to tell traefik to redirect your incoming /code requests to /code/. For this I use a redirect-code middleware + the strip middleware. Notice the redirect-code middleware in the code below.

In general, be careful with the regex if you use some (for redirection for instance).
Each app will have its specific configuration.

traefik:
    labels:
      - "traefik.enable=true"
      # HTTP Routers
      - "traefik.http.routers.traefik-rtr.entrypoints=https"
      - "traefik.http.routers.traefik-rtr.rule=Host(`$DOMAINNAME`) && (PathPrefix(`/traefik`) || PathPrefix(`/api`))"
      # HTTP Services - API
      - "traefik.http.routers.traefik-rtr.service=api@internal"
      # HTTP to HTTPS Redirect
      - "traefik.http.routers.http-catchall.entrypoints=http"
      - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      # Middlewares
      - "traefik.http.routers.traefik-rtr.middlewares=strip-traefik-prefix@file,chain-basic-auth@file"
portainer:
    labels:
      - "traefik.enable=true"
      # HTTP Routers
      - "traefik.http.routers.portainer-rtr.entrypoints=https"
      - "traefik.http.routers.portainer-rtr.rule=Host(`$DOMAINNAME`) && PathPrefix(`/portainer`)"
      # HTTP Services
      - "traefik.http.routers.portainer-rtr.service=portainer-svc"
      - "traefik.http.services.portainer-svc.loadbalancer.server.port=9000"
      # Middlewares
      - "traefik.http.routers.portainer-rtr.middlewares=strip-portainer-prefix@file,chain-basic-auth@file"
code-server:
    labels:
      - "traefik.enable=true"
      # HTTP Routers
      - "traefik.http.routers.code-server-rtr.entrypoints=https"
      - "traefik.http.routers.code-server-rtr.rule=Host(`$DOMAINNAME`) && (PathPrefix(`/code/`) || PathPrefix(`/code`))"
      # HTTP Services
      - "traefik.http.routers.code-server-rtr.service=code-server-svc"
      - "traefik.http.services.code-server-svc.loadbalancer.server.port=8443"
      # Middlewares
      - "traefik.http.routers.code-server-rtr.middlewares=strip-code-prefix@file,redirect-code@file,chain-basic-auth@file"

And my middlewares:

http:
  middlewares:
    strip-traefik-prefix:
      stripPrefix:
        prefixes:
          - "/traefik"  
    
    strip-portainer-prefix:
      stripPrefix:
        prefixes:
          - "/portainer"

    strip-code-prefix:
      stripPrefix:
        prefixes:
          - "/code/"
  
    redirect-code:
      redirectRegex:
        regex: "/code$"
        replacement: "/code/"
        permanent: true

Hope this helps. But really if you can use subdomains with DNS resolvers, don't risk the messy PathPrefix configuration. This is such a struggle! Thanks @bluepuma77 for your fast replies!

Nice hack, but that means no other application can use the /api path.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.