Routing containerless services on Traefik v2
Posted
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:
- Replace all instances of
service_name
with a name for your service - Replace
subdomain.exampledomain.com
with your desired route - Replace
service_host:service_port
with the correct IP and port for your service
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.