Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

Traefik and the file provider: publish a service outside a container

By updated

Improve this page

Traefik logo

To publish a service that does not run in a container, for example a service managed by systemd on the host, you describe its route in a file that Traefik watches through the file provider. Such a service carries no label, so the Docker provider cannot discover it. This lesson explains how the file provider works, what it reloads without a restart, and why a correct route can still return an error when the backend is unreachable. It targets Traefik 3.7.15.

What you will learn

The lesson follows the path of a route: its description in a file, its reload, then the check that the backend answers from Traefik's position.

  • Explain why a service outside a container is not discovered on its own.
  • Describe a router and a service in a dynamic file.
  • Tell the static configuration from the dynamic configuration.
  • Prove that a route change is picked up without restarting Traefik.
  • Check the reachability of the backend from Traefik's network position.

Prerequisites

This lesson builds on Docker discovery: it assumes you know the notions of router, service and backend, and that Traefik is already running.

  • The notions from Traefik: entrypoints, routers, services and providers.
  • Publishing containers with Traefik with Docker, to measure the difference between discovery and declaration.
  • A simple web service managed by systemd, listening on a local port.

Why can't a service outside a container be discovered?

A provider is the source that tells Traefik what to publish. The Docker provider reads container metadata. A service started by systemd has neither a container nor a label: no source describes its route, so Traefik ignores it. You have to supply that description by hand, and that is the job of the file provider.

The description contains the same objects as the labels, but written in a YAML or TOML file: a router that selects the request, and a service that designates the backend by its URL. The only difference is the source, not the model. An object defined here carries the @file suffix, just as an object coming from Docker carries @docker.

What does Traefik reload without a restart?

Traefik distinguishes two levels of configuration. The static configuration (entrypoints, enabled providers, ACME resolvers) is read at startup: changing it requires a restart of Traefik. The dynamic configuration (routers, services, middlewares) can change while Traefik runs.

The file provider belongs to the first category through its activation, and to the second through its content. You enable it once in the static configuration with providers.file.directory, which designates a directory. The files dropped in that directory are then watched: the providers.file.watch option defaults to true, according to the provider reference. Adding, changing or removing a route then requires no restart.

Two details from the reference avoid surprises. The filename and directory options are mutually exclusive, and the documentation recommends directory. After a reload, Traefik waits at least 2s before handling a new event (providersThrottleDuration): a change is therefore not visible to the millisecond, and several changes made close together are grouped.

How do you describe a route to a host service?

A dynamic file declares three things: a rule that recognizes the request, an entry point where it arrives, and the backend address. The skeleton below shows where each one goes; the values between angle brackets are to be replaced with those of your environment.

http:
routers:
<router-name>:
entryPoints:
- <entrypoint>
rule: Host(`<public-name>`)
service: <service-name>
services:
<service-name>:
loadBalancer:
servers:
- url: "http://<backend-address>:<port>"

The skeleton chains together like this: the router reads the request, the Host rule compares the requested name, and the service forwards the request to the given URL. The name <service-name> links the two objects; a typo at that spot disables the route. For a backend that does not speak HTTPS, the URL starts with http://, and Traefik keeps the TLS termination on the client side.

Why can a backend that "is running" stay unreachable?

The address written in url is resolved from Traefik, not from your terminal. It is the most frequent cause of a 502 on a host service. Two cases come up again and again.

  • Traefik runs in a container. Inside that container, 127.0.0.1 means the container itself, not the host. An http://127.0.0.1:<port> URL fails there even though curl on the host succeeds. You need an address that the container can use to reach the host.
  • The service only listens on the loopback interface. A service bound to 127.0.0.1 accepts only connections coming from the machine itself. From a container or another host, the connection is refused.

To settle it, compare what the service announces with what Traefik can reach. systemctl status <unit> tells you whether the unit is active, and ss -ltn lists the listening ports with their address. An immediate 502 points to a refused connection; a 504 after a long silence points rather to a network path that leads nowhere, as detailed in Publish a web service.

How do you prove the route was picked up without a restart?

A proof is measured with two observations that must agree: the route changes behavior, and Traefik has not restarted. One alone is not enough, because a route can also change because Traefik was relaunched.

  1. Measure the behavior before the change: the response and the HTTP code for the public name concerned.
  2. Note what identifies the instance: the start time of the process or container, or its process identifier.
  3. Edit the dynamic file, then wait a few seconds (the 2s delay above matters).
  4. Repeat the request and compare the response, then read the identifier or start time again: they must be unchanged.

If the route does not change, do not assume the reload failed. Read the Traefik logs: a syntax error in a file is recorded there, and since version 3.7.12 the file name appears in the message. Always check the result with a real request rather than by the mere absence of an error.

Hands-on: publish a systemd service

The exercise asks you to make a host service reachable under a public name, then to show that Traefik reloaded the configuration without restarting. The environment-specific values and the success criteria are in the lab scenario.

Key points

A host service is published with the same routing mechanism as a container, provided you give it a description.

  • A service outside a container has no label: describe its route in a watched file.
  • The static configuration enables the provider; the dynamic configuration reloads without a restart.
  • Designate a directory with directory, and mount the parent directory if Traefik runs in a container.
  • The backend URL is resolved from Traefik: there, 127.0.0.1 means Traefik itself.
  • Prove a hot reload with two observations: the route changed, the instance did not restart.

Knowledge check

The quiz checks the difference between static and dynamic configuration, the role of the file provider, and the reachability of the backend.

Knowledge check

Check what you have learned with this interactive quiz

8 questions
8 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn