acme
Let's Encrypt / ACME protocol - automatic TLS certificate issuance and renewal.
Load with: use acme
What this module does
acme implements the ACME protocol (RFC 8555) used by Let's Encrypt to issue free TLS certificates.
It covers the full lifecycle: creating a client, registering an account, placing a certificate order,
responding to HTTP-01 or DNS-01 challenges, finalising the order, downloading the certificate,
checking renewal windows, and revoking certificates.
Two overloads of acmel() exist - one returns the production Let's Encrypt URL, the other
the staging URL. Use staging while testing so you don't hit rate limits.
Quick example
use acme
# Create a client pointed at Let's Encrypt production
client = acmec(acmel(), "admin@example.com")
# Register an account (agrees to ToS)
client = acmer(client, tru)
# Place an order for a domain
order = acbme(client, ["example.com"])
# Get the authorisation challenges
authz = acmea(order, order.authorizations[0])
challenges = acmec(authz)
# For HTTP-01: write the challenge file
acmht("example.com", challenges[0].token, challenges[0].keyAuthorization)
# Tell Let's Encrypt to validate
acmeh(client, challenges[0].url, challenges[0].token, challenges[0].keyAuthorization)
# Finalise and download the certificate
acbme(order, my_csr)
cert = acmed(order)
Functions
Client setup
acmec(directory_url, contact_email)
Creates a new ACME client object. Pass the directory URL (use acmel() to get it) and your contact email. Returns an object with directory, contact, account, and nonce fields.
acmel()
Two overloads: returns the Let's Encrypt production directory URL, or the staging directory URL. Use staging for testing.
acmed(client)
Fetches the ACME directory from the server. Returns the directory object (contains URLs for newAccount, newOrder, etc.), or nil on failure.
Account management
acmer(client, tos_agreed)
Registers a new ACME account. Generates a 2048-bit RSA key, builds a JWK, and POSTs to the newAccount endpoint. Pass tru for tos_agreed to accept Let's Encrypt's terms of service. Returns the updated client with the account set.
acmej(pubkey)
Converts an RSA public key to JWK format via __acme_jwk_from_rsa.
acmes(payload, jwk, account_key, url, nonce)
Signs a payload using JWS (RS256). Returns an object with protected, payload, and signature fields, all base64-encoded. Used internally for all signed ACME requests.
acmeb(client, kid, hmac_key)
Binds an external account (EAB) to the client - used with CAs that require pre-registration. Calls __acme_eab_bind.
Order and authorisation
acbme(client, domains)
Places a new certificate order for a list of domain names. Returns the order object (with authorizations, finalize URL, etc.), or nil on failure. Note: acbme is overloaded - see also Certificate finalisation below.
acmea(order, authz_url)
Fetches the authorisation object for a given authorisation URL. Returns the authorisation (contains challenge list), or nil on failure.
acmec(authz)
Extracts the challenges list from an authorisation object. Note: acmec is overloaded - see also Client setup above.
Challenge response
acmht(domain, token, keyauth)
HTTP-01 challenge: writes the key authorisation string to .well-known/acme-challenge/{token} and returns the path.
acmeh(client, challenge_url, token, keyauth)
Notifies the ACME server that the challenge is ready for validation. POSTs an empty signed payload to the challenge URL.
acmdn(domain, keyauth_digest)
DNS-01 challenge: returns an object with the TXT record name (_acme-challenge.{domain}) and the base64-encoded value to set.
Certificate finalisation and download
acbme(order, csr)
Finalises the order by submitting a CSR (base64-encoded) to the finalize URL. Returns the updated order, or nil on failure.
acmed(order)
Downloads the issued certificate from the order's certificate URL. Returns the certificate PEM string, or nil on failure.
Renewal and revocation
accer(cert, days_before_expiry)
Returns tru if the certificate expires within days_before_expiry days. Parses the cert with cert.certp and checks the not_after field against the current time.
acmrn(domains, days_before_expiry)
Checks each domain in the list against the cert at /etc/letsencrypt/live/{domain}/cert.pem. Returns a list of domains that either have no cert or need renewal.
acbev(client, cert, reason)
Revokes a certificate. reason is an integer reason code (e.g. 0 = unspecified, 1 = keyCompromise). POSTs to the revokeCert URL.
Rate limits
acmlm()
Returns an object with Let's Encrypt's current rate limit values: 300 orders/account, 50 certificates/domain, 5 duplicate certificate limit, 5 failed validations limit, etc.
Notes
acmecandacbmeandacmedare each overloaded with different signatures - which one runs depends on what arguments you pass.- Use the staging URL while developing:
acmec(acmel(), "you@example.com")- the second overload ofacmel()returns the staging URL. - Requires
net,cryx,enc,jsn,cert,tim, andfsto be available.