Traefik Basics

2020-05-01 6 minutes #self-hosting #containers #traefik


Traefik is a cloud native reverse proxy, which is basically a fancy way of saying it’s a reverse proxy with some fancy features. Specifically it has fancy features around auto-discovery, and deep integration with technologies like Docker and Kubernetes.

# Basic concepts

Traefik has four fundamental concepts: Entrypoints, routers, middleware and services. In that order.

Entrypoints are the ports Traefik listens for traffic on. Generally you’d want one for port 80 and another for 443.

Routers are what listen to entrypoints, and match domains and paths to services. A route has a rule, which identifies it, a service, and a set of middleware.

Middleware run in between the service and the router, and can modify the request or response. Traefik has a number of useful ones built in for adding headers, redirecting, rate limiting and more.

Services are your applications to route traffic to. A service may be a single container, or multiple in a load-balancing setup. Services can be either HTTP, TCP or UDP.

# Running Traefik

Traefik is available as a single binary, but it runs best under Docker. You can create an incredibly simple docker-compose file to run Traefik correctly.

version: "2.3"

services:
  traefik:
    container_name: traefik
    image: traefik:v2.2.1
    network_mode: host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik:/etc/traefik
    restart: unless-stopped

One thing to note about this is the network_mode: host. Traefik needs to be able to access your application containers over the network. You can do this by creating a custom network and adding both traefik and your applications to it. Using host networking means you don’t need to do this, as traefik can communicate to all the docker networks automatically. This isn’t necessarily recommended, and definitely shouldn’t be done for all containers, but I trust traefik not to be doing weird things.

# Traefik configuration

Traefik configuration is split in 2. Traefik’s primary configuration can be either YAML or TOML. Configuration for the services themselves can live in many places. For docker-compose, it’s done using container labels.

Traefiks main configuration allows you to configure the entrypoints for traefik to listen on, how TLS is configured, and where traefik should look for services.

The docker configuration for traefik is probably what turns most people off of it. Traefik’s configuration may seem verbose to achieve something which would be very straightforward with Nginx or alike. But if you approach things differently, they can be very clean.

My typical configuration is very simple:

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.foo.rule=Host(`sub.example.com`)"
  - "traefik.http.routers.foo.tls=true"
  - "traefik.http.routers.foo.tls.certresolver=le"

Here, I instruct traefik to route traffic for sub.example.com to this container, and issue a certificate for it. Everything else, traefik works out for itself. Which port should traffic be routed to? Use the EXPOSE command from the Dockerfile! Which entrypoints to listen on? Listen on them all!

The obvious omission is HTTPS redirection. I do this using a service which listens on any domain, and issues a redirect, whether traefik knows about the domain or not. Since 2.2.0, traefik now as this built in.

# The dashboard

When getting started, and even long after that, the traefik dashboard is an incredible too. Listening by default on port 8080, traefik services a read-only web interface showing the current state including routers, services and middleware.

If you’re trying to configure a service, and not sure how Traefik is seeing, if it sees it at all. The web interfaces shows you everything.

Traefik router configuration for this website
Traefik router configuration for this website

Traefik service configuration for this website
Traefik service configuration for this website

# TLS

Traefik supports TLS out the box, both with manually defined keys, and through LetsEncrypt.

When using LetsEncrypt, Traefik will automatically renew certificates when needed, and automatically provision them when new services are added.

On top of HTTP challenges, Traefik also supports DNS challenges, although more configuration is required.

Unfortunately, Traefik doesn’t store its certificates in the usual .crt and .key formats, instead they’re stored in a custom JSON format. This isn’t a massive issue, but something to keep in mind if you were hoping to reuse the certificates elsewhere (probably a bad idea anyway).

Configuring TLS is very simple. First, you need to tell Traefik how to generate certificates:

certificatesResolvers:
  le:
    acme:
      email: you@example.com
      storage: /etc/traefik/acme.json
      httpChallenge:
        entryPoint: web

This creates a resolver named le, which provisions LetsEncrypt certificates using the web entrypoint for HTTP challenges. Then, you tell each service where to get its certificates from:

labels:
  ...
  - "traefik.http.routers.website.tls=true"
  - "traefik.http.routers.website.tls.certresolver=le"

And that’s it. After the container is restarted, traefik will issue it a certificate, and keep on top of renewals.

# HTTPS redirection

Now HTTPS is no good if it’s not used, and the best way of ensuring that is to redirect HTTP connections to HTTPS automatically. This can be done at a service level, but it’s very easy to set it up for all.

We’ll do this using the File provider, and create a new router which just redirects all traffic.

http:
  middlewares:
    hsts:
      redirectScheme:
        scheme: https

  routers:
    hsts:
      service: ping@internal
      rule: PathPrefix(`/`)
      entryPoints:
        - web
      middlewares:
        - hsts

The service is set to ping@internal because routers need a service. The ping service is built-in to Traefik, and just returns 200 OK to all requests, not that it’ll be hit, as the redirectScheme middleware will redirect traffic before it hits the service.

Now, we just add our newly created file provider:

providers:
  docker:
    endpoint: unix:///var/run/docker.sock
    watch: true
    exposedByDefault: false

  file:
    filename: /etc/traefik/file-provider.yml

And now, all traffic which hits our web endpoint will be immediately redirected to HTTPS.

# Traefik and routing to an application

So, what does a fully configured traefik setup look like? I’m glad you asked!

First, you’ll need to set up and install traefik, which can be done with a very simple docker-compose file, as shown above. Your default configuration will need to define at least one entrypoint.

Once you already have traefik installed and setup, adding services is very simple:

Step 1: pick an application, find a container, and write a minimal compose file:

version: "2.3"

services:
  whoami:
    image: containous/whoami:latest
    container_name: whoami
    restart: unless-stopped

Step 2: add the absolute minimum traefik configuration:

version: "2.3"

services:
  whoami:
    image: containous/whoami:latest
    container_name: whoami
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.example.com`)"

Step 3: start your new service with docker-compose up -d, and wait a few seconds for traefik to notice it. You can check on the progress of this by refreshing the dashboard until it appears.

Step 4: visit the URL in your browser, and notice traffic being routed correctly.

To add more applications, just start more compose files with more configuration. Traefik will pick up on new containers automatically and start routing traffic, no restart required.

# Should you use Traefik?

This is a more difficult question than it may seem. Personally I’m super happy I migrated from Nginx to traefik, and I know plenty of others who feel the same. If you’re trying to manage a number of different docker containers on one machine, then traefik is something worth looking into.

However, if you’ve just got a couple services, and you’re comfortable with Nginx, why rock the boat? Both traefik and nginx are reverse proxies, and they’re both great. You’re not going to see performance, security, or really simplicity gains simply from switching. With that said if you’re using docker, it’s worth a look into anyway.

Using Traefik using only the file provider is definitely not a good idea, and nginx is definitely a better tool for the job!

Share this page

Related content