Traefik store certificates in acme.json file unlike Caddy for instance that stores certificates that could be directly imported into Adguard.

By default - Traefik won’t terminate DOT TLS traffic, so it could only forward it to another host. Here we will have to customize Traefik in order to make the TLS termination work. So, let’s assume You have already running Adguardhome in Your kubernetes cluster and Traefik itself is functioning fine:

1. Make an ingress route rule

IngressRoute here is being used instead of Ingress rules, as it allow to configure more settings:

For this step we assume that Adguard service is already working. Good starting point could be this helm chart: adguard-home | TrueCharts Charts

# Traefik IngressRoute for DNS-over-TLS (DoT) with TLS termination
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: adguardhome-dot
spec:
  entryPoints:
    - dot
  routes:
    - match: HostSNI(`adguard.domain.com`)
      services:
        - name: adguard-service-name
          port: 53  # Plain DNS port since Traefik handles TLS
  tls:
    certResolver: wildcard
    domains:
      - main: "domain.com"
        sans:
          - "*.domain.com"
    options:
      name: dot-tls-options

Next we are going to create dot-tls-options manifest. As You can see - we don’t need to enable TLS in Adguard itself, but the Traefik will work for TLS termination.

2. TLS Options file

Here we specify the actual TLS Options. As You could see - here we actually enable DOT protocol, so that Traefik understand what to do with incoming traffic.

# TLS Options for DNS-over-TLS ALPN support
apiVersion: traefik.io/v1alpha1
kind: TLSOption
metadata:
  name: dot-tls-options
spec:
  alpnProtocols:
    - "dot"  # Enable DNS-over-TLS ALPN protocol
  minVersion: "VersionTLS12"
  cipherSuites:
    - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
    - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
    - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"

3. Finally - modify Traefik itself.

In this example we assume that Traefik comes preinstalled as Helm chart on k3s

# HelmChartConfig for Traefik with DoT support
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
  
    ports:
      # Configure DNS over TLS 
      dot:
        port: 8853
        expose:
          default: true
        exposedPort: 853
        protocol: TCP
        tls:
          enabled: true
          # Enable ALPN protocol for DNS over TLS
          options: dot-tls-options
    
    additionalArguments:
      # Add DoT entrypoint with ALPN support
      - "--entrypoints.dot.address=:8853"
      - "--entrypoints.dot.transport.lifecycles.requestAcceptGraceTimeout=30s"
      - "--entrypoints.dot.transport.lifecycles.graceTimeOut=30s"
      
    # Global TLS options
    tlsOptions:
      dot-tls-options:
        alpnProtocols:
          - "dot"
        minVersion: "VersionTLS12"

So - that’s it. This should work as DNS over TLS solution for Pihole as well not only Adguard Home.