Back to Blog

DNS-Persist-01 Is Almost Here. Here's What It Actually Changes.

The new ACME challenge type that replaces per-renewal DNS credential rotation with a single standing record. It's close to production at Let's Encrypt, and there's a security delay worth understanding.

CertGuard TeamSSL Security Experts8 min read
A close-up of a high-density network switch with rows of SFP+ ports, teal fiber optic cables plugged in, and amber status lights glowing in the port bays

The problem: your DNS credentials are in places they shouldn't be

Your DNS provider API key is basically everywhere in a standard ACME automation setup.

Your certbot cron job has it. Your CI/CD pipeline has it. Your Kubernetes secret store has it, sometimes in three namespaces. Your Terraform state file might have it. If you're using cert-manager with a DNS-01 solver, there's a Secret object with those credentials sitting right there in the cluster, readable by anything that can reach the Kubernetes API in that namespace.

That's the structural consequence of how DNS-01 works. The challenge demands a fresh TXT record on every issuance. Your automation needs write access to DNS at issuance time, every time. Credentials travel with the renewal job wherever it runs.

For a single domain on a standard setup, annoying but manageable. For a platform issuing certificates on behalf of tenants, or a fleet of isolated environments that each need their own certificate, the credential surface grows with every issuance. And it's a rotation problem too: changing your DNS API key means tracking down every place you distributed it. People don't do that often enough, because it's painful.

dns-persist-01 is Let's Encrypt's answer to this.

How DNS-01 works, briefly

If you've already read DNS vs HTTP Domain Validation: What Actually Happens Behind the Scenes, skip ahead. If not: DNS-01 proves domain ownership by having you publish a TXT record at _acme-challenge.yourdomain.com. The CA queries for that record, confirms it matches the challenge value it issued, and grants authorization.

The key detail is that the value changes every issuance. Your ACME client requests a new nonce, publishes it as a TXT record, waits for propagation, gets validated. Then the record sits there doing nothing until the next renewal, and the whole thing repeats. Write credentials have to be present at every single renewal.

What dns-persist-01 changes

The new challenge type drops the per-renewal cycle entirely. You write one record, once. That record says: Let's Encrypt account https://acme-v02.api.letsencrypt.org/acme/acct/1234567890 is authorized to issue certificates for this domain, until I say otherwise.

Every subsequent issuance checks the standing record. Still there, still matches your account: validation passes. No token exchange. No propagation wait. No credential in the renewal pipeline.

The authorization is tied to your account, not to a specific request. An attacker who gets into your certificate automation pipeline can't issue certificates for your domain under a different CA or a different account. They'd need your ACME account key or your DNS provider credentials. With dns-persist-01, the DNS credentials don't need to be in the renewal path at all after the initial setup.

The record format

The authorization record goes at _validation-persist.yourdomain.com as a TXT record:

_validation-persist.example.com. IN TXT "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890"

Two required fields: the CA's domain name and your account URI. The account URI is issued when you register with Let's Encrypt. Certbot prints it, cert-manager stores it in the account Secret, lego exposes it too.

You can retrieve your account URI from certbot like this:

sudo certbot show_account

By default this authorizes certificates only for the exact domain example.com. No wildcard. No subdomains.

Wildcards and expiry

Add policy=wildcard to cover *.example.com and matching subdomains:

_validation-persist.example.com. IN TXT "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890; policy=wildcard"

To add an automatic expiry, use persistUntil with a Unix timestamp:

_validation-persist.example.com. IN TXT "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890; persistUntil=1767225600"

After that timestamp the CA rejects new validations against that record. Certificates already issued don't get revoked automatically. You'd handle that separately.

You can publish multiple TXT records at the same label to authorize different CAs simultaneously. Each CA only validates records that match its own issuer domain name, so there's no conflict between them.

The security problem holding up production

DNS-persist-01's CA/Browser Forum ballot (SC-088v3) passed unanimously in October 2025. Let's Encrypt announced staging for late Q1 2026 and production for Q2 2026. That timeline slipped. The reason is a real security issue identified by the IETF ACME working group in early 2026.

Here's the attack. An attacker sets up a malicious ACME server, call it letsencyrpt.org, one transposed character. They trick a victim into configuring it as their CA endpoint. When the victim registers, the malicious server returns the attacker's real Let's Encrypt account URI in the challenge response. The victim, thinking they're authorizing their own account, publishes a dns-persist-01 record containing the attacker's account URI instead. The attacker then uses their legitimate Let's Encrypt account to obtain a certificate for the victim's domain.

