Skip to Content

Self-Host Traefik: The Ultimate Reverse Proxy for Your Homelab in 20 Minutes

Self-Host Traefik: The Ultimate Reverse Proxy for Your Homelab in 20 Minutes

Tired of manually configuring Nginx every time you add a service? Traefik auto-discovers your Docker containers and handles routing, SSL, and load balancing — zero config files required.

Why Traefik?

Traditional reverse proxies like Nginx or Apache require you to manually edit config files and reload services every time you add or change a backend. Traefik flips this model: it watches your Docker socket (or Kubernetes API, Consul, etc.) and automatically creates routes for containers with the right labels.

What you get:

  • Auto-discovery: New containers get routes instantly via Docker labels
  • Automatic HTTPS: Let's Encrypt integration with HTTP-01 or DNS-01 challenges
  • Middleware: Built-in auth, rate limiting, headers, redirects, circuit breakers
  • Dashboard: Real-time view of routers, services, and middlewares
  • Lightweight: Single binary, ~30MB RAM, no external dependencies

Prerequisites

  • A VPS or server with Docker + Docker Compose installed
  • A domain pointed to your server (e.g., *.sysbrix.com A record)
  • Ports 80 and 443 open
  • 5 minutes of actual work — the rest is copy-paste

Step 1: Create the Docker Network

Traefik needs a shared network to reach your containers:

docker network create web

Step 2: Docker Compose for Traefik

Create ~/traefik/docker-compose.yml:

version: "3.8"

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    restart: unless-stopped
    command:
      # API and Dashboard
      - "--api.dashboard=true"
      - "--api.insecure=false"
      # Docker provider
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=web"
      # Entrypoints
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      # Redirect HTTP to HTTPS
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      # Let's Encrypt
      - "[email protected]"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      # Logging
      - "--log.level=INFO"
      - "--accesslog=true"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
    networks:
      - web
    labels:
      # Dashboard via traefik.sysbrix.com (optional, add auth!)
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.sysbrix.com`)"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
      # Basic auth for dashboard (user: admin, password: changeme)
      - "traefik.http.routers.dashboard.middlewares=dashboard-auth"
      - "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$2y$$05$$rW0zZ6Y0Z0Z0Z0Z0Z0Z0Z0u3Z0Z0Z0Z0Z0Z0Z0Z0Z0Z0Z0Z0Z0Z0"

networks:
  web:
    external: true
Note: The basic auth hash above is a placeholder. Generate a real one with: htpasswd -nb admin yourpassword | sed -e s/\$/\$\$/g

Step 3: Start Traefik

cd ~/traefik
mkdir -p letsencrypt
chmod 600 letsencrypt
docker compose up -d

Step 4: Route a Container (The Magic Part)

Here's where Traefik shines. To expose any container, just add labels:

version: "3.8"

services:
  whoami:
    image: traefik/whoami
    container_name: whoami
    networks:
      - web
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.sysbrix.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"

networks:
  web:
    external: true

That's it. No Nginx reloads. No DNS juggling. Traefik sees the labels, gets the SSL cert, and routes traffic.

Step 5: Add Middleware (Auth, Headers, Rate Limit)

labels:
  # ... router labels ...
  # Rate limit: 100 requests per 10 seconds
  - "traefik.http.middlewares.ratelimit.ratelimit.average=100"
  - "traefik.http.middlewares.ratelimit.ratelimit.period=10s"
  # Security headers
  - "traefik.http.middlewares.secure-headers.headers.stsSeconds=31536000"
  - "traefik.http.middlewares.secure-headers.headers.contentTypeNosniff=true"
  - "traefik.http.middlewares.secure-headers.headers.frameDeny=true"
  # Apply middlewares
  - "traefik.http.routers.whoami.middlewares=ratelimit,secure-headers"

Verification

  1. Check Traefik is running: docker logs traefik — look for "Configuration loaded"
  2. Test HTTP redirect: curl -I http://whoami.sysbrix.com → should return 301 to HTTPS
  3. Test HTTPS: curl https://whoami.sysbrix.com → valid cert + response
  4. Dashboard: Visit https://traefik.sysbrix.com (if enabled)

Real-World Example: Exposing Grafana

services:
  grafana:
    image: grafana/grafana:latest
    networks: [web]
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.grafana.rule=Host(`grafana.sysbrix.com`)"
      - "traefik.http.routers.grafana.entrypoints=websecure"
      - "traefik.http.routers.grafana.tls.certresolver=letsencrypt"
      - "traefik.http.services.grafana.loadbalancer.server.port=3000"

Next Steps

  • Wildcard certs: Switch to DNS-01 challenge for *.sysbrix.com certs
  • Authentik/Keycloak: Add forward-auth middleware for SSO across all services
  • Fail2ban: Ban IPs at the Traefik level for extra security
  • Metrics: Enable Prometheus metrics and visualize in Grafana

Traefik turns reverse proxy management from a chore into a non-event. Add a label, get HTTPS. That's the way it should have always worked.

Self-Host n8n + AI: Build Intelligent Automation Workflows in 20 Minutes