Traefik Setup For Home-Lab

Traefik is a leading modern open source reverse proxy and ingress controller that makes deploying services and APIs easy. Traefik integrates with your existing infrastructure components and configures itself automatically and dynamically. Traefik also comes with a powerful set of middlewares that enhance its capabilities to include load balancing, API gateway, orchestrator ingress, and more. Now that we have an understanding of this reverse proxy, let us get started with the setup for our home-lab.

Before we get into the installation details of traefik, we need a working docker environment and you can follow this guide below to set it up.

How to Install Docker on Debian 13 (Trixie)
Debian is one of the most well-known and respected names in the Linux world, which doesn’t need much of an introduction. As a general-purpose distribution, it’s built a rock-solid reputation for stability and reliability, making it a go-to choice for millions of people from regular home users to
How to Install Docker on Arch Linux: A Step-by-Step Guide
If you’re venturing into the world of containerization and looking for an efficient way to deploy applications, Docker is the tool you need. But what’s better than harnessing the power of containerization on a linux distro that keeps you on the cutting edge? Arch’s rolling release nature

Now create a docker-compose.yaml file and paste this:

secrets:
  cf-token:
    file: ./cf-token
services:
  traefik:
    image: traefik:latest # or traefik:v3.3 to pin a version
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true # helps to increase security
    secrets:
      - cf-token # the secret at the top of this file
    env_file:
      - .env # store other secrets e.g., dashboard password
    networks:
       proxy:
    ports:
      - 80:80
      - 443:443
     # - 10000:10000 # optional
     # - 33073:33073 # optional
    environment:
      - TRAEFIK_DASHBOARD_CREDENTIALS=${TRAEFIK_DASHBOARD_CREDENTIALS}
      # - [email protected] # Cloudflare email
      # - CF_DNS_API_TOKEN=YOUR-TOKEN # Cloudflare API Token
      - CF_DNS_API_TOKEN_FILE=/run/secrets/cf-token # see https://doc.traefik.io/traefik/https/acme/#providers
      # token file is the proper way to do it
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /home/ubuntu/docker/traefik/traefik.yaml:/traefik.yaml:ro
      - /home/ubuntu/docker/traefik/acme.json:/acme.json
      - /home/ubuntu/docker/traefik/config.yaml:/config.yaml:ro
      - /home/ubuntu/docker/traefik/logs:/var/log/traefik
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=http"
      - "traefik.http.routers.traefik.rule=Host(`traefik-docker.linuxpad.blog`)"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}"
      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
      - "traefik.http.routers.traefik-secure.entrypoints=https"
      - "traefik.http.routers.traefik-secure.rule=Host(`traefik-docker.linuxpad.blog`)"
      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.tls=true"
      - "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
      - "traefik.http.routers.traefik-secure.tls.domains[0].main=linuxpad.blog"
      - "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.linuxpad.blog"
      - "traefik.http.routers.traefik-secure.service=api@internal"

networks:
  proxy:
    external: true # or comment this line to auto create the network

Next is create a config.yaml file and paste this:

