How to redirect from HTTP:8000 to HTTPS:4433 (not default 443)

This is a weird scenario, but anyways, this is the thing:
I am hosting some containers at home, and my ISP does not allow exposing ports below 1024. Therefore I made this way:
Traefik ports 80, 443 and 8080 are binded to ports 80, 443 and 8080 in my device, respectively. In the router I had to make port forwarding like this:

external port 8000 forwards to my device on port 80, thus reaching traefik:80
external port 4433 forwards to my device on port 443, thus reaching traefik:443

then to access my services I need to either use HTTP with the following:

http://traefik.mydomain.duckdns.org:8000
OR
https://traefik.casarin.duckdns.org:4433

the problem is that I don't want to have a 404 page not found when accessing the HTTP protocol, since my services are only listening to HTTPS, so I want Traefik to make some redirects.
I tried some stuffs, I could get a redirect from HTTP to HTTPS, but since the ports differ from Traefik ports, the redirects were like from HTTP:8000 to HTTPS:443(port omitted in browser), instead of from HTTP:8000 to HTTPS:4433. This is the only way external devices can access my services on HTTPS.

This is my docker-compose.yml for Traefik:

  traefik:
    image: traefik:v3.2
    container_name: traefik
    networks:
      - selfhost
    volumes:
      - ./traefik.yml:/etc/traefik/traefik.yml:ro
      - ./dynamic.yml:/config/dynamic.yml:ro
      - ./letsencrypt:/letsencrypt:rw
    restart: unless-stopped
    ports:
      - 8080:8080
      - 80:80
      - 443:443
    environment:
      DUCKDNS_TOKEN: mytoken

This is my static traefik.yml:

entryPoints:
  web:
    address: :80

  websecure:
    address: :443
    http:
      tls:
        certResolver: letsencrypt
        domains:
          - main: mydomain.duckdns.org
            sans:
              - "*.mydomain.duckdns.org"

certificatesResolvers:
  letsencrypt:
    acme:
      email: myemail
      storage: /letsencrypt/acme.json
      dnsChallenge:
        provider: duckdns
        # disablePropagationCheck: true
        # delayBeforeCheck: 60s
        resolvers:
          - "1.1.1.1:53"
          - "8.8.8.8:53"

api:
  insecure: true

providers:
  file:
    filename: /config/dynamic.yml
    watch: true

log:
  level: DEBUG

This is my dynamic.yml:

http:
  middlewares:
    redirect-to-https:
      redirectScheme:
        scheme: https
        port: 4433
        permanent: true

  routers:
    whoami:
      rule: Host(`whoami.mydomain.duckdns.org`)
      service: whoami
      entryPoints:
        - websecure

    portainer:
      rule: Host(`portainer.mydomain.duckdns.org`)
      service: portainer
      entryPoints:
        - websecure

    traefik:
      rule: Host(`traefik.mydomain.duckdns.org`)
      service: traefik
      entryPoints:
        - websecure

    redirect-http:
      rule: HostRegexp(`{host:.+}`)
      entryPoints:
        - web
      middlewares:
        - redirect-to-https
      service: noop-service

  services:
    whoami:
      loadBalancer:
        servers:
          - url: http://whoami:80

    portainer:
      loadBalancer:
        servers:
          - url: http://portainer:9000

    traefik:
      loadBalancer:
        servers:
          - url: http://localhost:8080

    noop-service:
      loadBalancer:
        servers: []

This way I am getting a 404 page not found when reaching http://whoami.mydomain.duckdns.org:8000, instead of redirecting WITH the port 4433...

What to do?

Simply try RedirectRegex (doc):

# Redirect with domain replacement
http:
  middlewares:
    test-redirectregex:
      redirectRegex:
        regex: "^http://localhost/(.*)"
        replacement: "http://mydomain/${1}"

I tried something like this:

http:
  middlewares:
    redirect-to-https:
      redirectRegex:
        regex: ^http:\\whoami.mydomain.duckdns.org:8000
        replacement: https://whoami.mydomain.duckdns.org:4433
        permanent: true

  routers:
    whoami:
      rule: Host(`whoami.mydomain.duckdns.org`)
      service: whoami
      middlewares:
        - redirect-to-https
      entryPoints:
        - websecure
        - web

