Logo
Published on

Setting up Traefik and Proxying Traffic through Cloudflare

Authors
  • avatar
    Name
    Ayden Jahola
    Twitter
Table of Contents

What is Traefik?

Traefik is a modern open-source HTTP reverse proxy and load balancer designed for speed and performance. It simplifies the deployment of microservices and is ideal for containerized environments. As a cloud-native edge router, Traefik can route traffic to various services based on flexible rules and configurations. This guide will demonstrate how to set up Traefik using Docker and Docker Compose.

Prerequisites

Ensure you have the following installed on your system:

Setting up Traefik

Follow these steps to configure Traefik with Docker and Docker Compose:

Step 1: Create a Directory for Traefik

mkdir traefik
cd traefik

Step 2: Create a docker-compose.yml File

Create a docker-compose.yml file with the following contents:

---
services:
  traefik:
    image: traefik:latest
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy # Network for public services (exposed to the internet)
    ports:
      - 80:80 # HTTP port
      - 443:443 # HTTPS port
    environment:
      - CF_API_EMAIL=${CF_API_EMAIL} # Cloudflare email
      - CF_API_KEY=${CF_API_KEY} # Cloudflare API key
    volumes:
      - /etc/localtime:/etc/localtime:ro # Sync time
      - /var/run/docker.sock:/var/run/docker.sock:ro # Docker socket
      - ./traefik.yml:/traefik.yml:ro # Traefik configuration
      - ./traefik_dynamic.yml:/traefik_dynamic.yml:ro # Dynamic configuration (optional)
      - ./acme.json:/acme.json # SSL certificates
    labels:
      - 'traefik.enable=true' # Enable Traefik
      - 'traefik.http.routers.api.entrypoints=https' # Enable HTTPS
      - 'traefik.http.routers.api.rule=Host(`traefik.yourdomain.com`)' # Traefik dashboard
      - 'traefik.http.routers.api.service=api@internal' # Internal service

networks: # Create Docker networks
  proxy: # Public network
    external: true # External network

Step 3: Create the traefik.yml Configuration File

api:
  dashboard: true # Enable the Traefik dashboard

entryPoints: # Define entry points for HTTP and HTTPS
  http:
    address: ':80'
    http:
      redirections: # Redirect HTTP to HTTPS
        entryPoint:
          to: 'https'
          scheme: 'https'
          permanent: true # Permanent redirect (301)
  https:
    address: ':443'
    http:
      tls:
        certresolver: cloudflare # Use Cloudflare for SSL certificates
        domains: # Define domains for SSL certificates
          - main: 'yourdomain.com' # Main domain (root)
            sans: '*.yourdomain.com' # Wildcard domain (subdomains)

certificatesResolvers: # Define certificate resolvers for SSL certificates (Cloudflare)
  cloudflare:
    acme:
      storage: 'acme.json' # Storage for SSL certificates (acme.json)
      dnsChallenge: # Use DNS challenge for SSL certificates
        provider: 'cloudflare' # Cloudflare as the DNS provider
        delayBeforeCheck: 90 # Delay before checking DNS propagation
        disablePropagationCheck: true # Disable DNS propagation check
        resolvers:
          - '1.1.1.1:53' # Cloudflare DNS resolver
          - '1.0.0.1:53' # Cloudflare DNS resolver

providers: # Define providers for dynamic configuration
  docker: # Docker provider
    watch: true # Watch Docker containers
    network: 'proxy' # Network for public services (exposed to the internet)
    exposedbydefault: false # Expose services by default (false)
    endpoint: 'unix:///var/run/docker.sock' # Docker socket endpoint
  file: # File provider (optional)
    filename: 'traefik_dynamic.yml' # Dynamic configuration file (traefik_dynamic.yml)

Step 4: Create the traefik_dynamic.yml File

Refer to Traefik's documentation for dynamic configuration options. Customize as needed.

Step 5: Set Up acme.json

touch acme.json
chmod 600 acme.json

Step 6: Configure .env for Cloudflare Credentials

CF_API_EMAIL=[email protected]
CF_API_KEY=your-api-key # Cloudflare API key (generate from Cloudflare dashboard)

Step 7: Create the Docker Networks

docker network create proxy # Public network (exposed to the internet)
docker network create internal # Internal network (not exposed to the internet)

Step 8: Start Traefik

docker compose up -d

Configuring Cloudflare DNS

Publicly Exposed Services

  1. Log in to Cloudflare.
  2. Select your domain.
  3. Go to the DNS tab.
  4. Add an A record:
    • Name: home
    • IPv4 Address: Your public IP
    • TTL: Automatic
    • Proxy Status: Proxied
  5. Add a CNAME record:
    • Name: traefik
    • Target: home.yourdomain.com
    • TTL: Automatic
    • Proxy Status: Proxied

I use CNAME records to point to the home record, which is the public IP of the server. This setup allows for easy IP changes without updating multiple records. The home record is proxied to hide the server's IP address.

Internally Exposed Services

  1. Log in to Cloudflare.
  2. Select your domain.
  3. Go to the DNS tab.
  4. Add an A record:
    • Name: local
    • IPv4 Address: Your servers internal IP (e.g., 192.168.1.34)
    • TTL: Automatic
    • Proxy Status: DNS Only

For services only accessible internally, you can use traefik.local.yourdomain.com without additional DNS configuration.

Accessing the Traefik Dashboard

Navigate to https://traefik.yourdomain.com to access the Traefik dashboard. You can monitor and manage your services from this interface.

Example Service Configuration (Plausible)

Here's an example of how to configure a service (e.g., Plausible) with Traefik:

---
services:
  plausible:
    image: ghcr.io/plausible/community-edition:v2.1.1
    container_name: plausible
    command: sh -c "/entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
    depends_on:
      - plausible_db
      - plausible_events_db
      - mail
    env_file:
      - plausible-conf.env
    environment:
      - DISABLE_REGISTRATION=true
    restart: always
    labels: # Traefik labels
      - 'traefik.enable=true' # Enable Traefik
      - 'traefik.http.routers.plausible.rule=Host(`plausible.yourdomain.com`)' # Plausible domain
      - 'traefik.http.routers.plausible.entrypoints=https' # Enable HTTPS entry point
      - 'traefik.http.services.plausible.loadbalancer.server.port=8000' # if the app doesnt use 80 or 443 you can specify the port here, in this case plausible uses 8000
    networks: # Docker networks
      - internal # Internal network (not exposed to the internet, so the DB and Mail services can communicate with Plausible)
      - proxy # Public network (exposed to the internet)

  plausible_db:
    image: postgres:16-alpine
    container_name: plausible-db
    restart: always
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    networks: # Docker networks
      - internal # Internal network (so that the Plausible service can communicate with the DB on the ineternal network only)

networks: # Docker networks
  proxy: # Public network
    external: true # External network (exposed to the internet)
  internal: # Internal network (not exposed to the internet)
    external: false # Internal network (not exposed to the internet)

Conclusion

This guide provided a step-by-step process for setting up Traefik with Docker and Docker Compose, integrating it with Cloudflare for traffic proxying. Traefik is a robust solution for managing traffic to microservices, offering both simplicity and scalability. If you encounter any issues, feel free to reach out for assistance.

My Homelab configs can be found here.