Skip to main content
RunBook Academy

OPNsenseXXIV · PKI and CertificatesPKI and certificate management

ACME and automated certificate renewal

Intermediate⏱ ~14 min🧪 Lab requiredopensslcurlssh

What you'll learn

  • Explain how the ACME protocol automates certificate issuance and renewal
  • Distinguish HTTP-01 and DNS-01 challenges and when each applies
  • Configure the OPNsense os-acme-client plugin for a public hostname
  • Configure the DNS-01 challenge for a hostname behind a firewall
  • Apply the operational discipline that prevents ACME renewal failures

Prerequisites

Verified against OPNsense 25.x · FreeBSD 14.x · PF (FreeBSD packet filter) FreeBSD 14.x · Unbound 1.20+ · Kea DHCP OPNsense 25.x plugin · WireGuard in-kernel + OPNsense plugin · strongSwan (IPsec plugin) OPNsense 25.x plugin · OpenVPN 2.6.x · Suricata 7.x · 2026-08-14

Not yet marked complete on this device.

Short-lived certificates are safer than long-lived ones: the window in which a compromised key can be misused is short, and revocation is less critical when the certificate would have expired anyway. The price is renewal — every certificate must be re-issued before it expires. ACME (Automatic Certificate Management Environment) automates that renewal.

This lesson covers how ACME works at the protocol level, the difference between HTTP-01 and DNS-01 challenges, how to configure the OPNsense os-acme-client plugin for a public hostname, how to configure DNS-01 for hostnames that are not publicly reachable, and the operational discipline that keeps automated renewal working.

How ACME works

ACME is defined by RFC 8555. The protocol flow:

Client (ACME agent)                    ACME server (CA)
  | --- Register account ------------>      |
  | <-- Account URL ------------------       |
  | --- Request challenge for name ---->     |
  | <-- Challenge token, type ------------   |
  | --- Prove control of name ------------>  |
  | <-- Challenge verified ----------------   |
  | --- Finalise order (submit CSR) ---->    |
  | <-- Certificate ---------------------    |

The client proves control of the name by satisfying a challenge. The CA publishes a token, the client places a specific value at a known location tied to the name, the CA verifies the value is present, and the CA signs the certificate. The challenge types are HTTP-01, DNS-01, and TLS-ALPN-01 (less commonly used).

The renewal is automatic. The ACME agent runs on a schedule, checks the certificate’s expiry, and if the expiry is within the renewal window (typically 30 days before expiry), it runs the challenge and re-issues. The agent installs the new certificate and reloads the service.

HTTP-01 vs DNS-01

The two challenge types most operators encounter:

HTTP-01. The CA expects a token at http://\<name\>/.well-known/acme-challenge/\<token\>. The client serves the token over HTTP on port 80. The CA fetches the URL and verifies the token is present.

  • Pros: simple, no DNS provider integration needed, works with most CAs.
  • Cons: requires port 80 to be reachable from the Internet, does not work for wildcard certificates, does not work for hostnames that are not publicly resolvable.

DNS-01. The CA expects a TXT record at _acme-challenge.\<name\>. The client creates the TXT record via the DNS provider’s API. The CA queries DNS and verifies the TXT record is present.

  • Pros: works without exposing port 80, supports wildcard certificates (*.example.com), works for hostnames that are not publicly resolvable.
  • Cons: requires the DNS provider to support an API the ACME agent can call, the API token is a high-privilege credential (it can modify DNS records), and the DNS propagation delay can affect renewal timing.
ChallengePort 80 neededWildcards supportedWorks for private hostnamesDNS provider API needed
HTTP-01YesNoNoNo
DNS-01NoYesYesYes

Configuring ACME on OPNsense

The OPNsense ACME client lives in the os-acme-client plugin. After installing the plugin under System → Firmware → Plugins:

  1. Open Services → ACME Client → Accounts.
  2. Add an account with the ACME server URL (default: Let’s Encrypt production at https://acme-v02.api.letsencrypt.org/directory, staging at https://acme-staging-v02.api.letsencrypt.org/directory for testing).
  3. Open Services → ACME Client → Automations.
  4. Click Add to configure an automation that issues a certificate for a specific hostname.

For an HTTP-01 challenge:

  • Challenge type: HTTP-01.
  • Domain: the hostname (e.g. fw.example.com).
  • Automations: select the action (write certificate to OPNsense trust store, restart GUI, etc.).

For a DNS-01 challenge:

  • Challenge type: DNS-01.
  • DNS service: select the DNS provider plugin (Cloudflare, Route53, DigitalOcean, etc.).
  • API key: paste the provider API key.
  • Domain: the hostname.

The automation runs on the OPNsense cron schedule, checks the certificate, and re-issues if it is within the renewal window.

Read-only / Safeverify ACME cert
$ openssl s_client -connect fw.example.com:443 -servername fw.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates
subject=CN = fw.example.com
issuer=C = US, O = Let's Encrypt, CN = R10
notBefore=Aug  1 00:00:00 2026 GMT
notAfter=Oct 30 00:00:00 2026 GMT

Illustrative output

Operational discipline for ACME

The renewal automation is the production safety net. The discipline:

  1. Test against staging first. A misconfigured challenge that fails repeatedly against production burns rate limit budget and triggers temporary blacklisting.
  2. Monitor the renewal. The automation can fail silently. The expiry monitoring lesson in this part of the course covers what to alert on.
  3. Keep the DNS API token scoped and audited. A leaked token compromises every name in the zone.
  4. Plan for ACME server unavailability. If Let’s Encrypt is offline, the renewal fails. A multi-CA strategy (a backup CA configured but not active, or a switch to an internal CA for the duration) is the production answer.
  5. Document the chain. The certificate is signed by an ACME CA. The chain must reach a root the verifier trusts. Let’s Encrypt’s chain is in the default trust stores of most browsers and operating systems — but a firewall service that needs to trust its own certificate is already configured for the chain.

Summary

  • ACME automates certificate issuance and renewal. The client proves control of the name via a challenge, the CA verifies and signs.
  • HTTP-01 requires port 80 reachable from the Internet. DNS-01 works for private hostnames and wildcards but needs a high-privilege DNS API token.
  • OPNsense ships the os-acme-client plugin. Test against staging first to avoid burning production rate limits.
  • Monitor renewals, scope the DNS token, plan for CA unavailability, and document the chain.

Knowledge check · 4 questions

  1. Q1. You need an ACME certificate for a hostname that is not publicly resolvable (split-horizon DNS, internal-only). Which challenge type allows the CA to verify control of the name without reaching port 80?

  2. Q2. A DNS-01 ACME challenge requires an API token with full DNS zone control, and a leaked token allows an attacker to issue themselves certificates for any name in the zone.

  3. Q3. Which of the following are part of the operational discipline that keeps ACME renewal working in production? Select all that apply.

  4. Q4. You have configured ACME for fw.example.com with DNS-01 using a Cloudflare API token. The first issuance succeeds. Six months later the renewal fails. What is the most likely cause?

Passing score: 75%. Answers are checked in this browser.