DNS persist mode - acmesh-official/acme.sh GitHub Wiki

DNS persist mode lets you publish a single, long-lived TXT record once in your zone and then issue / renew certificates forever without further DNS edits โ€” including unattended cron renewals.

It implements draft-ietf-acme-dns-persist-01, an IETF draft that defines a persistent DNS authorization record at _validation-persist.<your-domain>.

Why use it

DNS validation has historically forced a tradeoff:

Mode Auto-renewal Needs API access
DNS API mode โœ… Yes โœ… Required
DNS manual mode โŒ No (manual every renewal) โŒ Not needed
DNS persist mode โœ… Yes โŒ Not needed

If your DNS provider does not offer an API, but you can edit your zone once, DNS persist is the right mode. Renewals are fully automatic afterwards.

Step 1: Print the TXT record value

acme.sh --make-dns-persist-value -d example.com

You'll get an output like:

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

The TXT value is human-readable text in the syntax of RFC 8659 ยง4.2:

issuer-domain-name; accounturi=<your-account-uri>[; policy=wildcard]

If the CA's directory advertises multiple caaIdentities (e.g. ZeroSSL lists sectigo.com, trust-provider.com, etc.), one TXT record per identity is printed โ€” you only need to add ANY ONE of them.

Optional flags for --make-dns-persist-value

Flag Description
--server <ca> Pick the CA. The account is registered automatically if you have not used this CA before. Default is your configured default CA.
--dns-persist-wildcard Adds policy=wildcard to the record so it also authorizes wildcard / subdomain certs.
--dns-persist-ca-name <name> Use a specific CA identity domain (e.g. ssl.com). If omitted, identities are read from the ACME directory's caaIdentities field.
--dns-persist-days <N> Adds a persistUntil field to the record so it self-expires N days from now. After that timestamp, the CA will refuse new validations against this record. Useful if you want a time-bounded authorization. Omit for a record with no expiry.

Examples:

# Let's Encrypt
acme.sh --make-dns-persist-value -d example.com --server letsencrypt

# Wildcard policy (also authorizes *.example.com)
acme.sh --make-dns-persist-value -d example.com --dns-persist-wildcard

# Force a specific issuer name
acme.sh --make-dns-persist-value -d example.com --dns-persist-ca-name "ssl.com"

# Self-expire the authorization after 365 days
acme.sh --make-dns-persist-value -d example.com --dns-persist-days 365

Step 2: Add the TXT record at your DNS provider

Use whatever interface your DNS provider gives you to add the TXT record. The name is _validation-persist.<your-domain> and the value is the quoted string from the previous step.

Wait for DNS propagation (usually a few minutes).

Step 3: Issue the certificate

acme.sh --issue -d example.com --dns-persist

The CA reads your persistent TXT record directly โ€” no challenge token is provisioned during issuance. This is the key difference vs. dns-01 / DNS API modes.

Renewal

Cron will renew automatically โ€” the same TXT record is reused forever. Combined with ARI, the CA also picks the renewal time for you, so the entire lifecycle is unattended.

# Manual renewal also works:
acme.sh --renew -d example.com

Trust model & security notes

The persistent TXT record contains your ACME account URI. This means:

  • Only the holder of the corresponding ACME account key (i.e. you, on this machine) can issue certs for your domain through this record.
  • Anyone reading your DNS sees your account URI. The account URI itself is not a secret โ€” it identifies the account, but you also need the matching private key to use it. No issue.
  • If you lose your ACME account key (for example, you reinstall and don't restore ~/.acme.sh/), the TXT record becomes useless. You'll need to print and re-publish a new one with the new account.
  • If you want to revoke this authorization, simply delete the TXT record.

Wildcard policy

By default the record only authorizes the exact FQDN. Add policy=wildcard (via --dns-persist-wildcard) to additionally authorize:

  • The base domain
  • *.<base domain> wildcards
  • Specific subdomains under it

Compatibility

DNS persist is an IETF draft. Check that your CA implements it before relying on it.

Related

โš ๏ธ **GitHub.com Fallback** โš ๏ธ