Open-Source Wikis

/

Traefik

/

Features

/

ACME provider

traefik/traefik

ACME provider

ACME (RFC 8555) is the protocol Let's Encrypt and other public CAs use to issue certificates. Traefik bundles an ACME client built on github.com/go-acme/lego/v4 and exposes it as a "certificate resolver" in static configuration.

Source

pkg/provider/acme/:

File Role
provider.go The 40k-byte heart: state machine, domain extraction, renewal, message emission.
account.go ACME account creation and persistence.
challenge_http.go HTTP-01 challenge handler exposed at the acme-http@internal route.
challenge_tls.go TLS-ALPN-01 challenge served via the TLS manager.
local_store.go JSON-on-disk persistence of account and certificates.
local_store_unix.go, local_store_windows.go Platform-specific file locking.
store.go The interface implemented by local_store.
provider_test.go Unit tests covering domain extraction and renewal logic.

The DNS-01 challenge support is delegated to Lego, which ships providers for dozens of DNS APIs.

Configuration

certificatesResolvers:
  letsencrypt:
    acme:
      email: ops@example.com
      caServer: https://acme-v02.api.letsencrypt.org/directory
      storage: /letsencrypt/acme.json
      keyType: EC256
      tlsChallenge: {}
      # or:
      httpChallenge:
        entryPoint: web
      # or:
      dnsChallenge:
        provider: route53
        delayBeforeCheck: 0
        resolvers: ['1.1.1.1:53']

A router opts in by setting tls.certResolver: letsencrypt. The provider observes which domains are needed by inspecting active routers.

Lifecycle

graph TD
    Static[static config] --> Provider[ACME Provider]
    Watcher[Configuration watcher] -->|active routers + domains| Provider
    Provider --> NeedsCert{certificate missing or expiring?}
    NeedsCert -->|yes| Lego[lego client]
    Lego -->|HTTP-01| HTTP[challenge_http.go]
    Lego -->|TLS-ALPN-01| TLS[challenge_tls.go]
    Lego -->|DNS-01| DNS[Lego DNS plugin]
    HTTP --> Cert[certificate]
    TLS --> Cert
    DNS --> Cert
    Cert --> Store[local_store.go]
    Cert --> Emit[dynamic.Message<br/>tls.Certificates]
    Emit --> Watcher
    Watcher --> TLSManager[pkg/tls/tlsmanager.go]

The provider is both a listener (it watches the configuration to know which domains it must serve) and a producer (it emits a dynamic.Configuration containing the resolved certificates).

Renewal

provider.go runs a periodic renewal job. A certificate is renewed when:

  • It is within 30 days of expiry by default (configurable).
  • The list of SANs has changed (i.e. a new domain became required and the cert needs to cover it).

Failed renewals are retried with exponential backoff. The previous certificate keeps serving until the renewal succeeds.

Storage

local_store.go writes one JSON file per resolver — typically /letsencrypt/acme.json. The file contains:

  • The ACME account (private key + registration URL).
  • The list of issued certificates (PEM-encoded private key and certificate, SANs, resolver name).

The file is read at startup and rewritten atomically (temp file + rename) on every change. Permissions are checked at startup; the file must be 0600 to avoid leaking the account key.

DNS-01

DNS-01 challenges are essential for wildcard certificates. Traefik supports them via Lego's plugin set: Route 53, Cloudflare, Gandi, GCP Cloud DNS, Azure DNS, DigitalOcean, Vultr, OVH, and many more — all selected by the resolver's dnsChallenge.provider value. Each plugin reads its credentials from environment variables documented in Lego's README.

DNS-01 has its own quirks:

  • delayBeforeCheck — wait this long before checking that the TXT record propagated.
  • resolvers — explicit DNS resolvers to use for propagation checks.
  • disablePropagationCheck — escape hatch for environments where the check fails for benign reasons.

HTTP-01 and the internal route

When the HTTP-01 challenge is enabled, the provider injects a router named acme-http@internal that intercepts /.well-known/acme-challenge/* on the configured entry point. The actual handler is in challenge_http.go. After a successful challenge, the router can be left in place — it returns 404 for non-challenge paths.

TLS-ALPN-01 and the TLS manager

The TLS-ALPN-01 challenge is served on port 443 via a special tls.Config returned by the TLS manager. challenge_tls.go registers a temporary certificate with the manager keyed by the challenge name; the manager hands it back during the handshake of the validating CA's connection.

Tests

  • pkg/provider/acme/provider_test.go — domain extraction, renewal-due logic, account handling.
  • pkg/provider/acme/local_store_test.go — persistence and locking.
  • integration/acme_test.go — end-to-end against a Pebble (Let's Encrypt staging) container.

Practical notes

  • Always start against caServer: https://acme-staging-v02.api.letsencrypt.org/directory to avoid hitting Let's Encrypt's rate limits during development.
  • Storage is a single JSON file. For production, persist it on a volume that survives container restarts. Multiple Traefik instances must share the same file or use a key-value store via a separate persistence layer.
  • HTTP-01 requires port 80 to be reachable from the CA. If you front Traefik with another load balancer, route /.well-known/acme-challenge/* to Traefik.
  • TLS-ALPN-01 requires port 443. It does not interfere with normal TLS termination.
  • For wildcard certificates, only DNS-01 is allowed by Let's Encrypt.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

ACME provider – Traefik wiki | Factory