Routing containerless services on Traefik v2

Contents

Introduction

I very recently posted a step by step guide on setting up Traefik as a reverse proxy for your container-based services.

Since then, I have had a number of questions on whether or not Traefik can be used as a router for services that are not containerized, or for applications running on other hosts on the network. In short, the answer is yes, and it is reasonably simple to configure using the file provider.

Setting Up Traefik

If you haven’t already, you should check my last post for a basic Traefik configuration. This post assumes that you already have a traefik.toml file and a basic docker-compose service for Traefik. I also assume that you have a Let’s Encrypt certificate resolver in your configuration, but you can skip this if you choose.

Firstly, we will need to make a new folder to hold all of the “custom” services that we will be defining. Even though we will only be making one in this post, it is always good to plan ahead. I suggest that you create this in the same folder as your traefik.toml file for convenience. I named this folder custom_services, and I will be referring to it by this name throughout this post.

After you have created your new folder, you will need to expose it to Traefik by adding it to your docker-compose file as a volume. I have mounted this to /etc/traefik/custom_services, but you can choose virtually any path as long as you account for it in your traefik.toml file later. Your volumes section now should look something like this:

    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /path/to/acme.json:/acme.json
      - /path/to/traefik.toml:/etc/traefik/traefik.toml
      - /path/to/custom_services:/etc/traefik/custom_services

Next, we need to tell Traefik that this folder exists, and that it holds file providers. We will do this by following the steps in the file provider documentation. You will need to add the following to the [providers] section of your traefik.toml file, making sure that the path matches the Docker mount point you defined in the previous step:

  [providers.file]
    directory = "/etc/traefik/custom_services"

For completeness, the [providers] section of my configuration is as follows:

[providers]
  [providers.docker]
    endpoint = "unix:///var/run/docker.sock"
    watch = true
    exposedbydefault = false
  [providers.file]
    directory = "/etc/traefik/custom_services"

Creating the file provider

Now that Traefik knows to parse files in this folder, we can start defining our new service. Create a new .toml file in the custom_services folder that you created with a name of your choice. Ideally it should be something related to the service you are working on, like plex.toml.

Open up this new file, and add the following configuration. This will provide us with routing to the service, HTTP to HTTPS redirection, and a TLS certificate from Let’s Encrypt.

 [http]
  [http.middlewares]
    [http.middlewares.service_name-redirect.redirectScheme]
        scheme = "https"

  [http.routers.service_name-redirect]
    entrypoints = ["web"]
    rule = "Host(`subdomain.exampledomain.com`)"
    middlewares = ["service_name-redirect"]
    service = "service_name"

  [http.routers.service_name]
    entrypoints = ["websecure"]
    rule = "Host(`subdomain.exampledomain.com`)"
    service = "service_name"
    [http.routers.service_name.tls]
        certResolver = "letsencrypt"

  [http.services]
    [http.services.service_name.loadbalancer]
      [[http.services.service_name.loadBalancer.servers]]
        url = "http://service_host:service_port/"

First, let’s make a few substitutions:

Take note that you cannot use localhost as the hostname for your service, as from Traefik’s perspective localhost is the container itself, not your server. You will most likely need to use the IP address of your server here.

Let’s go through what we just defined.

HTTPS Router

We create two routers in this configuration, one of which listens on the websecure entrypoint, or port 443, for HTTPS traffic. To this router, we apply a rule that filters traffic by the Host field in the packet headers, picking out only the packets that were directed at your specified subdomain and domain name combination. Finally, we tell the router that this traffic is to be routed to a specific service that you have created.

The HTTPS router also sets up TLS in the form of a certificateResolver which fetches certificates from Let’s Encrypt.

HTTP Router

The other router in this configuration listens on the web entrypoint instead of websecure, and passes traffic through a middleware that we have defined before routing it to the service. This middleware is responsible for changing the scheme of the request from HTTP to HTTPS.

Middleware

The middleware runs, as the name suggests, in the middle of the HTTP routing operation. The redirectScheme middleware is documented here.

Services

The final piece of the puzzle is the service to which we route all of our traffic. Each service has at least one load balancer to which traffic is forwarded. We have simply defined this load balancing server using the IP address and port on which your “external” service runs.

Conclusions

All done! Spin up your Traefik container, and you should be able to access your containerless service using the domain name that you specified.

Hopefully this guide provides some clarity on an otherwise slightly muddy process. As always, leave a comment if you found this useful.

comments powered by Disqus