This works with dns-persist-01 because the standing record contains only an account URI, and the attacker supplied that URI. With dns-01 or http-01, the validation token is generated server-side and tied to the specific order. It can't be reused across accounts. dns-persist-01 has no equivalent binding in its current draft form.

The proposed fix ties the DNS record to the account's public key rather than just its URI. The client includes a hash of the public key in the record; the CA verifies that the account presenting the key matches what's in DNS. That kills the proxy attack. The attacker's CA account has a different public key, so the record doesn't authorize it.

The cost: you'd need to update your DNS record whenever you rotate your ACME account key. Account key rotation is rare in practice, far less frequent than certificate renewal, so this is a modest trade-off. But it does reintroduce a small DNS dependency, once per key rotation instead of once per renewal.

As of mid-2026, Let's Encrypt treats this as a hard production blocker. The IETF draft hasn't been updated yet to reflect the public-key binding fix.

What's actually usable right now

Pebble, Let's Encrypt's lightweight test CA, already supports dns-persist-01 for dev and CI testing. The lego ACME client has native support. If you're building a platform that issues certificates and want to evaluate the workflow, Pebble plus lego is a working stack today:

# spin up Pebble in Docker for local testing
docker run -p 14000:14000 -p 15000:15000 letsencrypt/pebble

# lego supports dns-persist-01 natively -- point it at Pebble
LEGO_CA_CERTIFICATES=/path/to/pebble.crt \
  lego --server https://localhost:14000/dir \
       --email test@example.com \
       --dns yourprovider \
       --domains example.com \
       run

cert-manager has an open GitHub issue (no active pull request as of late July 2026). win-acme has a similar tracking issue. Certbot has nothing yet. If you rely on any of these: watch the issues, don't block production plans on it.

The specification lives at draft-ietf-acme-dns-persist, adopted as an IETF ACME working-group item in late 2025. The CA/Browser Forum ballot is SC-088v3. Both are public documents.

When dns-persist-01 is worth switching to

Once production deployment lands, the clearest wins are in platform certificate issuance. dns-persist-01 lets you ask customers or tenants to set one DNS record once instead of integrating with their DNS provider API for every renewal cycle. Air-gapped and IoT environments benefit for a similar reason: set the record during provisioning, and write credentials don't need to exist anywhere in the environment after that. Multi-region setups get a quieter advantage too. No propagation wait at renewal time means renewals complete faster and more predictably, which matters when you're running a tight window between ACME Renewal Information alerts and expiry.

Where it probably doesn't fit: single-server setups where your DNS API key already lives in one well-controlled place, or setups where per-issuance validation is a deliberate audit control. The standing authorization model trades that auditability for operational simplicity. That's a reasonable trade for platforms but maybe not for tightly controlled environments.

The right time to prepare is now. Find your ACME account URI, decide which domains you'd cover, figure out whether policy=wildcard fits your setup. When production lands the configuration change will be small if you've already done that thinking.

The Let's Encrypt announcement from February 2026, A New Model for DNS-Based Challenge Validation, is the canonical primary source and worth reading in full. The HN discussion from the same week surfaced most of the operational questions practitioners had, including the account-correlation privacy concern and the DNSSEC debate.

Frequently asked questions

Does dns-persist-01 replace dns-01, or can I use both? Both challenge types coexist. Let's Encrypt will continue to support dns-01 regardless of whether dns-persist-01 ships. The new challenge is additive. Your existing automation doesn't need to change unless you choose to migrate.

If I use dns-persist-01, can any CA use my record to issue certificates? No. The record includes the CA's own domain name (letsencrypt.org in the example), and each CA only validates records matching its own issuer domain. Sectigo, DigiCert, ZeroSSL: none of them can use a record that authorizes Let's Encrypt.

What happens to certificates already issued if I delete the dns-persist-01 record? They stay valid until expiry. Deleting the record blocks future issuance under that authorization. It doesn't touch certificates already in hand.

Is DNSSEC required for dns-persist-01? No, but the IETF draft recommends it. The CA/Browser Forum's multi-perspective validation, checking from multiple geographic vantage points, is the primary mitigation for DNS interception, and that applies to dns-persist-01 the same way it applies to dns-01.

When will certbot and cert-manager support this? No public commitment from either project as of August 2026. The feature is blocked upstream at Let's Encrypt, so client support is unlikely before production deployment is confirmed. The open issues in both trackers are the right places to watch.

Related posts

Never miss an expiring certificate again

CertGuard watches your SSL certificates and domains, and alerts you long before anything expires. Free for your first five domains.

Start Free