🏡 Home
Back to notes

Traefik

Last updated on 07 January 2025

Most of my personal services I run within my Tailscale network, and so I do not tend to bother with HTTPS (since provisioning TLS certificates for multiple services running on a single host via Tailscale is a pain).

However, for external services that need to be accessed publicly, I use Traefik [1] as a reverse proxy and for managing and provisioning TLS certificates.

1

Running Traefik

Run Traefik using Docker. Create a `docker-compose.yml` file in a directory called `traefik`:

services:
  reverse-proxy:
    image: traefik:v2.6
    container_name: traefik
    command:
      - "--providers.docker"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.email=CHANGEME"
      - "--certificatesresolvers.myresolver.acme.storage=/etc/traefik/acme/acme.json"
      - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./acme:/etc/traefik/acme # To persist certificate info
      - /var/run/docker.sock:/var/run/docker.sock # To access the host Docker daemon
    networks:
      - net
    restart: always

networks:
  net:
    driver: bridge

Rate-limiting

Sometimes it is useful to rate-limit access to services via Traefik. For example, I recently experienced bots scraping my Gitea instance, causing the host to be partially overloaded.

Rate-limit rules can be set using standard Traefik labels in the compose definition for the relevant service. For example, in my Gitea `docker-compose.yml` file:

...
  - traefik.http.routers.gitea.middlewares=gitea-ratelimit
  - traefik.http.middlewares.gitea-ratelimit.ratelimit.average=2
  - traefik.http.middlewares.gitea-ratelimit.ratelimit.period=1s
  - traefik.http.middlewares.gitea-ratelimit.ratelimit.burst=5

The bridge network

This setup creates a bridge network into which we will add other services. This allows Traefik to route traffic to them.

The directory name (`traefik`) is important (in my case) since my services rely on the fact that the network created is called `traefik_net`.

Adding other services

When adding other services, follow these steps:

1. Set-up DNS such that your chosen domain name points to the server

1. Create a `docker-compose.yml` for the service with Traefik labels (see below)

1. Bring up the service

An example `docker-compose.yml` for a Traefik-connected service:

services:
  example:
    image: example
    networks:
      - traefik_net
    labels:
      - traefik.http.routers.servicename.rule=Host(`domain.com`)
      - traefik.http.routers.servicename.tls=true
      - traefik.http.routers.servicename.tls.certresolver=myresolver

networks:
  traefik_net:
    external: true

Change `domain.com` to the real domain (or subdomain) and change `servicename` to a unique name in your Traefik network.

When you bring the service up, Traefik will detect it and then auto-provision and renew the TLS certificates.

Back to notes