Way 1 · Free ACME · Do it yourself
Free SSL certificates with ACME: setup and operations guide
Free SSL certificates cover issuance. You still need to keep renewal, installation and monitoring running. Choose a CA, restrict DNS access and test the whole process through to the service using the SSL certificate.
- Choose it when
- your servers and devices have built-in ACME that renews on its own and reports its own errors, or when you have a technician who can build and maintain scripts. The certificates are free, and you choose the CA, client and validation method for each server.
- No longer fits when
- each server ends up with its own solution, documentation and monitoring fall behind, and there is no central place that shows how everything is set up and running. The hours spent developing scripts, updating them and setting up new servers add up quickly as the environment grows.
How ACME works
ACME is the protocol between your client and a CA. The client requests the SSL certificate and proves control of its names. Installing it in the right service is a separate step.
RFC 8555: ACME describes the sequence: account creates the ACME account; order requests the names; authorization specifies what needs approval; challenge proves domain control; finalize submits a CSR; certificate lets the client retrieve the issued SSL certificate.
ARI (ACME Renewal Information, RFC 9773) lets the CA suggest a renewal window. The client still needs to run regularly and install the result. Read how the ACME protocol works from request to renewal.
Choose a free CA
Choose a CA that fits your validation method and operations. Create the required account, read the CA’s terms and allow it in your CAA records.
| CA | What should you know? |
|---|---|
| Google Trust Services (recommended) | A little more to set up the first time: a Google Cloud account, a project and an EAB key. In return, dns-persist-01 gives the most secure validation, because the servers do not need DNS API credentials. Setup · dns-persist-01 |
| Let's Encrypt (most popular) | Requires validation with http-01 or dns-01. If you can easily open port 80, it works well for most. With dns-01 the servers need DNS API credentials, preferably only for a separate validation zone (see Domain validation). Has rate limits on duplicates. Getting started · Adoption · Rate limits |
| ZeroSSL | Requires an account. ACME and EAB |
| Actalis (EU) | A good choice when the EU comes first. Only one FQDN per certificate, but free. ACME guide · Free plan · European CA |
The ACME client creates your Let’s Encrypt account. The table highlights http-01 and dns-01; Let’s Encrypt also supports tls-alpn-01.
Google Trust Services requires a Google Cloud account and a project with the Public CA API enabled. Create an EAB key (External Account Binding) to associate the ACME account with the project. The project’s ACME accounts share Public CA quotas. ZeroSSL also requires EAB credentials; its free ACME service is separate from its other API products.
A CAA record restricts which CAs may issue. Allow your chosen CA with issue and check issuewild for wildcards. Use the CAA rules and FairSSL CAA generator to create the right DNS record.
Rate limits for issuance
As certificate lifetimes get shorter, rate limits bite harder, because you issue more often. The limits matter most when you issue many new certificates at once, for example when a new environment comes on board, when you switch CA, or when you restore servers from backup. A certificate that moves from another CA counts as new at the new CA.
| CA | Limits on issuance and validation | Names per certificate | Source |
|---|---|---|---|
| Google Trust Services |
| Not stated | Google Cloud: quotas · Google: EAB and project Updated 28 October 2026. Last checked 7 November 2026. |
| Let's Encrypt |
| Up to 100 names (FQDN or IP) per certificate, depending on the certificate profile selected. | Let's Encrypt: rate limits Updated 5 August 2026. Last checked 7 November 2026. |
| ZeroSSL |
| Not stated | ZeroSSL: ACME Last checked 7 November 2026. |
| Actalis |
| 1 FQDN | Actalis: free plan · Actalis: ACME · Actalis: European CA Last checked 7 November 2026. |
If you plan many new certificates, spread them across several accounts or projects where the limit applies per account. Set up a second CA in advance and add it to your CAA records, so you can switch without waiting.
Domain validation
Choose a method supported by both your CA and client. Use DNS validation for wildcards and internal servers with public domain names. Restrict the client’s DNS permissions to validation.
http-01: The client places a response at http://<name>/.well-known/acme-challenge/<token>. The CA retrieves it over port 80. It cannot validate wildcards. An internal server can only use this method if a public HTTP system answers the challenge for the name.
dns-01: The client creates a TXT record at _acme-challenge.<name>. For *.example.com, use _acme-challenge.example.com. The CA reads public DNS; the service itself can remain internal. Let’s Encrypt explains HTTP and DNS validation.
tls-alpn-01: The CA connects to port 443 and requests acme-tls/1 using ALPN. A responder presents a special temporary SSL certificate as proof. Your TLS terminator must support the method. RFC 8737: tls-alpn-01.
| Method | Inbound port on the service | Wildcard | Internal server | What must you run? |
|---|---|---|---|---|
| http-01 | 80 | No | Only with a public HTTP responder | Client with webroot access or an HTTP responder |
| dns-01 | None; the CA queries public DNS | Yes | Yes, with a public DNS name | Client with a DNS plugin and restricted DNS API access |
| tls-alpn-01 | 443 | No | Only with a public TLS responder | Client/responder supporting acme-tls/1 at TLS termination |
| dns-persist-01 | None; the CA queries public DNS | Yes, with the CA’s policy | Yes, with a public DNS name | Compatible client, ACME account key and persistent TXT record |
The client publishes the proof. The CA checks it. Installation follows issuance.
Restrict DNS API access with a validation zone
The DNS plugin uses API credentials to create and remove TXT records. With a client on every server, every server receives DNS credentials. A leaked key can change anything its permissions allow. Avoid giving the client access to the entire domain zone.
Create a separate validation zone (challenge zone). Point a CNAME from _acme-challenge to a name in the validation zone and grant the client write access only there. The CA follows the CNAME to the TXT record. The client or DNS plugin must also support writing to the target; a CNAME does not automatically redirect its API calls. Each SAN name may need its own delegation.
The CNAME stays in the domain zone. The client writes challenge values only in the validation zone.
DNS example: CNAME and TXT in separate zones
The first record belongs in example.com. The second belongs in the validation zone acme.example.net. Replace the names and let the client set the current challenge value. The CNAME stays in place; the TXT value changes for new dns-01 validations.
_acme-challenge.example.com. 300 IN CNAME example-com.acme.example.net.
example-com.acme.example.net. 300 IN TXT "<challenge-value>" dns-persist-01 at Google
dns-persist-01 uses one persistent TXT record at _validation-persist that binds the domain to the CA and the ACME account, so the client no longer writes a new TXT value for each renewal. The IETF draft is at version -02, dated 20-09-2026. Google Trust Services supports it today and requires EAB. Let’s Encrypt does not yet, but it is planned. GlobalSign has it planned for 2027. ZeroSSL and Sectigo ACME do not support it. Follow Google’s dns-persist-01 format and client requirements.
The record is bound to one ACME account. If each server has its own ACME client and account, the domain needs one TXT record per server under _validation-persist. If the servers share one account, one record is enough, but then every server can issue for all the domains and revoke all the certificates. Never create a new account on a server that already uses dns-persist-01. Change the key instead, so the record still applies. Google: ACME accounts and dns-persist-01
At FairSSL, dns-persist works with the DigiCert certificates and requires your own DigiCert account; on the shared account AutoDNS validates instead. Read more in dns-persist-01 with DigiCert: one DNS record, and every name is approved in advance and dns-persist-01 in sslbrain: no DNS keys on your servers. For classic dns-01, follow our guide to DNS plugins and ACME DNS validation.
Configuration, clients and ARI
Choose renewal timing, key type and SAN names to suit the systems using the SSL certificate. Test against staging and create a scheduled job with installation after successful renewal.
Include only the SAN names the service needs. Choose RSA or ECDSA according to client and service support. Let a current ACME client follow ARI and check its renewal job. A fixed calendar date may not suit the next SSL certificate’s validity period.
SSL certificate lifetimes are falling. The timeline uses the same lifetimes as the rest of this site: at most 199 days now and 99 days by 15 March 2027 at the latest. DigiCert switches on 24 February 2027. Free CAs may issue shorter SSL certificates. Manual renewal is not an operational plan.
ARI provides a recommended renewal window, including when a CA wants early renewal. These clients document ARI support. Our guides explain client setup; adapt the CA address and EAB when using a free CA.
| Client | ARI source | Setup |
|---|---|---|
| simple-acme | ARI documentation: simple-acme | Setup guide for simple-acme |
| lego | ARI documentation: lego | Setup guide for lego |
| Certbot | ARI documentation: Certbot | Setup guide for Certbot |
| Caddy | ARI documentation: Caddy | Setup guide for Caddy |
win-acme or simple-acme?
simple-acme continues the work of the same developer and is described as a backwards-compatible replacement for win-acme. The project’s own explanation and installation guide using wacs.exe describe the transition. Use our simple-acme guide for SSL certificates on Windows.
Posh-ACME: what controls renewal timing?
The search “renewaldays posh-acme” mixes settings from different clients. RenewalDays is a win-acme/simple-acme setting, not a Submit-Renewal parameter. Posh-ACME uses the order’s RenewAfter. ARI can update it when supported by the CA. Posh-ACME checks RenewAfter before renewing.
Schedule Submit-Renewal regularly under the same user and configuration used during setup. A job does not start itself when RenewAfter is reached. -Force bypasses the timing check and should not be your normal renewal policy. See the Submit-Renewal documentation and Windows setup with scheduled ACME jobs.
Commands for Let’s Encrypt staging
Install the client first. Replace example.com, email addresses and paths with your own. The HTTP examples require an existing webroot reachable on port 80; use a test server. Staging issues SSL certificates without public trust. Keep them separate and do not bind them to production services.
simple-acme · PowerShell · http-01
Run from the installation folder. The existing webroot must serve challenge files. PEM files go in the test folder; --installation none leaves IIS bindings alone.
New-Item -ItemType Directory -Force C:\acme-staging
.\wacs.exe --source manual --host example.com --validation filesystem --webroot C:\inetpub\wwwroot --store pemfiles --pemfilespath C:\acme-staging --installation none --baseuri https://acme-staging-v02.api.letsencrypt.org/ --accepttos --emailaddress admin@example.com Certbot · shell · http-01
certonly obtains the SSL certificate without installing it. Test configuration, working files and logs are stored separately.
sudo certbot certonly --webroot -w /var/www/html -d example.com \
--server https://acme-staging-v02.api.letsencrypt.org/directory \
--config-dir /etc/letsencrypt-staging --work-dir /var/lib/letsencrypt-staging \
--logs-dir /var/log/letsencrypt-staging --agree-tos --email admin@example.com lego v4 · shell · http-01
This example uses the documented lego v4 flags and a separate folder. The client writes the challenge file to your existing webroot.
lego --server https://acme-staging-v02.api.letsencrypt.org/directory \
--path ./lego-staging --email admin@example.com --accept-tos \
--domains example.com --http --http.webroot /var/www/html run acme.sh · shell · http-01
Choose the CA explicitly. letsencrypt_test selects staging. Later, use --install-cert and a suitable --reloadcmd for production; the service should not read directly from the client’s internal storage.
acme.sh --register-account --server letsencrypt_test --config-home ./acme-staging --accountemail admin@example.com
acme.sh --issue --server letsencrypt_test --config-home ./acme-staging \
-d example.com --webroot /var/www/html Posh-ACME · PowerShell · dns-01
This example requires Cloudflare DNS and an API token with Zone:DNS:Edit for the relevant zone. Enter the token at the prompt. For other DNS providers, choose their plugin. Submit-Renewal may skip an order that is not yet due.
Set-PAServer LE_STAGE
$pArgs = @{ CFToken = (Read-Host 'Cloudflare API token' -AsSecureString) }
New-PACertificate example.com -AcceptTOS -Contact admin@example.com -Plugin Cloudflare -PluginArgs $pArgs
Get-PAOrder | Select-Object MainDomain, RenewAfter
Submit-Renewal Once staging works, create a separate production configuration at Let’s Encrypt. Use the CA’s production address in the client, or letsencrypt in acme.sh and LE_PROD in Posh-ACME. Test the scheduled job and installation script with the permissions they will have in production.
Install the SSL certificate
Install the SSL certificate, chain and private key where the service expects them. Reload its configuration or restart it as required, then check the SSL certificate it actually presents.
A successful ACME job does not prove that installation succeeded. Use the client’s installation function or a script after renewal. Adapt file formats, permissions and bindings using the guide for your server or appliance.
- NetScaler: SSL certificate setup with ACME. Follow the guide for the appliance configuration.
- FortiGate: ACME and SSL certificate installation. Check requirements for your firmware and service.
- F5 BIG-IP: installing and binding SSL certificates. An ACME client can handle issuance; also plan import and binding on F5.
Monitor SSL certificates
Keep an inventory of SSL certificates, names, servers and owners. Monitor both the renewal job and the SSL certificate the service actually presents. Send failures to someone who can act on them.
Let’s Encrypt stopped expiry emails on 4 June 2025. A job can renew correctly while a service still uses an old file or binding. Check expiry and names at every destination.
Check the SSL certificate served
Run from a network that can reach the service. Use the correct hostname for SNI. Review names, chain and validity in the response; this manual check does not replace continuous monitoring.
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null
openssl s_client -connect example.com:443 -servername example.com </dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName A free FairSSL account includes CT-log monitoring of your domains without an agent or installation. Enable expiry alerts for the discovered SSL certificates. CT logs show issuance, not what each server uses; a new SSL certificate for the same names can replace the old one in monitoring. Keep checking each service too.
Troubleshooting and a plan for failures
Agree who responds to failures and how you will fix DNS, permissions, clients and installations. Store logs where the people responsible can read them, even when the server is unavailable.
If one name in a SAN SSL certificate can no longer be validated, renewal of the whole SSL certificate can fail. Remove names you no longer use and check all names after domain changes. Have a plan to issue and install again from a working machine.
“domain validation failed (dns01)”
- Read the exact name and expected TXT value in the client log. Query every authoritative nameserver; your local resolver may return a cached answer.
- Check DNS propagation and TTL. Wait until the change is visible on authoritative servers and old cached answers expire before trying again.
- Follow the CNAME into the correct zone. Check that the DNS plugin writes to the target zone, not a private DNS zone or the wrong name.
- Remove stale TXT values. Keep values needed by other active validations; concurrent orders may need different values at the same name.
- Check CAA and issuewild for your CA. If you hit rate limits, respect the retry time in the error and troubleshoot in staging. Repeated attempts will not fix an incorrect DNS record.
Query CNAME, TXT and CAA using dig / nslookup
Substitute the actual authoritative nameservers returned by the NS queries for ns1.example.com and ns1.example.net, then repeat against each server. This example follows the validation zone above. Without a CNAME, query TXT directly at _acme-challenge.example.com.
dig +short NS example.com
dig @ns1.example.com _acme-challenge.example.com CNAME +noall +answer
dig +short NS acme.example.net
dig @ns1.example.net example-com.acme.example.net TXT +noall +answer
nslookup -type=TXT example-com.acme.example.net ns1.example.net
dig @ns1.example.com example.com CAA +noall +answer When http-01 fails
Check port 80 in your firewall and NAT, and that A/AAAA point to the right server. Check the webroot matches the affected hostname. Request the challenge URL externally with the current token while validation is pending. Redirects must not lead the CA to a login page, wrong path or unreachable host. Let’s Encrypt documents the permitted redirects.
Inspect HTTP responses and redirects
Replace TOKEN with the filename from the client log. The first command shows the initial response; the second follows redirects. The content must be the expected challenge response, not an HTML error page.
curl -v --max-time 15 http://example.com/.well-known/acme-challenge/TOKEN
curl -vL --max-redirs 10 --max-time 30 http://example.com/.well-known/acme-challenge/TOKEN Document every server configuration
Record the client and version, CA and ACME account, validation method, DNS zone, renewal job, file paths and installation commands. Note where the private key lives and who has access.
Keep a protected backup of the ACME account key and required configuration. The account key is not the SSL certificate’s private key. Record ownership, alerts and the recovery procedure. The people responsible must be able to find the documentation and restore the setup.
Questions about free SSL certificates and ACME
Can I get free SSL certificates with ACME?
Yes. Let’s Encrypt, Google Trust Services, ZeroSSL and Actalis offer free ACME issuance with different requirements. You still need to handle renewal, installation and monitoring.
Can ACME work with an internal server?
Yes, using a public domain name and public DNS validation. dns-01 needs no inbound port on the service. http-01 and tls-alpn-01 require a publicly reachable responder.
What is the difference between win-acme and simple-acme?
simple-acme continues the work of the same developer. The project describes it as a backwards-compatible replacement for win-acme. Read its installation documentation and our Windows guide before migrating.
Does RenewalDays control Posh-ACME renewal?
No. Posh-ACME checks the order’s RenewAfter when Submit-Renewal runs. ARI can update that time. You must schedule the job yourself; -Force bypasses the timing check. RenewalDays is a win-acme/simple-acme setting.
Why does dns-01 validation fail?
Check the TXT value on authoritative nameservers, DNS propagation and TTL, the CNAME target, the plugin’s zone and stale TXT records. Also check CAA and the CA’s rate limits. Use the client log to identify the failing name.
Is CT-log monitoring enough to find an expired SSL certificate?
No. CT logs show issuance. They do not show which SSL certificate a service actually uses. Monitor both the renewal job and the SSL certificate at each destination.
Sources and official documentation
- RFC 8555: ACME
- RFC 9773: ACME Renewal Information
- RFC 8737: tls-alpn-01
- Let's Encrypt: getting started
- Let's Encrypt: adoption
- Let's Encrypt: challenge types
- Let's Encrypt: rate limits
- Let's Encrypt: staging
- Let's Encrypt: expiry emails ended
- Let's Encrypt: CAA / issuewild
- Google Trust Services: Public CA / EAB
- Google Trust Services: quotas
- Google Trust Services: ACME accounts and dns-persist-01
- Google Trust Services: dns-persist-01
- ZeroSSL: ACME / EAB
- Actalis: ACME
- Actalis: Free Plan
- Actalis: European CA
- simple-acme: win-acme
- simple-acme: wacs.exe
- simple-acme: CLI
- simple-acme: ARI / RenewalDays
- Certbot: user guide
- Certbot: ARI changelog
- lego v4: CLI flags
- lego v4: CLI examples
- lego: ARI changelog
- Caddy: ARI
- acme.sh: webroot / installation
- acme.sh: CA / staging
- Posh-ACME: tutorial
- Posh-ACME: Set-PAServer
- Posh-ACME: Cloudflare DNS plugin
- Posh-ACME: Submit-Renewal
- Posh-ACME: RenewAfter / ARI
- ISC BIND: dig
- Microsoft: nslookup
- curl: command line
- OpenSSL: s_client
- OpenSSL: x509 / SAN / expiry
Last updated: