Your First Router
This chapter puts one real site behind Traefik: a backend service that already exists, given a name and a front door. Everything after this chapter is elaboration.
The setup
The lab's backends are two small programs
that answer any request by saying who
they are (their source is
examples/backend.py; any real service —
a wiki, a photo app, an admin page —
behaves the same way from Traefik's side
of the fence):
fern, listening on port 9001otter, listening on port 9002
Yours might be a service already running on your server. The only things Traefik needs to know about it are its address and the name you want to give it.
The dynamic file
In the watched folder (dynamic/, from
chapter 3), one file —
examples/dynamic-routers.yml holds the
lab's final version — begins as just
this:
http:
routers:
fern:
rule: "Host(`fern.test`)"
entryPoints:
- web
service: fern
services:
fern:
loadBalancer:
servers:
- url: "http://127.0.0.1:9001"
That is the entire instruction set:
when a request arrives at the web
entrypoint asking for the host
fern.test, send it to the service
fern, which currently means the server
at 127.0.0.1 port 9001. Add otter the
same way and two sites share one door.
Trying it, honestly
A reader following along has one problem
the lab had too: fern.test is not a
real name. It is from the reserved
.test top-level domain, which can never
be registered or collide with a real
site. There are three honest ways to ask
for it, in increasing order of permanence:
- curl's
--resolve(what the transcripts use): answer this one request as if DNS said so. - Your hosts file (
/etc/hosts, orC:\Windows\System32\drivers\etc\hosts): add127.0.0.1 fern.testand every program on your machine believes it. - Real DNS: in a real deployment the names are real — a public domain, or names your home router or Pi-hole hands out on the LAN — and this whole section is unnecessary.
curl -s --resolve fern.test:8000:127.0.0.1 \
http://fern.test:8000/hello
Check (transcript t01): the fern backend
answers, and its echo shows what Traefik
told it — host-seen: fern.test:8000,
and the forwarding headers
x-forwarded-for, x-forwarded-host,
x-forwarded-proto. Those headers are
how a backend learns the visitor's real
address and the name they asked for;
services that build links or log visitors
care about them, and Traefik sets them by
default.
The informative 404
Ask for a name no router claims:
curl -s -o /dev/null -w '%{http_code}\n' \
--resolve heron.test:8000:127.0.0.1 \
http://heron.test:8000/hello
404 — and the body, if you fetch it, is
Traefik's own plain text 404 page not
found. Memorise the shape of that
answer. From now on, a 404 in that exact
voice means no router matched; a 404 in
any other voice came from a backend, and
your routing is fine. Half of all proxy
debugging is knowing whose error you are
reading (chapter 15).
What you have, and haven't, got
You have name-based routing: two services behind one door, distinguished by the name asked for. You have not got HTTPS (chapter 7), any say over paths (chapter 5), or any protection on either site (chapter 6). The router you wrote will also happily serve fern to the whole network the entrypoint listens on — a reverse proxy is a publisher, and chapter 14 returns to what that commits you to.