Using Traefik Reverse Proxy to Redirect Local DNS Entry to Protected Domain

I have a domain registered with cloudflare, and from my internal network, I want to be able to type something like portainer.local into my browser, and then have that be redirected to portainer.mydomain.cc. I've done this successfully with NGINX Proxy Manager in the past with no cert warnings, etc., but I just can't seem to get it to work with Traefik.

To start, I have local cname record that points portainer.local to portainer.mydomain.cc, and a dns entry that points portainer.mydomain.cc to the my Traefik reverse proxy container.

Here is my Portainer container compose file that shows the Traefik labels:

version: '3.7'
services:
  portainer-ee:
    container_name: portainer
    image: 'portainer/portainer-ee:latest'
    restart: always
    network_mode: broker
    ports:
      - '8000:8000'
      - '9443:9443'
    volumes:
      - '/var/run/docker.sock:/var/run/docker.sock'
      - '/mnt/docker/mapped/config/portainer:/data'
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.portainer.entrypoints=https'
      - 'traefik.http.routers.portainer.rule=Host(`portainer.mydomain.cc`)'
      - 'traefik.http.routers.portainer.middlewares=portainer-https-redirect'
      - 'traefik.http.middlewares.portainer-https-redirect.redirectscheme.scheme=https'
      - 'traefik.http.routers.portainer-secure.entrypoints=https'
      - 'traefik.http.routers.portainer-secure.rule=Host(`portainer.mydomain.cc`)'
      - 'traefik.http.routers.portainer-secure.tls=true'
      - 'traefik.http.routers.portainer-secure.service=portainer'
      - 'traefik.http.services.portainer.loadbalancer.server.port=9443'
      - 'traefik.http.services.portainer.loadbalancer.server.scheme=https'
      - 'traefik.docker.network=broker'

For completeness sake, here is my Traefik container with labels:

version: '3.7'
services:
    traefik:
      image: traefik:latest
      container_name: traefik
      restart: always
      network_mode: broker
      security_opt:
        - no-new-privileges:true
      environment:
        - CF_API_EMAIL=myemailaddress@gmail.com
        - CF_DNS_API_TOKEN=mycloudflaretoken
      ports:
        - '80:80'
        - '443:443'
      volumes:
        - '/etc/localtime:/etc/localtime:ro'
        - '/var/run/docker.sock:/var/run/docker.sock:ro'
        - '/mnt/docker/mapped/config/traefik/config/traefik.yml:/traefik.yml:ro'
        - '/mnt/docker/mapped/config/traefik/config/acme.json:/acme.json'
        - '/mnt/docker/mapped/config/traefik/data:/data'
      labels:
        - 'traefik.enable=true'
        - 'traefik.http.routers.traefik.entrypoints=http'
        - 'traefik.http.routers.traefik.rule=Host(`traefik.mydomain.cc`)'
        - 'traefik.http.routers.traefik.middlewares=traefik-https-redirect'
        - 'traefik.http.routers.traefik-secure.entrypoints=https'
        - 'traefik.http.routers.traefik-secure.rule=Host(`traefik.mydomain.cc`)'
        - 'traefik.http.routers.traefik-secure.middlewares=traefik-auth'
        - 'traefik.http.routers.traefik-secure.tls=true'
        - 'traefik.http.routers.traefik-secure.tls.certresolver=cloudflare'
        - 'traefik.http.routers.traefik-secure.tls.domains[0].main=mydomain.cc'
        - 'traefik.http.routers.traefik-secure.tls.domains[0].sans=*.mydomain.cc'
        - 'traefik.http.routers.traefik-secure.service=api@internal'
        - 'traefik.http.middlewares.traefik-auth.basicauth.users=myusername:mypasswordhash'
        - 'traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https'
        - 'traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https'

Here is my trafeik.yml config:

api:
  dashboard: true
  debug: true
entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"
serversTransport:
  insecureSkipVerify: true
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    directory: "/data/"
    watch: true
certificatesResolvers:
  cloudflare:
    acme:
      email: myemailaddress@gmail.com
      storage: acme.json
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"

Last but not least is the yml file I made in the /data/ directory, referenced in the traefik.yml file:

http:
  middlewares:
    redirect-portainer-middleware:
      redirectRegex:
        permanent: true
        regex: "http://portainer.local/(.*)"
        replacement: "https://portainer.mydomain.cc/${1}"
  routers:
    redirect-portainer-router:
      rule: "Host(`portainer.local`)"
      entrypoints:
      - http
      middlewares: 
      - redirect-portainer-middleware
      tls:
        certresolver: "cloudflare"
      service: "noop@internal"

I admit I'm a little in over my head as I just started with Traefik the other day, and that NGINX Proxy Manager had been relatively easy to configure in comparison to my attempt here. Using a wildcard cert from letsencrypt (obtained from cloudflare), all I had to do was make a redirection host and point it to my proxy host, and it always worked. Am I on the right track here, or am I way off base? Any help I can get would be appreciated.

You used the word "redirect". Do you want the server to do a classical redirect, as in tell the browser to go to a different target address? Or should Traefik proxy (internally forward) all requests to the target service?

What would be the difference, and which approach is most efficient? If I can type some.address into my browser (on my internal network), and then have that address immediately change to my.protected.domain, I would consider that a win.

I guess have Traefik proxy all requests to the target service, because doing it that way, it’s my understanding that the browser isn’t even aware of the request. Is that correct?

I still don't understand your use case. You want to enter example.local but want to see example.com?

Usually TLS/SSL is used when browsing, but you can't really get a cert for example.local. How did you do that with NGINX Proxy Manager?

So maybe I wasn’t clear enough in what I was trying to do, and for that I apologize. Let’s use the portainer example again.

In NGINX Proxy Manager, I can go to the Redirection Hosts section and create an entry to point portainer.local to portainer.mydomain.cc. In the Proxy Hosts section, I’ll have a proxy host entry for portainer.mydomain.cc that uses a wildcard certificate.

So now, when I open a browser and enter portainer.local, I’m immediately redirected to https://portainer.mydomain.cc. I like doing it this way because it’s just easier to have a short entry to remember on my internal network that I can type instead of having to type out the whole fqdn. Obviously if I’m coming from outside my network, I can’t do anything like that, but from inside, this is purely for convenience.

I've cleaned up my config a bit to make it less confusing. I took out all the labels and am only using yaml files. The traefik.yml file has not changed.

Here is my portainer.yml:

http:
  routers:
    portainer:
      entryPoints:
        - "https"
      rule: "Host(`portainer.mydomain.cc`)"
      tls: {}
      service: portainer
  middlewares:
    portainer-https-redirect:
      redirectScheme:
        scheme: https
        permanent: true
  services:
    portainer:
      loadBalancer:
        servers:
          - url: "https://10.10.10.4:9443"
        passHostHeader: true

And here is the regex redirect I'm attempting from my portainer-redirect.yml:

http:
  routers:
    redirect-portainer-router:
      rule: "HostRegexp(`portainer.local`)"
      entrypoints:
        - https
      middlewares: 
        - redirect-portainer-middleware
      tls: {}
      service: "noop@internal"
  middlewares:
    redirect-portainer-middleware:
      redirectRegex:
        permanent: true
        regex: "https://portainer.local"
        replacement: "https://portainer.mydomain.cc"

It seems now that I am redirected, but not before a cert warning from my browser. Additionally, I'm not even sure why the entrypoint has to be https as the dns name I'm typing into my browser isn't an https address, but the above redirect doesn't work at all if I don't specify https and tls: {}. Is there any way to circumvent this? I'm not sure exactly how it worked in NGINX, but I didn't receive a cert warning and was immediately redirected to my protected domain.

I figured it out. My traefik.yml was actually the problem. Like I said, I don't have much experience with this, and I was more than a little confused, because every time I typed an address meant for the Traefik reverse proxy, my browser would first go secure and I would get a cert warning with no redirection of the actual domain name taking place. Only after I accepted was I then redirected to where I wanted to go.

My aha moment was when I thought about everything seemingly forced from http to https, no matter what. Sure enough, I checked the traefik.yml file (which I originally copied from someone else's example), and noticed this:

entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"

As soon as I commented out the http redirection to https, I then modified my below portainer-redirect.yml to the following:

http:
  routers:
    redirect-portainer-router:
      rule: "HostRegexp(`portainer.local`)"
      entrypoints:
        - http
      middlewares: 
        - redirect-portainer-middleware
      service: "noop@internal"
  middlewares:
    redirect-portainer-middleware:
      redirectRegex:
        permanent: true
        regex: "http://portainer.local"
        replacement: "https://portainer.mydomain.cc"

I was then able to do exactly what I wanted by typing in "portainer.local" from my browser. I'm sure this would've been easy for someone with a little bit of experience that even checked my posted config longer than 5 seconds, but that didn't happen. If there are any newbie's out there struggling to do the same thing that I was, I hope this helps.

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