http:
  middlewares:    
    default-security-headers:
      headers:
        customBrowserXSSValue: 0                            # X-XSS-Protection=1; mode=block
        contentTypeNosniff: true                          # X-Content-Type-Options=nosniff
        forceSTSHeader: true                              # Add the Strict-Transport-Security header even when the connection is HTTP
        frameDeny: false                                   # X-Frame-Options=deny
        referrerPolicy: "strict-origin-when-cross-origin"
        stsIncludeSubdomains: true                        # Add includeSubdomains to the Strict-Transport-Security header
        stsPreload: true                                  # Add preload flag appended to the Strict-Transport-Security header
        stsSeconds: 3153600                              # Set the max-age of the Strict-Transport-Security header (63072000 = 2 years)
        contentSecurityPolicy: "default-src 'self'"     
        customRequestHeaders:
          X-Forwarded-Proto: https
    https-redirectscheme:
      redirectScheme:
        scheme: https
        permanent: true
    authelia:
      forwardAuth:
        address: "http://authelia:9091/api/verify?rd=https://auth.linuxpad.blog"
        trustForwardHeader: true
        authResponseHeaders:
          - Remote-User
          - Remote-Groups
          - Remote-Name
          - Remote-Email

  routers:
    portainer:
      entryPoints:
        - "https"
      rule: "Host(`portainer.linuxpad.blog`)"
      middlewares:
        - authelia
        - default-security-headers
        - https-redirectscheme
      tls: {}
      service: portainer

    proxmox:
      entryPoints:
        - "https"
      rule: "Host(`proxmox.linuxpad.blog`)"
      middlewares:
        - authelia
        - default-security-headers
        - https-redirectscheme
      tls: {}
      service: proxmox
    
    beszel:
      entryPoints:
        - "https"
      rule: "Host(`beszel.linuxpad.blog`)"
      middlewares:
        - authelia
        - default-security-headers
        - https-redirectscheme
      tls: {}
      service: beszel

    dozzle: 
      entryPoints:
        - "https"
      rule: "Host(`dozzle.linuxpad.blog`)"
      middlewares:
        - authelia
        - default-security-headers
        - https-redirectscheme
      tls: {}
      service: dozzle
    
    homepage:
      entryPoints:
        - "https"
      rule: "Host(`linuxpad.blog`)"
      middlewares:
        - authelia
        - default-security-headers
        - https-redirectscheme
      tls: {}
      service: homepage
    
    vaultwarden:
      entryPoints:
        - "https"
      rule: "Host(`vaultwarden.linuxpad.blog`)"
      middlewares:
        - authelia
        - default-security-headers
        - https-redirectscheme
      tls: {}
      service: vaultwarden
    
    uptime-kuma:
      entryPoints:
        - "https"
      rule: "Host(`uptime-kuma.linuxpad.blog`)"
      middlewares:
        - authelia
        - default-security-headers
        - https-redirectscheme
      tls: {}
      service: uptime-kuma

    dockge:
      entryPoints:
        - "https"
      rule: "Host(`dockge.linuxpad.blog`)"
      middlewares:
        - authelia
        - default-security-headers
        - https-redirectscheme
      tls: {}
      service: dockge


  services:
    portainer:
      loadBalancer:
        servers:
          - url: "https://192.168.8.183:9443"
        passHostHeader: true
    
    proxmox:
      loadBalancer:
        servers:
          - url: "https://192.168.8.178:8006"
        passHostHeader: true
    
    dozzle:
      loadBalancer:
        servers:
          - url: "http://192.168.8.188:9999"
        passHostHeader: true
    
    beszel:
      loadBalancer:
        servers:
          - url: "http://192.168.8.188:8090"
        passHostHeader: true

    homepage:
      loadBalancer:
        servers:
          - url: "http://192.168.8.188:3030"
        passHostHeader: true
    
    vaultwarden:
      loadBalancer:
        servers:
          - url: "http://192.168.8.188:4044"
        passHostHeader: true
    

    uptime-kuma:
      loadBalancer:
        servers:
          - url: "http://192.168.8.188:3001"
        passHostHeader: true
    
    dockge:
      loadBalancer:
        servers:
          - url: "http://192.168.8.188:5001"
        passHostHeader: true

Also create a traefik.yaml file and paste this:

api:
  dashboard: true
  debug: true
entryPoints:
  http:
    address: ":80"
    http:
    #  middlewares: # uncomment if using CrowdSec - see my video
    #    - crowdsec-bouncer@file
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"
    # http:
    #  middlewares: # uncomment if using CrowdSec - see my video
    #    - crowdsec-bouncer@file
  # tcp:
   # address: ":10000"
  # apis:
   # address: ":33073"
serversTransport:
  insecureSkipVerify: true
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: /config.yaml # example provided gives A+ rating https://www.ssllabs.com/ssltest/
certificatesResolvers:
  cloudflare:
    acme:
      # caServer: https://acme-v02.api.letsencrypt.org/directory # production (default)
      # caServer: https://acme-staging-v02.api.letsencrypt.org/directory # staging (testing)
      email: [email protected] # Cloudflare email (or other provider)
      storage: acme.json
      dnsChallenge:
        provider: cloudflare # change as required
        # disablePropagationCheck: true # Some people using Cloudflare note this can solve DNS propagation issues.
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"

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

t

Finally, paste this into the .env file:

TRAEFIK_DASHBOARD_CREDENTIALS=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/

The default credential for TREAFIK_DASHBOARD_CREDENTIALS is test:test.