Skip to content

Commit 7735cdf

Browse files
authored
Merge pull request #6937 from acmesh-official/dev
sync
2 parents 76d1377 + d35876e commit 7735cdf

5 files changed

Lines changed: 959 additions & 37 deletions

File tree

README.md

Lines changed: 90 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
| 🌐 DNS mode | Use DNS TXT records |
147147
| 🔗 [DNS alias mode](https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode) | Use DNS alias for verification |
148148
| 📡 [Stateless mode](https://github.com/acmesh-official/acme.sh/wiki/Stateless-Mode) | Stateless verification |
149+
| 📌 DNS persist mode | Persistent DNS TXT record ([draft-ietf-acme-dns-persist-01](https://datatracker.ietf.org/doc/draft-ietf-acme-dns-persist/)) |
149150

150151
---
151152

@@ -396,7 +397,51 @@ acme.sh --renew -d example.com
396397
397398
---
398399

399-
### 🔟 Issue Certificates of Different Key Types (ECC or RSA)
400+
### 🔟 Use DNS Persist Mode
401+
402+
📚 Spec: [draft-ietf-acme-dns-persist-01](https://datatracker.ietf.org/doc/draft-ietf-acme-dns-persist/)
403+
404+
DNS persist mode lets you place a **single, long‑lived `_validation-persist` TXT record** in your zone and reuse it for every subsequent issuance and renewal. There is no per-issuance challenge token, so renewals require **no DNS edits** — useful when DNS API access is not available but you still want unattended renewals.
405+
406+
#### 🪄 Step 1: Print the TXT record value
407+
408+
```bash
409+
acme.sh --make-dns-persist-value -d example.com [--server letsencrypt] [--dns-persist-wildcard] [--dns-persist-ca-name "sectigo.com"] [--dns-persist-days 365]
410+
```
411+
412+
Options:
413+
414+
| Flag | Description |
415+
|------|-------------|
416+
| `--server <ca>` | Pick the CA (default is your configured default). The account is registered automatically if you have not used this CA before. |
417+
| `--dns-persist-wildcard` | Adds `policy=wildcard` to the record so it also authorizes wildcard / subdomain certs. |
418+
| `--dns-persist-ca-name <name>` | Use a specific CA identity domain (e.g. `sectigo.com`). If omitted, identities are read from the ACME directory's `caaIdentities` field and one record per identity is printed — you only need to add **any one** of them. |
419+
| `--dns-persist-days <N>` | Adds `persistUntil=<unix-timestamp>` to the record, set to N days from now. The CA will refuse new validations against the record after that time. Omit for a record with no expiry. |
420+
421+
You should get an output like:
422+
423+
```sh
424+
TXT persist domain:_validation-persist.example.com
425+
TXT persist value :"letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/123456789"
426+
```
427+
428+
#### ✍️ Step 2: Add the TXT record to your DNS
429+
430+
Add the printed `TXT persist domain` / `TXT persist value` pair as a TXT record at your DNS provider, then wait for it to propagate.
431+
432+
#### 📜 Step 3: Issue the certificate
433+
434+
```bash
435+
acme.sh --issue -d example.com --dns-persist
436+
```
437+
438+
**Done!** No challenge token is provisioned during issuance — the CA reads the persistent TXT record directly.
439+
440+
> 🔄 Renewals just work: `acme.sh --renew -d example.com` (or the cron job) reuses the same TXT record automatically — no further DNS edits needed.
441+
442+
---
443+
444+
### 1️⃣1️⃣ Issue Certificates of Different Key Types (ECC or RSA)
400445

401446
Just set the `keylength` to a valid, supported value.
402447

@@ -427,7 +472,7 @@ acme.sh --issue -w /home/wwwroot/example.com -d example.com -d www.example.com -
427472

428473
---
429474

430-
### 1️⃣1️⃣ Issue Wildcard Certificates
475+
### 1️⃣2️⃣ Issue Wildcard Certificates
431476

432477
It's simple! Just give a wildcard domain as the `-d` parameter:
433478

@@ -439,9 +484,9 @@ acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf
439484

440485
---
441486

442-
### 1️⃣2️⃣ How to Renew Certificates
487+
### 1️⃣3️⃣ How to Renew Certificates
443488

444-
> 🔄 No need to renew manually! All certs will be renewed automatically every **30** days.
489+
> 🔄 No need to renew manually! All certs will be renewed automatically every **30** days, **or earlier when the CA's ARI says so** (see below).
445490
446491
However, you can force a renewal:
447492

@@ -455,9 +500,41 @@ acme.sh --renew -d example.com --force
455500
acme.sh --renew -d example.com --force --ecc
456501
```
457502

503+
#### 📡 ACME Renewal Information (ARI) — RFC 9773
504+
505+
If the CA exposes a `renewalInfo` endpoint in its ACME directory (Let's Encrypt, ZeroSSL, etc.), `acme.sh` follows [RFC 9773](https://www.rfc-editor.org/rfc/rfc9773.html) automatically — **no flag needed, no opt-in**:
506+
507+
| What | When | Why |
508+
|------|------|-----|
509+
| 🔍 **Polls `suggestedWindow`** | Every cron run, before deciding to skip | Lets the CA shift the renewal time forward in case of an incident (key compromise, mass revocation, etc.) |
510+
| 🎯 **Picks a random renewal time** inside the window | Right after a successful issuance/renewal | Disperses renewals across the network so all clients don't hit the CA at the same instant |
511+
| 🔗 **Sends `replaces=<certID>`** in `newOrder` | On renewal | Lets the CA correlate the new order with the certificate it supersedes (RFC 9773 §5) |
512+
| ↩️ **Retries without `replaces`** | If the CA rejects with `alreadyReplaced` or an ARI validation error | Robust against edge cases (e.g. switching CAs, retired issuers) |
513+
514+
**Renewal trigger logic:** the cert is renewed if **any one** of the following becomes true:
515+
516+
1. `--force` is given
517+
2. The CA's **ARI `suggestedWindow` has started**
518+
3. The cached `Le_NextRenewTime` has passed (default fallback for CAs without ARI)
519+
520+
You can see the resulting next renewal time (already ARI-picked when applicable) in:
521+
522+
```sh
523+
acme.sh --info -d example.com
524+
# Look for: Le_NextRenewTimeStr=...
525+
```
526+
527+
For the live ARI window the CA is currently advertising, run with `--debug 2`:
528+
529+
```sh
530+
acme.sh --renew -d example.com --debug 2 2>&1 | grep -i 'ARI suggestedWindow'
531+
```
532+
533+
> 💡 If your CA does not advertise `renewalInfo`, `acme.sh` falls back to the classic 30-day rule — no behavior change.
534+
458535
---
459536

460-
### 1️⃣3️⃣ How to Stop Certificate Renewal
537+
### 1️⃣4️⃣ How to Stop Certificate Renewal
461538

462539
To stop renewal of a cert, you can execute the following to remove the cert from the renewal list:
463540

@@ -471,7 +548,7 @@ The cert/key file is not removed from the disk.
471548
472549
---
473550

474-
### 1️⃣4️⃣ How to Upgrade acme.sh
551+
### 1️⃣5️⃣ How to Upgrade acme.sh
475552

476553
> 🚀 acme.sh is in constant development — it's strongly recommended to use the latest code.
477554
@@ -495,25 +572,25 @@ acme.sh --upgrade --auto-upgrade 0
495572

496573
---
497574

498-
### 1️⃣5️⃣ Issue a Certificate from an Existing CSR
575+
### 1️⃣6️⃣ Issue a Certificate from an Existing CSR
499576

500577
📚 https://github.com/acmesh-official/acme.sh/wiki/Issue-a-cert-from-existing-CSR
501578

502579
---
503580

504-
### 1️⃣6️⃣ Send Notifications in Cronjob
581+
### 1️⃣7️⃣ Send Notifications in Cronjob
505582

506583
📚 https://github.com/acmesh-official/acme.sh/wiki/notify
507584

508585
---
509586

510-
### 1️⃣7️⃣ Under the Hood
587+
### 1️⃣8️⃣ Under the Hood
511588

512589
> 🔧 Speak ACME language using shell, directly to "Let's Encrypt".
513590
514591
---
515592

516-
### 1️⃣8️⃣ Acknowledgments
593+
### 1️⃣9️⃣ Acknowledgments
517594

518595
| Project | Link |
519596
|---------|------|
@@ -555,7 +632,7 @@ Support this project with your organization. Your logo will show up here with a
555632

556633
---
557634

558-
### 1️⃣9️⃣ License & Others
635+
### 2️⃣0️⃣ License & Others
559636

560637
📄 **License:** GPLv3
561638

@@ -565,7 +642,7 @@ Support this project with your organization. Your logo will show up here with a
565642

566643
---
567644

568-
### 2️⃣0️⃣ Donate
645+
### 2️⃣1️⃣ Donate
569646

570647
> 💝 Your donation makes **acme.sh** better!
571648
@@ -577,7 +654,7 @@ Support this project with your organization. Your logo will show up here with a
577654

578655
---
579656

580-
### 2️⃣1️⃣ About This Repository
657+
### 2️⃣2️⃣ About This Repository
581658

582659
> [!NOTE]
583660
> This repository is officially maintained by <strong>ZeroSSL</strong> as part of our commitment to providing secure and reliable SSL/TLS solutions. We welcome contributions and feedback from the community!

0 commit comments

Comments
 (0)