InfraRunBook
    Back to articles

    Traefik Lets Encrypt ACME Challenge Types Explained

    Traefik
    Published: Apr 9, 2026
    Updated: Apr 9, 2026

    A practical engineer's guide to Traefik's three ACME challenge types — HTTP-01, TLS-ALPN-01, and DNS-01 — with real configuration examples and decision criteria for Let's Encrypt certificate automation.

    Traefik Lets Encrypt ACME Challenge Types Explained

    What ACME Is and Why It Drives Modern TLS Automation

    The ACME (Automatic Certificate Management Environment) protocol is the machine-to-machine handshake that lets services like Let's Encrypt issue TLS certificates without you filing a support ticket or pasting a CSR into a web form. Traefik has first-class ACME support baked in — configure a

    certificatesResolvers
    block and Traefik handles everything from initial account registration to certificate renewal. But the protocol defines three distinct challenge types: HTTP-01, TLS-ALPN-01, and DNS-01. Picking the wrong one for your environment will either block certificate issuance entirely or create operational headaches you won't notice until a cert expires at 2 AM.

    I want to walk through each challenge type in depth, show real Traefik configuration for each, and clear up the misconceptions I see engineers run into repeatedly.

    How ACME Challenges Work

    The fundamental question ACME answers is: does the entity requesting this certificate actually control the domain? Let's Encrypt can't take your word for it. The challenge is the proof-of-control mechanism. You request a certificate, Let's Encrypt issues a challenge token, you fulfill the challenge by placing that token somewhere predictable, and Let's Encrypt's validation infrastructure verifies it. Pass the check, get the cert.

    Traefik handles all of this automatically once configured. You don't manually respond to challenges — Traefik does it on your behalf. But you still need to understand what each challenge type requires from your infrastructure, because they have very different prerequisites that determine whether they'll work in your specific deployment topology.

    HTTP-01 Challenge

    HTTP-01 is the simplest and most commonly deployed challenge type. Let's Encrypt generates a token and expects to retrieve it from a well-known URL path on your domain over plain HTTP on port 80:

    http://solvethenetwork.com/.well-known/acme-challenge/<token>

    Traefik handles this by temporarily serving the challenge token on the HTTP entry point via its built-in challenge handler. Port 80 must be reachable from the public internet, and the DNS A record for your domain must resolve to the IP address where Traefik is running — specifically, an address that Let's Encrypt's validation servers can reach.

    Here's a minimal Traefik static configuration using HTTP-01:

    entryPoints:
      web:
        address: ":80"
      websecure:
        address: ":443"
        http:
          tls:
            certResolver: letsencrypt
    
    certificatesResolvers:
      letsencrypt:
        acme:
          email: infrarunbook-admin@solvethenetwork.com
          storage: /traefik/certs/acme.json
          httpChallenge:
            entryPoint: web

    The

    httpChallenge.entryPoint
    value must reference an entry point bound to port 80. Traefik intercepts requests to the
    .well-known/acme-challenge
    path on that entry point and serves the token directly — before any of your routing rules evaluate the request. You don't need to configure a separate router for this; it happens transparently at the middleware layer.

    The catch with HTTP-01 is that port 80 must be directly reachable from the outside. In my experience, this is the single most common reason HTTP-01 validation fails silently — engineers get the Traefik config right but miss a security group rule, an iptables DROP, or a CDN proxy mode that strips port 80 challenges before they reach the origin. Let's Encrypt's validation servers make outbound HTTP connections from their own IP ranges. Your firewall doesn't know they're special. Traefik's logs will show the failed validation attempt if you look, but because Traefik retries in the background, the failure isn't surfaced prominently.

    HTTP-01 also doesn't support wildcard certificates. You can only validate explicit hostnames, not patterns like

    *.solvethenetwork.com
    . For wildcards, DNS-01 is required.

    TLS-ALPN-01 Challenge

    TLS-ALPN-01 is the least-discussed challenge type, but it solves a specific problem well. It performs domain validation entirely over TLS on port 443, using a special Application-Layer Protocol Negotiation extension value (

    acme-tls/1
    ). Let's Encrypt initiates a TLS handshake to your server, and Traefik responds with a self-signed certificate containing the challenge token embedded in a TLS extension field (
    id-pe-acmeIdentifier
    ). No HTTP, no DNS API — just a TLS handshake on the port you're already using.

    Configuring it in Traefik is about as minimal as it gets:

    entryPoints:
      websecure:
        address: ":443"
    
    certificatesResolvers:
      letsencrypt:
        acme:
          email: infrarunbook-admin@solvethenetwork.com
          storage: /traefik/certs/acme.json
          tlsChallenge: {}

    tlsChallenge
    takes no arguments. Traefik automatically handles the ALPN negotiation on the entry point bound to port 443. There's no separate entry point reference needed — it's inferred from the
    websecure
    entry point that's listening on 443.

    The practical benefit here is that you only need port 443 open. If you're running an HTTPS-only service and have closed port 80 entirely, TLS-ALPN-01 is your fallback without the complexity of DNS-01. It still requires that port 443 is directly accessible from Let's Encrypt's validation servers — so it won't work behind a terminating load balancer or a CDN that handles TLS upstream of Traefik. If something else is doing TLS termination before the connection reaches sw-infrarunbook-01, Traefik never sees the ALPN extension and the challenge fails.

    I've found TLS-ALPN-01 most useful for single-node deployments where HTTP-01 isn't viable but setting up DNS provider API credentials is more overhead than the situation warrants. It's a good middle ground. Like HTTP-01, it doesn't support wildcard certificates.

    DNS-01 Challenge

    DNS-01 is the most capable challenge type and the only one that supports wildcard certificates. Instead of serving content over HTTP or TLS, you prove domain ownership by creating a specific DNS TXT record under the

    _acme-challenge
    subdomain:

    _acme-challenge.solvethenetwork.com IN TXT "<token>"

    Let's Encrypt queries the authoritative DNS server for that record. If the token matches, validation passes. Traefik automates this using the

    lego
    library under the hood, which supports dozens of DNS providers through their respective APIs.

    The critical requirement is that Traefik needs API credentials for your DNS provider to create and clean up TXT records automatically. Here's the static config for DNS-01 using Cloudflare as the provider:

    entryPoints:
      websecure:
        address: ":443"
    
    certificatesResolvers:
      letsencrypt:
        acme:
          email: infrarunbook-admin@solvethenetwork.com
          storage: /traefik/certs/acme.json
          dnsChallenge:
            provider: cloudflare
            delayBeforeCheck: 30

    The environment variable

    CF_DNS_API_TOKEN
    needs to be present in Traefik's process environment for the Cloudflare provider. The
    delayBeforeCheck
    setting (in seconds) tells Traefik to wait before signaling Let's Encrypt to validate — this accounts for DNS propagation time after the TXT record is created. I set this to at least 30 seconds in production. Some providers are faster; some are slower. If you're seeing intermittent validation failures with valid credentials, raising this value is the first thing to try.

    For a Docker-based deployment on sw-infrarunbook-01, a practical compose configuration looks like this:

    services:
      traefik:
        image: traefik:v3.0
        container_name: traefik
        environment:
          - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
        volumes:
          - /etc/traefik:/etc/traefik:ro
          - /traefik/certs:/traefik/certs
        ports:
          - "80:80"
          - "443:443"

    DNS-01 has one capability that makes it irreplaceable for private infrastructure: it works when your server has no inbound internet access whatsoever. Let's Encrypt's validation servers only need to reach your public DNS — they never make HTTP or TLS connections to your origin server. If solvethenetwork.com resolves to 192.168.10.50 on sw-infrarunbook-01 (a private RFC 1918 address behind NAT), HTTP-01 and TLS-ALPN-01 will always fail because Let's Encrypt can't route to that address. DNS-01 doesn't care about your server's IP at all. The validation is entirely out-of-band from your server's network connectivity.

    This is what makes DNS-01 the right answer for homelabs, air-gapped environments, and services behind load balancers. You get valid Let's Encrypt certificates on services that are never directly internet-accessible.

    Wildcard Certificates with DNS-01

    Wildcard cert issuance is straightforward in Traefik once DNS-01 is working. You specify the domain structure explicitly in your dynamic configuration so Traefik knows to request a wildcard rather than deriving individual per-hostname certs from routing rules:

    http:
      routers:
        main-app:
          rule: "Host(`app.solvethenetwork.com`) || Host(`api.solvethenetwork.com`)"
          entryPoints:
            - websecure
          service: main-app
          tls:
            certResolver: letsencrypt
            domains:
              - main: "solvethenetwork.com"
                sans:
                  - "*.solvethenetwork.com"

    When you provide an explicit

    domains
    block, Traefik requests the certificate structure you described rather than auto-deriving it from the routing rule hostnames. Without this block, Traefik issues individual certificates per hostname it observes in router rules. Both approaches are valid — explicit domain blocks give you predictable cert structure and make wildcard issuance possible.

    One thing to watch: a wildcard for

    *.solvethenetwork.com
    covers only one level of subdomain depth. It covers
    app.solvethenetwork.com
    but not
    v2.app.solvethenetwork.com
    . If you need multi-level coverage, you need additional explicit SANs. And the wildcard doesn't cover the apex domain
    solvethenetwork.com
    itself — that needs to be listed as an additional SAN if your routing rules include it.

    The Certificate Storage File

    Regardless of which challenge type you use, Traefik stores all ACME account state and issued certificates in a single JSON file — the

    storage
    path you specify in your resolver config. This file is critical and must survive container restarts. If you lose it, Traefik re-registers with Let's Encrypt and re-issues all certificates on next startup, which burns rate limit quota and causes a brief TLS disruption while new certificates are issued and populated.

    The file must have permissions

    600
    . Traefik checks this on startup and will refuse to use a file with permissions that are too open:

    chmod 600 /traefik/certs/acme.json

    In a multi-node high-availability setup, you cannot share this file directly between Traefik instances. Concurrent writes from multiple nodes will corrupt it. For HA deployments, configure Traefik to use a distributed certificate store — Redis is the most common choice. The configuration shifts from a local file path to a Redis connection URI, and Traefik uses distributed locking to prevent concurrent write collisions. This is a fundamentally different operational model from single-node deployments, and it's worth planning for if you're building anything that needs more than one Traefik instance.

    Staging vs Production and Rate Limits

    Let's Encrypt's production API enforces rate limits: 50 certificates per registered domain per week, with a separate limit of 5 failed validation attempts per hostname per hour. During initial setup or when debugging a new DNS-01 provider integration, always use the staging endpoint first:

    certificatesResolvers:
      letsencrypt-staging:
        acme:
          email: infrarunbook-admin@solvethenetwork.com
          storage: /traefik/certs/acme-staging.json
          caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
          httpChallenge:
            entryPoint: web

    Staging certificates aren't trusted by browsers, but the full issuance and validation flow is identical to production. You'll catch misconfigured DNS provider credentials, firewall blocks, and propagation timing issues without touching production rate limits. I always validate against staging first, especially on DNS-01 setups where both API credentials and the

    delayBeforeCheck
    value need tuning.

    Use a separate

    storage
    path for staging certs so that when you switch to production, Traefik starts fresh and issues real certificates without leftover staging state interfering.

    Why This Decision Matters in Production

    Choosing the wrong challenge type is one of the most common causes of silent cert issuance failures in Traefik deployments. The failure mode is subtle — Traefik continues serving traffic on existing certificates while quietly failing to renew, and you only notice when the cert expires and browsers start throwing warnings. By then, you're doing urgent incident response instead of routine maintenance.

    The decision logic I use comes down to three questions. First: is port 80 open and publicly accessible with a direct routable path to Traefik? If yes, HTTP-01 is the simplest and most reliable option — no API credentials, no extra configuration, and it just works. Second: is port 80 closed but port 443 is directly accessible without upstream TLS termination? TLS-ALPN-01 covers that case cleanly without adding DNS API complexity. Third: do you need wildcards, is your server on a private RFC 1918 address, or does a load balancer or CDN terminate TLS before traffic reaches Traefik? DNS-01 is the answer. It has higher setup cost upfront, but it covers all scenarios the other two can't touch.

    Common Misconceptions

    The first one I run into constantly: engineers assume that because their domain resolves correctly in DNS, the HTTP-01 challenge will pass. DNS resolution isn't the bottleneck — network accessibility is. Let's Encrypt's validation servers make outbound HTTP connections from their own public IP ranges. An ACL that allows traffic from your office IP does nothing. You need port 80 open to the broader internet. Traefik logs the failed challenge response if you look at debug level output, but because Traefik retries silently in the background, there's no prominent error surfaced to the operator.

    Another persistent misconception: DNS-01 requires handing Traefik root-level DNS provider credentials. That's not true with modern provider APIs. Cloudflare, for example, lets you create API tokens with

    Zone:DNS:Edit
    permission scoped to a single zone. That token can create and delete TXT records under
    _acme-challenge.solvethenetwork.com
    and nothing beyond that zone. You're not exposing your entire DNS account. This scoped access model makes DNS-01 operationally safer than its reputation suggests, and it's how I configure it for solvethenetwork.com in every environment where DNS-01 is the right call.

    People also overestimate the security value of wildcard certificates. A wildcard is genuinely useful when you're dynamically spinning up subdomains and don't want per-service cert management overhead. But it's not inherently more secure than individual service certificates. Per-hostname certificates issued via HTTP-01 or TLS-ALPN-01 with Traefik's automatic per-hostname renewal have a smaller blast radius — if one cert is somehow misused, it doesn't extend trust to every subdomain you operate under

    *.solvethenetwork.com
    . Don't reach for wildcards just because they feel more convenient. Match the certificate strategy to your actual operational and security requirements.

    Finally, the storage file path trips people up more than it should. The file path in your Traefik static config must be writable inside the container, and the corresponding directory must be mounted from the host as a persistent volume. I've seen configurations where the path looked correct in the config but no volume mount backed it — Traefik wrote the file to the container's ephemeral layer, and every container restart triggered a full re-registration and re-issuance. The Traefik logs show

    unable to load ACME certificate
    followed immediately by fresh issuance activity, which is the tell. If you're seeing that pattern on every restart, check your volume mounts before anything else.


    ACME challenge types aren't a configuration detail you can pick arbitrarily and revisit later without service disruption. They determine whether Traefik can provision and renew certificates without human intervention — which is the entire value proposition of integrating Let's Encrypt into your stack. Match the challenge type to your environment's actual network topology, lock down the storage file permissions, use staging during setup, and Traefik's certificate handling becomes genuinely set-and-forget. That's what automated TLS is supposed to feel like.

    Frequently Asked Questions

    Can I configure multiple ACME challenge types in Traefik at the same time?

    Yes. You define multiple named blocks under <code>certificatesResolvers</code>, each with a different challenge type, and reference them by resolver name from individual routers. For example, you can have one resolver using HTTP-01 for public-facing services and a separate resolver using DNS-01 for internal services on private IPs — both active simultaneously.

    Why does my DNS-01 challenge fail intermittently even though my API credentials are correct?

    DNS propagation time is almost always the cause. After Traefik creates the TXT record via your provider's API, there's a window before that record is globally visible. Raise the <code>delayBeforeCheck</code> value in your DNS challenge configuration — start at 30 seconds and increase if failures continue. Some DNS providers take longer than others to propagate changes to their authoritative servers.

    Does TLS-ALPN-01 work when Traefik is behind a Cloudflare proxy?

    No. When Cloudflare proxies your traffic, it terminates TLS on Cloudflare's edge before the connection reaches your origin server. The ALPN extension Traefik needs to respond to never arrives. For domains proxied through Cloudflare or any other CDN that terminates TLS upstream, DNS-01 is the only viable challenge type.

    How do I force Traefik to re-issue a specific certificate without deleting the entire storage file?

    Stop Traefik, open the acme.json storage file in a text editor, and remove the JSON entry for the specific domain you want to re-issue. The file is structured JSON — each certificate entry is keyed by the resolver name and domain. Save the file, restart Traefik, and it will re-issue only the certificate for that domain while leaving all others intact.

    Does Let's Encrypt rate limiting apply separately to staging and production?

    Yes. The staging environment has its own separate and much more generous rate limits, which is exactly why you should use it during development and debugging. Staging certificate issuances don't count against your production quota. The only downside is that staging certificates aren't trusted by browsers or operating systems, so you'll see TLS warnings — that's expected and acceptable during testing.

    Related Articles