How to forward requests to a local IP

Hi, I use Traefik 2.x for my docker container. Now, I need also to forward requests coming to foo.example.org to another private host (http://192.168.0.50:8080) that is reachable from the machine hosting both Traefik and Docker.

Usually I do this kind of things spinning up a dedicated Nginx container this way:

version: '3'

services:
   nginx:
        image: nginx
        restart: unless-stopped
        volumes:
              - ./log/:/log/
              - ./nginx.conf:/etc/nginx/conf.d/default.conf
        expose:
              - 80
        labels:
                traefik.enable: true
                traefik.http.routers.myService.rule: Host(`foo.example.org/`)
                traefik.http.routers.myService.entrypoints: websecure
                traefik.http.routers.myService.tls.certresolver: tlsleresolver        
        networks:
                - proxy

networks:
    proxy:
        external: true

with this config

nginx.conf
upstream myService {
    server 192.168.0.50:8080;
}

server {
    listen 80;
    server_name foo.example.org;
    access_log  /log/access.log  main;
    location / {
        proxy_pass http://myService;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forward-Proto http;
        proxy_set_header X-Nginx-Proxy true;

        proxy_redirect off;

    }
}

I'm wondering if I can get rid of Nginx and ask Traefik to do such a job. Here is my new config:

version: '3.7'

services:
  traefik:
    image: traefik:v2.5
    container_name: traefik
    security_opt:
      - no-new-privileges:true
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
      - ./.usersfile:/.usersfile
    ports:
      - 80:80
      - 443:443
    command:
      - --api.dashboard=true
      - --log.level=INFO
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=proxy
      - --entrypoints.webinsecure.address=:80
      - --entrypoints.webinsecure.http.redirections.entrypoint.to=websecure
      - --entrypoints.webinsecure.http.redirections.entrypoint.scheme=https
      - --entrypoints.websecure.address=:443

      # TLS certificatesresolvers w/ Let's encrypt
      - --certificatesresolvers.tlsleresolver.acme.tlschallenge=true
      - --certificatesresolvers.tlsleresolver.acme.email=myemail@example.org
      - --certificatesresolvers.tlsleresolver.acme.storage=/letsencrypt/acme.json

    networks:
      - proxy

    labels:
      traefik.enable: true

      # Dashboard
      traefik.http.routers.traefik.rule: Host(`traefik.example.org`)
      traefik.http.routers.traefik.service: api@internal
      traefik.http.routers.traefik.entrypoints: websecure
      traefik.http.routers.traefik.tls.certresolver: tlsleresolver
      traefik.http.routers.traefik.middlewares: traefik-auth
      traefik.http.middlewares.traefik-auth.basicauth.usersfile: /.usersfile

      # Mimicking Nginx
      traefik.http.routers.foo.rule: Host(`foo.example.org`)
      traefik.http.routers.foo.service: foo
      traefik.http.routers.foo.entrypoints: websecure
      traefik.http.routers.foo.tls.certresolver: tlsleresolver
      traefik.http.services.foo.loadbalancer.server.url: http://192.168.0.50:8080

networks:
  proxy:
    external: true

But I got "too many redirects". How can I do it?

Hi @floatingpurr,
Thanks for your interest in Traefik.

The "too many redirects" error comes from a loop that occurs in your traefik container.
When using traefik labels for dynamic configuration, the server url is not configurable and always points to the container ip. The label traefik.http.services.foo.loadbalancer.server.url with the value http://192.168.0.8080 is just ignored.

For you use case, I suggest you to use the file provider for the dynamic configuration.
To do so, you have to:

command:
  --providers.file.filename=/path/to/dynamic.yml
volumes:
  - ./config.yml:/path/to/dynamic.yml
  • create the dynamic config file (./config.yml):
http:
  routers:
    foo:
      rule: Host(`match.example.com`)
      service: foo

  services:
    foo:
      loadBalancer:
        servers:
          - url: http://host.docker.internal:8081
1 Like

Thank you @moutoum, adding the file provider fixed my problem. Thanx for describing the machinery behind that!

Hi @moutoum!

I am trying to implement this into my Jellyfin instance, as Jellyfin only allows you to send a password reset if coming from a local connection. I am trying to utilise this config in my dynamic config. Here's the nginx equivalent of what i'm trying to achieve.

This is what I've got so far but it doesn't seem to like me.

http:
  ## ROUTERS ##
  routers:
    forgot:
      entryPoints:
        - https
      rule: 'Host(`<redacted>`) && Path(`/Users/ForgotPassword`)'
      service: forgot
      middlewares:
      - passwordReset
    forgotPin:
      entryPoints:
        - https
      rule: 'Host(`<redacted>`) && Path(`/Users/ForgotPassword/Pin`)'
      service: forgotPin
      middlewares:
      - passwordReset

  ## SERVICES ##
  services:
    forgot:
      loadBalancer:
        servers:
          - url: http://jellyfin:8096/Users/ForgotPassword
    forgotPin:
      loadBalancer:
        servers:
          - url: http://jellyfin:8096/Users/ForgotPassword/Pin

  ## MIDDLEWARES ##
  middlewares:
    # Jellyfin Header
    passwordReset:
      headers:
        customRequestHeaders:
          X-Forwarded-For: 127.0.0.1

I appreciate any and all help!

Hi @LubricantJam,
Thanks for your interest in Traefik.

Your issue does not seem related to the previous content. Could you please open a new issue so it could help other users searching for the same issue later?

Thanks,
Maxence

No worries, I’ve moved it to Translating NGINX to Traefik Rules, thanks.

1 Like

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