Skip to content

Traefik

Traefik is the beating heart of my homelab. Every connection comes into traefik which then routes the traffic to the application being requested/served

I have a domain with Cloudflare and have created subdomains for all of my services.
It also uses Lets Encrypt and provides a valid SSL certificate

alt text

With Traefik, I also have the abillity to specify multiple entry points (2 internal and 2 external) This allows me to keep my internal services internal and only have my external services showing to the world.
The section Traefik Entry Points will explain more about these.

Directory Location Layout:

/ssd/appdata/traefik/
├── data
   ├── acme.json
   └── traefik.yml
├── docker-compose.yml
├── dynamic
   ├── app-cctv.yml
   ├── app-cmk.yml
   ├── app-docs.yml
   ├── app-graphs.yml
   ├── app-kuma.yml
   ├── app-pihole1.yml
   ├── app-pihole2.yml
   ├── app-portainer-cuthbert.yml
   ├── app-prom.yml
   ├── app-ubuntu.yml
   ├── app-unifi.yml
   ├── app-vaultwarden.yml
   ├── app-xbvr.yml
   └── config.yml
└── .env

docker-compose.yml

Below is the Docker Compose file (you will notice this also includes Portainer) Sensitive information is placed in a hidden .env file which is then referenced within the docker-compose.

networks:
  default:
    name: proxy
    external: true

services:

  traefik:
    image: traefik:3.1.0-rc3
    container_name: traefik
    restart: always
    networks:
      default:
        ipv4_address: "172.19.0.2"
    ports:
      - 80:80
      - 81:81
      - 443:443
      - 444:444
      - 8088:8088
    environment:
      - CF_API_EMAIL=${CF_API_EMAIL}
      - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /ssd/appdata/traefik/data/traefik.yml:/traefik.yml:ro
      - /ssd/appdata/traefik/data/acme.json:/acme.json
      - /ssd/appdata/traefik/dynamic:/ssd/appdata/traefik/dynamic
      - traefik-logs:/var/log/traefik
    labels:
      - traefik.enable=true
      - traefik.http.routers.traefik_https.rule=Host(`subdomain.domain.co.uk`)
      - traefik.http.routers.traefik_https.entrypoints=websecure-int
      - traefik.http.routers.traefik_https.tls=true
      - traefik.http.routers.traefik_https.tls.certresolver=production
      - traefik.http.routers.traefik.tls.domains[0].main=domain.co.uk
      - traefik.http.routers.traefik.tls.domains[0].sans=*.domain.co.uk
      - traefik.http.routers.traefik_https.service=api@internal

  portainer:
    image: portainer/portainer-ee:2.19.5
    container_name: portainer
    networks:
      default:
        ipv4_address: "172.19.0.3"
    command: -H unix:///var/run/docker.sock
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    labels:
      - traefik.enable=true
      - traefik.http.services.portainer.loadbalancer.server.port=9000
      - traefik.http.routers.portainer.rule=Host(`subdomain.domain.co.uk`)
      - traefik.http.routers.portainer.entrypoints=websecure-int
      - traefik.http.routers.portainer.tls=true
      - traefik.http.routers.portainer.tls.certresolver=production
      - traefik.http.routers.portainer.tls.domains[0].main=domain.co.uk
      - traefik.http.routers.portainer.tls.domains[0].sans=*.domain.co.uk

volumes:
  portainer_data:
  traefik-logs:

traefik.yml

The traefik.yml file lives inside the "data" directory and is used to:

enable/disable the dashboard, define entry points, assign middleware at a global level (rather than at an application level), specify your certificate resolver details, detail your docker provider and the docker socket address aswell as dynamic files/directory location. Finally you can also, optionally, provide the location of log files and details of any collector of metrics.

global:
  checkNewVersion: true
  sendAnonymousUsage: false

api:
  dashboard: true
  debug: true

entryPoints:
#internal
  web-int:
    address: :80
    http:
      redirections:
        entryPoint:
          to: websecure-int
          scheme: https
  websecure-int:
    address: :443
    http:
      middlewares:
        - global-default-headers@file
#external
  web-ext:
    address: :81
    http:
      redirections:
        entryPoint:
          to: websecure-ext
          scheme: https
  websecure-ext:
    address: :444
    http:
      middlewares:
        - global-default-headers@file
  metrics:
    address: :8088

certificatesResolvers:
  production:
    acme:
      email: <e-mail address>>
      storage: acme.json
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"

serversTransport:
  insecureSkipVerify: true

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    directory: /ssd/appdata/traefik/dynamic/
    watch: true

log:
  level: "INFO"
  filePath: "/var/log/traefik/traefik.log"

accessLog:
  filePath: "/var/log/traefik/access.log"

metrics:
  prometheus:
    addRoutersLabels: true
    addServicesLabels: true
    entryPoint: metrics
    buckets:
        - 0.1
        - 0.3
        - 1.2
        - 5.0

Dynamic Files Directory

Dynamic files can be very useful for services that are running on other hosts and are/aren't running in docker

As its "dynamic" you can make changes to these files and they will instantly take effect without needing to restart traefik

The section Traefik Dynamic Files goes into more detail about these files and shows examples.