Configuring Traefik for mistake-proof docker compose setup

Hi everyone,

I'd like to configure Traefik in a manner that ensures my docker-compose is secure-by-default and I'd like to strike a balance where it minimizes potential errors while being user-friendly (i.e. easy and safe copy-pasting compose configuration).

Network Configuration:

  • Two networks are in play: 10.0.0.0/24 (MAIN) and 192.168.1.0/24 (GUEST).
  • All services should be accessible from MAIN. However, only selected ones should be open to GUEST.

Desired Label Configuration:

Here's a brief outline of my ideal scenario:

  whoami:
    image: containous/whoami
    container_name: whoami
    labels:
      - "traefik.enable=true"
  
  whoami-guest:
    image: containous/whoami
    container_name: whoami-guest
    labels:
      - "traefik.enable=true"
      - "traefik.guest.enable=true"

In this setup:

  • whoami should only be reachable from MAIN.
  • whoami-guest should be accessible from both MAIN and GUEST.

Challenges:

Introducing an ipWhitelist middleware requires this label:

  - "traefik.http.routers.whoami.middlewares=main-ipwhitelist@file"

This isn't ideal because the router name needs to match the specific container name (no easy copy-pasting). While one could simplify with:

  - "traefik.http.routers.{{ .Name }}.middlewares=main-ipwhitelist@file"

It's still not fully secure-by-default. Without any middleware, the container shouldn't be accessible. I tried using the docker provider's constraints to not auto-create routers for middleware-free services. Yet, something like this doesn't work:

    constraints: "Label(`traefik.http.routers.{{ .Name }}.middlewares`, `main-ipwhitelist`) || Label(`traefik.http.routers.{{ .Name }}.middlewares`, `guest-ipwhitelist`)"

Unfortunately, constraints doesn't support templating.

Potential Solutions:

  1. Is there a method to activate middleware through a label that doesn't need including the service name within the label itself?
  2. Could we add a default blacklist middleware to all routers? This would restrict all traffic except from MAIN and GUEST. Then, on a per-service basis, we could introduce selective whitelisting for either MAIN or GUEST networks.

Does anyone have ideas for solutions that could meet my needs? Your input would be greatly appreciated!

I don’t get it.

What does "Guest" mean? It’s usually a separate WiFi network, never heard of "guest" containers.

Those networks are a Docker thing, you need to attach services/containers, how do you want to set it with Traefik labels?

Services usually need at least a rule with Host() or PathPrefix() to work. See simple Traefik example.

What does "Guest" mean? It’s usually a separate WiFi network

GUEST is a separate VLAN of 192.168.1.0/24, has nothing to do with dockers - the docker host is placed in yet another VLAN network and I have routing configured on my gateway that routes traffic between VLANs (firewall allows GUEST to connect to IP of the Traefik host)

Services usually need at least a rule with Host() or PathPrefix() to work. See simple Traefik example.

I'm injecting a Host() rule via defaultRule:

providers:
  file:
    directory: /etc/traefik/dynamic
    watch: true
  docker:
    endpoint: unix:///var/run/docker.sock
    watch: true
    exposedByDefault: false
    defaultRule: "Host(`{{ index .Labels \"com.docker.compose.service\"}}.example.org`)"

That way I don't have to configure traefik-routers per service and my local DNS resolves *.example.org to Traefik IP address.

I hope that clarifies the situation a bit better :slight_smile:

1 Like