But this way did not work. When the user accessed http://whoami.mydomain.duckdns.org:8000, they were not redirected, they were kept in HTTP instead...

Actually this seem to work:

http:
  middlewares:
    redirect-to-https:
      redirectScheme:
        scheme: https
        port: 4433
        permanent: true

  routers:
    whoami:
      rule: Host(`whoami.mydomain.duckdns.org`)
      service: whoami
      entryPoints:
        - websecure
        - web
      middlewares:
        - redirect-to-https

  services:
    whoami:
      loadBalancer:
        servers:
          - url: http://whoami:80

But I particularly liked the idea I read somewhere of separation of concerns, where I would create a new router and service solely for the purpose of doing redirects. Is that possible?

The way I just showed in this reply I had to expose the router to HTTP protocol and add middleware to it. If I could create a separate router/service for that, only that router would be exposed to HTTP and with the middleware, right?

I would assume the client/browser will add a / at the end, so you probably need a * at the end

You can create routers with different names, one for each entrypoint.

1 Like

Is there a variable that "means" the url I typed including the subdomains?
I mean, this way the rege could be something like:

^http://{whole-thing-typed-by-user}:8000/{whole-path-typed-by-user}?

What do you mean?
The only router I can think of is the one I showed in the main topic, isnt it?

I specifically supplied the example from the docs:


Use one router for web, one for websecure:

http:
  middlewares:
    redirect-to-https:
      redirectScheme:
        scheme: https
        port: 4433
        permanent: true

  routers:
    whoami-web:
      rule: Host(`whoami.mydomain.duckdns.org`)
      service: whoami
      entryPoints:
        - web
      middlewares:
        - redirect-to-https

    whoami:
      rule: Host(`whoami.mydomain.duckdns.org`)
      service: whoami
      entryPoints:
        - websecure
1 Like

But that specific example doesn't make sense... It looks more like a hard-coded domain instead of a variable, you know?

Ok, so I think the thing I was thinking about is not possible, like having a dummy router that would catch all requests and redirect to the correct router, I mean:

routerDummy catches EVERY request on HTTP:8000, then redirects the user to the correct router with HTTPS:4433

This might solve your challenge:

services:
  whoami:
    image: traefik/whoami:v1.10
    networks:
      - proxy
    labels:
      - traefik.enable=true
      - traefik.http.routers.redir.entrypoints=web8000
      - traefik.http.routers.redir.rule=HostRegexp(`.+`)
      - traefik.http.routers.redir.middlewares=redir
      - traefik.http.middlewares.redir.redirectscheme.scheme=https
      - traefik.http.middlewares.redir.redirectscheme.port=8443
      - traefik.http.services.redir.loadbalancer.server.port=80

wow actually it did work! I don't understand why... The previous config I shared in the main post is similar, right? Is something missing in that config???

EDIT:
actually it did not work, I have this setup:

# config/dynamic.yml
http:
  middlewares:
    http-to-https:
      redirectScheme:
        scheme: https
        port: 4433
        permanent: true

  routers:
    http-to-https:
      rule: HostRegexp(`.+`)
      entryPoints:
        - web
      middlewares:
        - http-to-https
      service: http-to-https

    whoami:
      rule: Host(`whoami.mydomain.duckdns.org`)
      service: whoami
      entryPoints:
        - websecure

  services:
    http-to-https:
      loadBalancer:
        servers:
          - url: http://localhost:80

    whoami:
      loadBalancer:
        servers:
          - url: http://whoami:80

With this setup, for some reason I am having this result:

  • When accessing http://whoami.mydomain.duckdns.org:8000, it does NOT redirect to the correct router, the result is just 404 page not found
  • When accessing https://whoami.mydomain.duckdns.org:4433, the result works as before

It kind of doesn't work with having a dummy router for using the middleware and redirecting all traffic to the correct router, you see?

As per what I understood from your last answer, you are actually creating a router for handling HTTP only for WHOAMI service, right? If so, I am not setting things properly I guess. Can you correct me?