How do I setup multiple Traefiks, with one domain, and one external IP

Hello everyone, I'm trying to have a setup where I can have an ingress Traefik instance that redirects to a specific Traefik instance on another server in the LAN, using one domain and with a docker setup on multiple hosts, so no Kubernetes.

The problem is that the Ingress Traefik does not have a way to know to which Traefik instance redirect a request since all the instances use the same domain, the only way is to manually have each subdomain in a file provider, but my objective is to have a docker provider on each instance and then have the Ingress Traefik figure out somehow how to deal with incoming requests so I don't have to maintain a manual list of subdomains, is this possible?

Bonus question: How can I share the certificate between all the instances since it is a wildcard certificate?

You could just use Docker Swarm to connect the nodes to a common Docker network, then you only need one Traefik instance. See undocumented simple Traefik Swarm example.

If you want multi-level Traefik, you need to make up your mind first how you want to use TLS. Ingress needs to have a cert to be able to use Host() or HostSNI() to match the URL and forward it accordingly. I would use Ingress Traefik to terminate TLS, so have LetsEncrypt there, then only forward decrypted http requests to the other instances.

I am pretty sure I created an example docker-compose.yml of chained Traefik here (or on Docker forum), but I can't find it, too many posts created :smile:

Found the config :slight_smile:, to be used with docker stack deploy:

version: '3.9'

networks:
  proxy-ext:
    name: proxy-ext
    driver: overlay
    attachable: true
  proxy-int:
    name: proxy-int
    driver: overlay
    attachable: true


volumes:
  traefik-certificates:


services:
  traefik-ext:
    image: traefik:v2.10
    hostname: '{{.Node.Hostname}}'
    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host
    networks:
      - proxy-ext
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik-certificates:/certificates
    command:
      - --providers.docker=true
      - --providers.docker.swarmMode=true
      - --providers.docker.exposedByDefault=false
      - --providers.docker.network=proxy-ext
      - --providers.docker.constraints=Label(`traefik.ext`,`true`)
      - --entryPoints.web.address=:80
      - --entryPoints.web.http.redirections.entryPoint.to=websecure
      - --entryPoints.web.http.redirections.entryPoint.scheme=https
      - --entryPoints.websecure.address=:443
      - --entryPoints.websecure.http.tls=true
      - --entryPoints.websecure.http.tls.certResolver=myresolver
      - --api.debug=true
      - --api.dashboard=true
      - --log.level=DEBUG
      - --accesslog=true
      - --certificatesResolvers.myresolver.acme.email=me@example.com
      - --certificatesResolvers.myresolver.acme.storage=/certificates/acme.json
      - --certificatesresolvers.myresolver.acme.tlschallenge=true
    deploy:
      mode: global
      placement:
        constraints:
          - node.role==manager
      labels:
        - traefik.ext=true
        - traefik.enable=true
        - traefik.http.routers.traefik-ext.entrypoints=websecure
        - traefik.http.routers.traefik-ext.rule=Host(`traefik-ext.example.com`)
        - traefik.http.routers.traefik-ext.service=api@internal
        - traefik.http.routers.traefik-ext.middlewares=auth-ext
        - 'traefik.http.middlewares.auth-ext.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/'
        - traefik.http.services.dummy-svc.loadbalancer.server.port=9999


  traefik-int:
    image: traefik:v2.10
    hostname: '{{.Node.Hostname}}'
    networks:
      - proxy-ext
      - proxy-int
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    command:
      - --providers.docker=true
      - --providers.docker.swarmMode=true
      - --providers.docker.exposedByDefault=false
      - --providers.docker.network=proxy-int
      - --providers.docker.constraints=Label(`traefik.int`,`true`)
      - --entryPoints.web.address=:80
      - --entryPoints.web.forwardedHeaders.insecure=true
      - --api.debug=true
      - --api.dashboard=true
      - --log.level=DEBUG
      - --accesslog=true
    deploy:
      mode: global
      placement:
        constraints:
          - node.role==manager
      labels:
        - traefik.ext=true
        - traefik.enable=true
        - traefik.http.routers.traefik-int.entrypoints=websecure
        - traefik.http.routers.traefik-int.rule=Host(`traefik-int.example.com`)
        - traefik.http.routers.traefik-int.service=api@internal
        - traefik.http.routers.traefik-int.middlewares=auth-int
        - 'traefik.http.middlewares.auth-int.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/'
        - traefik.http.services.dummy-svc.loadbalancer.server.port=9999
        - traefik.http.routers.traefik-fwd.entrypoints=websecure
        - traefik.http.routers.traefik-fwd.rule=PathPrefix(`/`)
        - traefik.http.routers.traefik-fwd.service=fwd
        - traefik.http.services.fwd.loadbalancer.server.port=80



  whoami-ext:
    hostname: '{{.Node.Hostname}}'
    image: traefik/whoami:v1.10
    networks:
      - proxy-ext
    deploy:
      mode: global
      labels:
        - traefik.ext=true
        - traefik.enable=true
        - traefik.http.routers.whoami-ext.entrypoints=websecure
        - traefik.http.routers.whoami-ext.rule=Host(`whoami-ext.example.com`)
        - traefik.http.services.whoami-ext.loadbalancer.server.port=80


  whoami-int:
    hostname: '{{.Node.Hostname}}'
    image: traefik/whoami:v1.10
    networks:
      - proxy-int
    deploy:
      mode: global
      labels:
        - traefik.int=true
        - traefik.enable=true
        - traefik.http.routers.whoami-int.entrypoints=web
        - traefik.http.routers.whoami-int.rule=Host(`whoami-int.example.com`)
        - traefik.http.services.whoami-int.loadbalancer.server.port=80

@bluepuma77 Can you explain what "hostname: '{{.Node.Hostname}}'" does or link me to documentation on that? I don't even know what to call that to search for myself.

It will set the hostname within the container to the hostname of the parent node (doc). So the container "knows" which host it is on.

1 Like