Adding a route to a service¶
This page gives a container a hostname behind its VM's Traefik, with a certificate and, if you choose, a sign-in. Do it when you add a container that serves a web interface, or when an existing one needs another name or a different chain.
The change is made in the container's Compose file in the fleet-stacks repo. A push, and a deploy of the stack by Komodo, carry it to the host. Traefik itself is never edited or restarted. See Provider for why.
Status: written, not yet run.
Prerequisites¶
- The container has a folder under
containers/in fleet-stacks, and a stack extends it. For a new one, do Add a stack of your own first and come back for the labels. - The host lists traefik-agent in its
docker_stacks, or is tf01 or bh01. See The Traefik stacks. - A checkout of fleet-stacks you can push to, on a machine with Python 3 and PyYAML.
Placeholders¶
| Placeholder | Value |
|---|---|
<image> |
The container's folder under containers/, such as uptime-kuma |
<key-prefix> |
The prefix of the container's keys, such as UPTIME_KUMA |
<port> |
The port the application listens on inside the container, such as 3001 |
<stack> |
The stack that runs the container, such as core-infra |
<host> |
The host that runs the stack, such as ci01 |
1. Choose the hostnames¶
Decide which names the route answers on. The fleet builds every name from the same four values, so a route written once works on any host. See Naming.
| Name | Built as | Use it for |
|---|---|---|
uptime-kuma.ci01.home.myah-mitchell.com |
Service, server, sub-domain, domain | Every route. It always means this VM |
uptime-kuma.home.myah-mitchell.com |
Service, sub-domain, domain | A service the site has one of |
uptime-kuma.myah-mitchell.com |
Service, domain | A service that is published to the internet, and no other |
Keep each name to one level below a name the certificate covers. The certificate has wildcards for the domain, the sub-domain, and the server, and a wildcard covers one level. See TLS termination and certificate resolvers.
The container's komodo.env holds the two words the names are built from. Check both lines are there:
2. Join the proxy network¶
In containers/<image>/compose.yaml, add proxy to the service's networks:
Traefik reaches a container over the proxy network and no other. The stack's own compose.yaml has to declare it, as the stack template does:
3. Add the labels¶
In the same file, give the service these labels. They are the ones the Uptime Kuma container carries, with the names made general:
labels: ## Traefik Labels
- "traefik.enable=true"
- "traefik.docker.network=${PROXY_NETWORK}"
- "traefik.http.routers.$PROJECT_NAME-<image>-rtr.rule=
Host(`${<key-prefix>_SERVICE_NAME}.${SUB_DOMAIN_NAME}${DOMAIN_NAME}`) ||
Host(`${<key-prefix>_HOSTNAME}.${SERVER_NAME}.${SUB_DOMAIN_NAME}${DOMAIN_NAME}`)"
- "traefik.http.routers.$PROJECT_NAME-<image>-rtr.middlewares=${TRAEFIK_AUTH_CHAIN:-chain-authentik@file}"
- "traefik.http.services.$PROJECT_NAME-<image>-svc.loadbalancer.server.port=<port>"
| Label | Does |
|---|---|
traefik.enable=true |
Lets Traefik see the container. Without it the rest are ignored |
traefik.docker.network |
Says which of the container's networks Traefik uses to reach it |
routers.<name>.rule |
The router and the hostnames it matches |
routers.<name>.middlewares |
The chain a request passes through |
services.<name>.loadbalancer.server.port |
The service: the port inside the container |
Start the router's and the service's names with $PROJECT_NAME, as the fleet's containers do. A name has to be unique on the VM's Traefik, and two containers that define the same router name cancel each other out.
The labels name no entrypoint and no certificate. The https entrypoint is the default and brings TLS with it. See Entrypoint.
Leave out SUB_DOMAIN_NAME in a third Host only for a service you intend to publish to the internet. ntfy's container shows that form.
4. Choose the chain¶
Keep the middlewares line from step 3 for an interface that should sit behind Authentik's sign-in. The variable takes chain-authentik@file when it is blank, and lets bootstrap mode switch the stack to the other chain.
Then give the key a line in containers/<image>/komodo.env, so the run can fill it in:
For a service that signs its own users in, or one that other machines call, write the other chain as a fixed value and add no key:
Warning
chain-no-auth@file puts no sign-in in front of the route. Use it only for a service with a login of its own.
Background: which chain the fleet's own containers use
ntfy, Komodo, Grafana, step-ca, vmauth, Stalwart, and Bulwark fix chain-no-auth@file. Each has its own login or token, and several are called by other services, which cannot follow a redirect to a sign-in page. Authentik fixes it too, since nothing can sign in to reach the sign-in.
Uptime Kuma, Mailpit, Semaphore, Dozzle, Technitium, the blackbox exporter, and the VictoriaMetrics interfaces take the variable. Some of those have no login at all, so the chain is the only thing guarding them.
A forward auth sign-in also needs the service to be known to Authentik. In this fleet one Provider covers every interface behind the chain. See Forward auth.
5. Declare the need for a Traefik¶
In containers/<image>/setup.yaml, say that the container needs a Traefik on its host:
The run reads this to stop when a host lists the stack with no Traefik stack beside it, and to add the stand-in in bootstrap mode. See What it changes.
6. Generate and push¶
From the root of the fleet-stacks checkout, generate the stack's files:
The output ends with Build complete.
Check that Compose accepts the stack:
The command prints nothing when the stack is valid.
Commit the container's folder and the stack's generated files together, and push. Komodo deploys from the pushed main branch.
7. Deploy¶
If a key was added to a komodo.env, write the host's Komodo file again first. A new key reaches a Stack only through that file. See After a change.
In Semaphore, run the site Template with Target set to <host>.
From ~/src/fleet-ansible, in a shell prepared for runs after the handover. See Running from a shell again.
The run's last stage has Komodo sync the host's Stacks, and the sync deploys a Stack whose definition changed.
If only labels changed, the Stack's definition in Komodo is the same as before and the sync may leave it alone. In Komodo's UI, open Resources > Stacks, open the Stack, and click Deploy. Komodo pulls the repo and recreates the container with its new labels.
8. Verify¶
The name needs a DNS record pointing at the host, or an entry in your own machine's hosts file.
Open the host's Traefik dashboard:
Under HTTP Routers, the new router is listed with its rule and no error. Open it. The middleware shown is the chain you chose, and the service shows one server.
Then open the route itself, with your names in place of the example:
The browser shows no certificate warning. Behind chain-authentik@file, Authentik asks for a sign-in and the application loads after it. Behind chain-no-auth@file, the application loads directly.
On a host in bootstrap mode the certificate is self-signed and no chain asks for a sign-in. See What you see in bootstrap mode.
If the router is missing or the page is wrong, see When it goes wrong.
What's next¶
To offer the route to the hub on tf01, or to the internet, see Publishing a route beyond its VM.
Not yet confirmed¶
- The whole page. No route has been added through these steps on a running host.
- Whether the sync redeploys a Stack when only a Compose file in fleet-stacks changed. The page gives the Deploy button as the fallback.
- The wording of the dashboard's router page, which follows Traefik's documentation.
- What a browser sees behind
chain-authentik@filefor a service Authentik's Provider does not cover.