# Let's Encrypt with InfraNest DNS Get certificates for any domain whose DNS is in InfraNest, including wildcards, without opening a port. Your ACME client asks InfraNest to add one TXT record, waits for it to be checked, then removes it. **Runnable code:** the code on this page, ready to clone and run, is in [`infranest-examples/examples/acme-dns-01`](https://github.com/InfraNest-Infrastructure-Organized/infranest-examples/tree/main/examples/acme-dns-01). CI runs it against the [sandbox](../sandbox.md). ## The token Make a token with **DNS → Write** only. It can change records and nothing else: it can't delete the zone, move it, or touch your servers. ## Add the challenge record Find the zone's ID with `GET /organizations/{organization}/dns-zones`, then: ```sh curl -X POST https://api.infranest.io/api/organizations/42/dns-zones/318/dns-records \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: acme-$CERTBOT_DOMAIN-$CERTBOT_VALIDATION" \ -d '{"type":"TXT","name":"_acme-challenge","value":"'"$CERTBOT_VALIDATION"'","ttl":60}' ``` Keep the `id` from the response. You need it to remove the record. The `Idempotency-Key` means a hook that retries after a timeout adds the record once, not twice. See [Retries and dry runs](../retries-and-dry-runs.md). ## Remove it afterwards ```sh curl -X DELETE https://api.infranest.io/api/organizations/42/dns-zones/318/dns-records/9021 \ -H "Authorization: Bearer $INFRANEST_TOKEN" ``` Every change appears in the zone's history in InfraNest and can be undone from there. ## Coming - **Ready-made providers** for lego and acme.sh, so you won't need a hook script at all.