Recommended Free Tools
The reliable Ansible workflow is a two-pass ACME transaction: request challenge data with community.crypto.acme_certificate, publish the HTTP-01 or DNS-01 challenge, then call the module again with the registered data to download the certificate. Use HTTP-01 when the domain reaches the Ubuntu host on port 80; use DNS-01 when port 80 cannot be exposed or when you need a wildcard name.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
Let’s Encrypt certificates last 90 days. Automation is therefore part of the installation, not an optional follow-up: store the account and certificate keys safely, make issuance idempotent, deploy fullchain.pem and privkey.pem, and reload the service only when the files change.
As an Amazon Associate I earn from qualifying purchases.
What Ansible is automating
Let’s Encrypt is operated by the Internet Security Research Group and issues certificates through the Automated Certificate Management Environment (ACME) protocol. The certificates are valid for 90 days and can be renewed automatically. Ansible does not bypass ACME validation; it coordinates the same validation that a manual client performs and makes the result repeatable across hosts.
The community.crypto.acme_certificate module is part of the community.crypto collection, not ansible-core. Install the collection before running a playbook:
#1 Best Overall
ansible-galaxy collection install community.crypto
The module deliberately runs twice. The first invocation creates an ACME order and returns the challenge information. Your playbook must then prove control of every requested name. The second invocation receives the first result through data and retrieves the issued certificate, chain, and full chain.
Choose the validation method before writing tasks
| Decision | HTTP-01 | DNS-01 |
|---|---|---|
| Network requirement | The hostname must resolve to the Ubuntu server and inbound TCP port 80 must reach a web server or a temporary standalone listener. | No inbound HTTP is required; the ACME TXT record is created in DNS. |
| Wildcard certificates | Not supported for wildcard names. | Required for names such as *.example.com. |
| Challenge publication | Serve the returned value at /.well-known/acme-challenge/<resource>. |
Publish each returned value as a TXT record at the returned _acme-challenge name. |
| Operational complexity | Usually simplest when you control the webroot and port 80. | Requires DNS-provider automation or an API workflow and time for DNS propagation. |
Use HTTP-01 for an ordinary web certificate
HTTP-01 is the straightforward option for example.com and names such as www.example.com when both DNS and port 80 are under your control. The web server must serve the challenge directory without redirecting it to an application that hides the file. A redirect to HTTPS can work in some configurations, but allowing the validation path over port 80 is less fragile.
Use DNS-01 for wildcards or closed HTTP networks
DNS-01 is the only way to obtain wildcard certificates from Let’s Encrypt. It is also the better fit for internal load balancers, hosts behind a firewall, or services for which exposing port 80 is unacceptable. The playbook must have permission to create and remove TXT records in the authoritative DNS zone, and it must wait until the records are visible to the public resolvers used during validation.
Prerequisites on Ubuntu
- A registered domain whose required names resolve to the intended service or whose DNS zone can be updated automatically.
- An Ubuntu host reachable by Ansible with privilege escalation available for writing under
/etc/letsencryptand reloading the service. - Python and Ansible on the control node and the target host, plus OpenSSL tools for key and CSR generation.
- The
community.cryptocollection installed on the control node. - For HTTP-01, a webroot served on port 80 or a coordinated standalone listener. For DNS-01, a provider module or API client with narrowly scoped credentials.
Install the collection on the machine from which Ansible runs:
ansible-galaxy collection install community.crypto
Do not confuse the collection with Certbot. You can use the Ansible module as the certificate client, or you can let Certbot manage issuance and renewal while Ansible configures the resulting files. Pick one owner for renewal on a host; running two independent clients against the same certificate can create competing files and reloads.
Create separate ACME and certificate keys
ACME uses an account key to authenticate requests to the certificate authority. The certificate itself has a different private key, represented by the CSR. Keep those keys separate. The account key should be long-lived and tightly protected; the certificate key is the key your web server presents and should be readable only by the service account or by root as required.
Rank #2
The following tasks create a 0600 account key and a certificate key, then build a CSR. Adjust the subject alternative names to the complete set of names you intend to request.
- name: Create the ACME account key
community.crypto.openssl_privatekey:
path: '{{ acme_account_key }}'
type: RSA
size: 4096
mode: '0600'
- name: Create the certificate private key
community.crypto.openssl_privatekey:
path: '{{ cert_key }}'
type: RSA
size: 2048
mode: '0600'
- name: Create the certificate signing request
community.crypto.openssl_csr:
path: '{{ csr_path }}'
privatekey_path: '{{ cert_key }}'
common_name: '{{ domain }}'
subject_alt_name:
- 'DNS:{{ domain }}'
- 'DNS:www.{{ domain }}'
mode: '0644'
Store the account email and any DNS API credentials in Ansible Vault or an equivalent secret store. Never place a token directly in a task, commit it to a repository, or print it with a debug task.
The two-pass Ansible playbook
The skeleton below shows the control flow. Set letsencrypt_directory to the current production ACME directory value used by your environment, and choose paths that match your service. The first task registers the challenge response; the second task consumes it.
---
- name: Issue or renew a Let’s Encrypt certificate
hosts: web
become: true
collections:
- community.crypto
vars:
domain: example.com
webroot: /var/www/html
acme_account_key: /etc/letsencrypt/account.key
cert_key: /etc/letsencrypt/live/{{ domain }}/privkey.pem
csr_path: /etc/letsencrypt/{{ domain }}.csr
cert_path: /etc/letsencrypt/live/{{ domain }}/cert.pem
chain_path: /etc/letsencrypt/live/{{ domain }}/chain.pem
fullchain_path: /etc/letsencrypt/live/{{ domain }}/fullchain.pem
letsencrypt_directory: '{{ acme_directory_from_your_environment }}'
acme_email: [email protected]
tasks:
- name: Request ACME challenge data
community.crypto.acme_certificate:
account_key_src: '{{ acme_account_key }}'
account_email: '{{ acme_email }}'
acme_directory: '{{ letsencrypt_directory }}'
terms_agreed: true
challenge: http-01
csr: '{{ csr_path }}'
register: acme_challenge
# Fulfil the returned challenge here.
- name: Retrieve the certificate after validation
community.crypto.acme_certificate:
account_key_src: '{{ acme_account_key }}'
account_email: '{{ acme_email }}'
acme_directory: '{{ letsencrypt_directory }}'
terms_agreed: true
challenge: http-01
csr: '{{ csr_path }}'
data: '{{ acme_challenge }}'
dest: '{{ cert_path }}'
chain_dest: '{{ chain_path }}'
fullchain_dest: '{{ fullchain_path }}'
remaining_days: 30
notify: Reload web service
handlers:
- name: Reload web service
ansible.builtin.service:
name: nginx
state: reloaded
remaining_days: 30 tells the module not to request a replacement when the existing certificate still has more than 30 days left. This check, existing output files, and a change-triggered handler keep repeated playbook runs safe and avoid unnecessary issuance.
Free tools Windows power users keep installed
One-click scans. No signup required.
Fulfil an HTTP-01 challenge
After the first module call, the registered result contains challenge data for each identifier in the CSR. For HTTP-01, publish the returned resource_value at the returned resource path beneath the webroot. The web server must be able to read the file before the second module call runs.
- name: Ensure the ACME challenge directory exists
ansible.builtin.file:
path: '{{ webroot }}/.well-known/acme-challenge'
state: directory
owner: root
group: root
mode: '0755'
- name: Publish each HTTP-01 challenge
ansible.builtin.copy:
content: '{{ item.value[''http-01''].resource_value }}'
dest: '{{ webroot }}/.well-known/acme-challenge/{{ item.value[''http-01''].resource }}'
owner: root
group: root
mode: '0644'
loop: '{{ acme_challenge.challenge_data | dict2items }}'
when: item.value[''http-01''] is defined
Before requesting the certificate, test one of the files from a network outside the server. A failure usually means the name resolves elsewhere, port 80 is filtered, a reverse proxy sends the path to the wrong backend, or the web server denies dot-directories. Correct that routing problem rather than repeatedly rerunning the ACME task.
Rank #3
Standalone HTTP-01
Standalone mode temporarily binds port 80 instead of using an existing webroot. It cannot bind while another process owns that port. Stop the web service for the validation window, coordinate a maintenance interval, or use webroot or DNS-01 instead. A stop-and-start sequence should be managed with Ansible handlers or a block with an always section so the service is restored even if validation fails.
Fulfil a DNS-01 challenge
For DNS-01, inspect every returned challenge entry and create a TXT record at its supplied _acme-challenge name with the supplied value. The exact Ansible task depends on your DNS provider, so keep the provider module behind a small role and pass credentials through Vault.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11- Loop over every identifier returned by the first
acme_certificatecall. - Create the TXT record at the returned record name, preserving the leading underscore and the correct DNS zone.
- Wait for propagation. Query authoritative servers or use the provider’s asynchronous completion status instead of assuming an immediate update.
- Run the second
acme_certificatetask with the unchanged registered result indata. - Remove temporary TXT records only after the order has completed, and retain any records needed by another simultaneous order.
Common DNS failures are a record created in the wrong zone, a stale value left beside the current value, propagation that has not completed, or an API token without permission to edit TXT records. Wildcard orders can contain more than one identifier, so publish every value rather than handling only the first loop item.
Deploy the files to Ubuntu services
Ubuntu’s documented Let’s Encrypt layout places live certificate material under /etc/letsencrypt/live/<domain>/. Configure the service to use fullchain.pem for the certificate chain and privkey.pem for the private key. The full chain allows clients to build trust through the required intermediate certificate; serving only the leaf certificate can cause verification failures on some clients.
Protect the private key with restrictive permissions and ensure the service account can read it without making it world-readable. Do not copy the private key into a public webroot, an Ansible fact, or a log file. If your playbook uses a different directory, apply the same separation and permissions.
Reload, rather than restart, a service after a successful certificate change when the daemon supports it. A handler notified by the certificate task prevents a reload on every idempotent run. Verify the active listener after deployment; a successful file update does not prove that the running process has opened the new keypair.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsRank #4
Renewal: Ansible module or Certbot
Renewal owned by the Ansible module
Schedule the playbook with your existing automation system and retain remaining_days so it renews only when necessary. The play must be able to perform the selected challenge unattended, and the reload handler must run after a changed certificate. For DNS-01, test both API authentication and propagation on a non-production name before relying on the schedule.
Renewal owned by Certbot
If you install the snap version of Certbot, its systemd renewal timer runs twice daily and attempts renewal when a certificate is close to expiry. Run:
certbot renew --dry-run
This exercises the renewal path without replacing the live certificate. Certbot-managed web-server integrations can reload supported services automatically, but a service outside that integration may continue using the old certificate. Add a Certbot deploy hook or an equivalent Ansible-triggered reload, then inspect the active listener after a test renewal.
Do not make Ansible issue a second certificate while Certbot is also renewing the same names. If Ansible only deploys configuration and Certbot owns the certificate files, have Ansible reference the existing paths and leave renewal to the timer.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Troubleshoot the failures that matter most
The HTTP-01 order fails immediately
- Confirm every requested DNS name resolves to the host that serves the challenge.
- Confirm inbound port 80 reaches that host through firewalls, security groups, NAT, and the reverse proxy.
- Fetch the exact
/.well-known/acme-challenge/...URL from outside the network and check that the returned body matchesresource_value. - Check that the web server does not rewrite the path into an application route or deny hidden directories.
Standalone mode reports that port 80 is busy
Find the process listening on port 80, then either stop it for the short validation interval, configure a controlled handoff, or switch to webroot or DNS-01. Repeated attempts without changing ownership of the port will produce the same failure.
The DNS-01 order cannot see the TXT record
- Check that the record was created in the authoritative zone, not in a similarly named parent or child zone.
- Query the authoritative DNS servers and allow for propagation before the second module call.
- Verify that the API token can create TXT records and that Ansible is using the intended account.
- Publish all returned values when multiple identifiers are present.
Renewal succeeds but clients still see the old certificate
Inspect the service configuration and the process actually bound to the listening port. Confirm that the deploy hook or Ansible handler ran after the files changed, then reload the daemon and verify the presented certificate from an external client. File timestamps alone do not establish what the running process is serving.
A replacement certificate is missing an existing name
When intentionally replacing a multi-domain certificate with Certbot, request the complete domain set. Supplying only a subset creates a certificate that does not cover the omitted names and can break clients that still use them.
Quick Recap
Security and reliability checklist
- Keep the ACME account key separate from the certificate private key.
- Store DNS API credentials in Ansible Vault or an equivalent secret manager and suppress them from task output.
- Use the production ACME directory only after the playbook works against a safe test environment.
- Request only the names that need to share a certificate; include every required name in the CSR.
- Use restrictive permissions on private keys and avoid copying them to application directories.
- Make challenge publication and cleanup idempotent.
- Set a renewal threshold such as 30 remaining days rather than forcing issuance on every run.
- Notify a reload handler only when certificate files change.
- Exercise the renewal path with
certbot renew --dry-runwhen Certbot owns renewal. - Monitor expiry and the service’s active certificate, not merely the success status of the automation job.
End-to-end run order
- Verify DNS, port 80 reachability, and the names in the CSR.
- Install
community.cryptowithansible-galaxy collection install community.crypto. - Create or retrieve the protected ACME account key and generate the domain CSR with a separate certificate key.
- Run
community.crypto.acme_certificateonce to obtain challenge data. - Publish every HTTP-01 file or DNS-01 TXT record and wait until the challenge is reachable.
- Run the same module with
dataset to the registered result and write the certificate, chain, and full chain destinations. - Configure the service for
fullchain.pemandprivkey.pem, then reload only after a change. - Schedule idempotent renewal and test it before the 90-day certificate reaches expiry.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.




