Learning to Love YAML - Converting Your Traefik Setup From Cmdline into YAML

In this post, I shared my Traefik configuration. Back then, I'd just learned about Traefik and followed a few posts to set things up and get them working with all of my containers. Since then, I've used Traefik for every new container I've set up, I've run servers like Minecraft and 7 Days to Die through it, as well as numerous different DevOps-adjacent containers. So whilst I'm no means an expert, I'm definitely a little more adept at some of its configuration nuances (I'll be publishing something next week about how to globally disable TLS 1.0 and 1.1 so keep an eye out for that).

Caveats

As per normal, ensure the below are met before starting this:

  • You've backed up your current config, certs volume, docker-compose.yml file and/or anything related to the running version of Traefik
  • You're doing this with Traefik in a Docker container
  • The same principal applies to a natively running version of Traefik I suppose, just ignore the bit about passing the file through to the container
  • You understand basic Docker concepts such as bringing a container up and down, and managing your configuration through a docker-compose.yml file

Static or Dynamic?

The best descriptor of the differences is probably the image above. All you really need to be concerned about is the following:

  • Static runs at startup
  • Dynamic runs each time a new request comes in to Traefik

Because of this distinction, there are certain elements that fit naturally into each of these categories. In the current config (located at the bottom of the post), Static options are provided via the 'command' key. There are certain Dynamic options that can be specified in the 'labels' key (the normal router creation, certresolver binding, etc) but we won't go over those in detail just yet.

Converting YAML Into... YAML?

Technically, to convert from the cmdline style flags to a permanent YAML file we're going from docker-compose.yml to traefik.yml, but you'll see that the format will wind up looking a little different. If you've worked with JSON at all, the way to split these up should look rather familiar. The basic gist is that everywhere you see a period, you insert a new line.

As an example, the command argument

- --entrypoints.http.address=:80

will translate into

entryPoints:
  http:
    address: 80

It's worth noting here that I'm not certain if you have to camel case the text in the YAML file, that's just how the docs recommend it

Create a file called traefik.yml in the same directory as your docker-compose.yml file (or don't, I'm not your dad... Just don't forget to amend the final volume mapping below) and convert these lines into sweet, sweet YAML. Once you've completed the whole 'command' key, you should have a file like the below (certain config will accept either true or {} as valid to turn them on, always worth double checking the docs for which is preferred):

entryPoints:
  http:
    address: ":80"

  https:
    address: ":443"

providers:
  docker: {}

certificatesResolvers:
  le:
    acme:
      email: name@email.tld
      storage: /letsencrypt/acme.json
      tlsChallenge: {}

That Rug Really Tied The Room Together

Now you have a static file on the host system, viola. Remove the 'command' key, rebuild the container and you're ready to go!

What's that? Your container is giving you an error that it can't find the file you just created? Ahhh... We probably should have actually utilised that new file somehow, huh?

Well then, ignoring that small blunder, just add a line to your volume mappings to make the file visible inside the container (/etc/traefik/traefik is the default location that Traefik will look for config). This is where you change the left hand side of the mapping if you located your traefik.yml file elsewhere...

- "./traefik.yml:/etc/traefik/traefik.yml"

and you're off to the races! Just bring the container down (you are storing your certs in a separate volume, riiiiiiight?) and back up again and Traefik will now reload, giving you this nifty little confirmation:

Now, if you ever want to add configuration to the Static options for Traefik, you just have to add them to this file and restart the container. The documentation is always a little bit more helpful when using YAML, as all things aren't necessarily formatted for cmdline on the website.

Previous Traefik Config

version: "3.3"

services:
  traefik:
    container_name: traefik
    image: traefik:v2.4.8
    command:
      # - --log.level=DEBUG
      # Entrypoints
      - --entrypoints.http.address=:80
      - --entrypoints.https.address=:443
      # Provider Info
      - --providers.docker
      # Certificate Resolver Info
      - --certificatesresolvers.le.acme.email=name@email.tld
      - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
    labels:
      - "traefik.enable=true"
      ### Middleware Redirect
      - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
      ### Global HTTP -> HTTPS Redirect
      - "traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.redirs.entrypoints=http"
      - "traefik.http.routers.redirs.middlewares=https-redirect"
      - "traefik.http.routers.redirs.priority=1"
    ports:
      - "80:80"
      - "443:443"
    volumes:
        - "/var/run/docker.sock:/var/run/docker.sock"
        - "certs:/letsencrypt"
    restart: unless-stopped
    networks:
      - proxy

volumes:
  certs:

networks:
  proxy:
    driver: bridge

New Traefik Config

version: "3.3"

services:
  traefik:
    container_name: traefik
    image: traefik:v2.4.8
    labels:
      - "traefik.enable=true"
      ### Middleware Redirect
      - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
      ### Global HTTP -> HTTPS Redirect
      - "traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.redirs.entrypoints=http"
      - "traefik.http.routers.redirs.middlewares=https-redirect"
      - "traefik.http.routers.redirs.priority=1"
    ports:
      - "80:80"
      - "443:443"
    volumes:
        - "/var/run/docker.sock:/var/run/docker.sock"
        - "certs:/letsencrypt"
        - "./traefik.yml:/etc/traefik/traefik.yml"
    restart: unless-stopped
    networks:
      - proxy

volumes:
  certs:

networks:
  proxy:
    driver: bridge
A truly special person shared this with me a while ago and I've been coming back to it ever since...