Guides

Traefik Integration

How to pair DNS Resolver with Traefik for zero-config internal service routing.

Traefik Integration

DNS Resolver and Traefik form a natural pair for internal networks:

  • DNS Resolver answers *.home.example.comHOST_IP for every client
  • Traefik receives the HTTPS connection, reads the Host() header, and routes to the correct container

No manual DNS or reverse-proxy configuration is required when adding a new service — Traefik's Docker provider discovers it automatically, and DNS Resolver makes the name resolvable immediately.

Network setup

Both DNS Resolver and all routed services must share a Docker network. The conventional name is dns-net:

networks:
  dns-net:
    name: dns-net

Traefik must also be attached to this network so it can reach container backends.

Minimal compose example

networks:
  dns-net:
    name: dns-net

services:
  dns:
    image: ghcr.io/circle-rd/dns-resolver:latest
    container_name: dns
    restart: unless-stopped
    ports:
      - "${HOST_IP}:53:53/udp"
      - "${HOST_IP}:53:53/tcp"
    environment:
      - DOMAIN=${DOMAIN}
      - HOST_IP=${HOST_IP}
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - dns-net

  traefik:
    image: traefik:v3
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    command:
      - --providers.docker=true
      - --providers.docker.network=dns-net
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - dns-net

  my-service:
    image: my-image:latest
    restart: unless-stopped
    networks:
      - dns-net
    labels:
      - traefik.enable=true
      - traefik.http.routers.my-service.rule=Host(`my-service.${DOMAIN}`)
      - traefik.http.routers.my-service.entrypoints=websecure
      - traefik.http.routers.my-service.tls=true

When my-service starts:

  1. docker-gen detects the container event and rewrites /etc/coredns/hosts (within DOCKERGEN_WAIT)
  2. CoreDNS reloads the hosts file (within HOSTS_RELOAD)
  3. my-service.home.example.com resolves to HOST_IP
  4. HTTPS traffic arrives at Traefik, which routes it to my-service via the Host() header

Point clients to DNS Resolver

Set your router's DHCP to hand out HOST_IP as the DNS server, or configure individual devices:

# Linux (NetworkManager)
nmcli connection modify "Wired connection 1" ipv4.dns "192.168.1.10"

# macOS — System Settings → Network → DNS

# Windows — Network adapter → IPv4 Properties → Preferred DNS server

Or configure only your Docker services to use the internal DNS without changing host settings:

# Any service compose.yml
services:
  my-app:
    dns:
      - 192.168.1.10

Internal certificate issuance

To issue TLS certificates for *.home.example.com without a public CA, combine DNS Resolver with:

  • uPKI CA + uPKI RA — ACME v2 endpoint backed by your private CA
  • Or step-ca / Vault PKI with the DNS-01 challenge via ACME DNS-01

Traefik's dnsChallenge certificate resolver sends the _acme-challenge query to DNS Resolver, which forwards it to the acme-dns sidecar when ACME_DNS_ENABLED=true.

Copyright © 2026