Independent personal review. Not affiliated with YouFibre Ltd. About this site

HTTPS for self-hosted services - ACME, Let’s Encrypt & Cloudflare DNS on OPNsense

Part 3 of 3 - Self-Hosting with OPNsense and HAProxy
← Part 1: What is a reverse proxy? Self-hosting explained
← Part 2: HAProxy on OPNsense - configuring your reverse proxy

At the end of Part 2, HAProxy is routing requests to the right internal services based on hostname - but with a self-signed certificate that browsers flag as untrusted. This post replaces that with a proper certificate from Let’s Encrypt: free, browser-trusted, and set to renew automatically.

The method used here is a DNS challenge via Cloudflare. This is the best approach for home self-hosting because it doesn't require port 80 to be open and works even for subdomains that aren't directly accessible from the internet during validation. OPNsense's ACME client handles the whole process, including automatic renewal.

Concepts: ACME, Let’s Encrypt, and DNS challenges

What ACME is

ACME (Automatic Certificate Management Environment) is the protocol that Let’s Encrypt uses to verify that you control a domain before issuing a certificate. It's also the same protocol that OPNsense's certificate client speaks. You don't interact with ACME directly; the client handles the exchange.

What a DNS challenge is

To issue a certificate, Let’s Encrypt needs to confirm you control the domain. There are two common ways to prove this:

  • HTTP challenge: Let’s Encrypt fetches a specific file from your web server over port 80. This requires port 80 to be open and reachable from the internet at the time of issuance.
  • DNS challenge: Your ACME client creates a temporary TXT record in your domain's DNS. Let’s Encrypt checks for that record. Once it's confirmed, the certificate is issued and the record is deleted. No port needs to be open during this process.

The DNS challenge is preferable for home setups because it works for wildcard certificates (*.example.com), doesn't require port 80 to be exposed, and works even if your services aren't yet reachable from the internet.

Why Cloudflare for DNS

Cloudflare provides a free DNS service with a well-documented API. OPNsense's ACME plugin has built-in support for Cloudflare's API, which means the certificate client can create and delete the TXT records automatically during validation. You don't need to do anything manually after initial setup - renewals happen entirely hands-free.

If your domain isn't currently on Cloudflare, you can either transfer it (free) or change just the nameservers to point at Cloudflare while keeping your domain registered elsewhere. Either way, Cloudflare just needs to be authoritative for the DNS zone.

Step 1: Get a Cloudflare API token

Don't use your main Cloudflare account API key for this. Create a scoped token that can only do what the ACME client needs:

  1. Log in to your Cloudflare dashboard and go to My Profile → API Tokens.
  2. Click Create Token.
  3. Use the Edit zone DNS template.
  4. Under Zone Resources, restrict the token to the specific zone (domain) you're issuing certificates for.
  5. Under Permissions, confirm it has Zone → DNS → Edit. Remove any other permissions.
  6. Create the token and copy it somewhere safe. You won't be able to view it again.

This token is what OPNsense will use to create the TXT records during certificate validation. Keeping it scoped to DNS edit on one zone limits the blast radius if it were ever compromised.

Step 2: Install the ACME plugin on OPNsense

  1. Go to System → Firmware → Plugins.
  2. Search for os-acme-client.
  3. Install it.
  4. After installation, it appears under Services → ACME Client.

Step 3: Configure an ACME account

Before issuing any certificates, you need to register an account with Let’s Encrypt:

  1. Go to Services → ACME Client → Accounts.
  2. Click Add.
  3. Enter your email address. Let’s Encrypt uses this to send expiry warnings (though with automatic renewal, you shouldn't need them).
  4. Leave the ACME URL set to Let’s Encrypt Production. During testing you can use the staging URL to avoid rate limits, but switch to production before issuing certificates you'll actually use.
  5. Save and click Register to create the account. A green status indicator confirms it registered successfully.

Step 4: Add a Cloudflare DNS challenge method

  1. Go to Services → ACME Client → Challenge Types.
  2. Click Add.
  3. Set the Name to something descriptive, e.g. cloudflare_dns.
  4. Set the Challenge Type to DNS-01.
  5. Set the DNS Service to Cloudflare.
  6. Paste your Cloudflare API token into the API Token field.
  7. Save.

Step 5: Issue a certificate

Go to Services → ACME Client → Certificates and click Add. Fill in the certificate details:

  • Common Name: your primary domain, e.g. example.com
  • Alt Names (SANs): add any subdomains you want the certificate to cover. Add each one separately: nextcloud.example.com, blog.example.com, etc. Alternatively, use a wildcard: *.example.com - this covers all subdomains with one cert.
  • ACME Account: select the account you registered in Step 3.
  • Challenge Type: select the cloudflare_dns method from Step 4.
  • Auto Renewal: enable this. OPNsense will automatically renew the certificate before it expires (Let’s Encrypt certificates are valid for 90 days; renewal typically happens at 60 days).

Save, then click the Issue / Renew button next to the certificate. OPNsense will contact Let’s Encrypt, create the TXT record in Cloudflare, wait for propagation, complete the challenge, and download the certificate. This takes between 30 seconds and a few minutes. A green status indicates success.

If it fails, check the ACME client log under Services → ACME Client → Log File. The most common failure causes are an incorrect API token, a typo in the domain name, or the TXT record not propagating quickly enough (rare with Cloudflare's fast DNS).

Step 6: Wire the certificate into HAProxy

Once the certificate is issued, it appears in OPNsense's certificate store under System → Trust → Certificates. Now attach it to the HAProxy frontend you configured in Part 2:

  1. Go to Services → HAProxy → Frontend.
  2. Edit your HTTPS frontend.
  3. Under SSL Certificates, remove the self-signed certificate and add the Let’s Encrypt certificate issued in Step 5.
  4. Save and click Apply.

Visit one of your configured hostnames in a browser. The padlock should now show as valid and the certificate should be issued by Let’s Encrypt. No more warnings.

Step 7: Automatic HAProxy reload on renewal

When ACME renews the certificate, HAProxy needs to reload to pick up the new certificate. OPNsense can do this automatically:

  1. Go to Services → ACME Client → Settings.
  2. Enable HAProxy Integration.
  3. Save.

With this enabled, OPNsense will reload HAProxy automatically whenever a certificate is renewed. No manual intervention needed - the setup is genuinely set-and-forget.

Wildcard certificates

If you use a wildcard certificate (*.example.com), a single certificate covers every subdomain. This simplifies management: one renewal, one HAProxy certificate entry, every service covered. The DNS challenge is the only method Let’s Encrypt supports for wildcard issuance, which is another reason the Cloudflare DNS challenge is the right choice for this setup.

The trade-off is that a wildcard certificate covers all subdomains indiscriminately. If you prefer to issue a separate certificate per service (which gives you more granular expiry and revocation control), you can - just add each service as its own certificate entry in the ACME client. Both approaches work with HAProxy.

Summary: what you now have

After completing all three parts of this series:

  • HAProxy on OPNsense is receiving all inbound HTTPS traffic on port 443.
  • ACL rules route each hostname to the correct internal service.
  • All traffic is encrypted with a trusted Let’s Encrypt certificate.
  • Certificates renew automatically, with HAProxy reloaded to apply the new certificate.
  • No port 80 exposure needed during validation thanks to the Cloudflare DNS challenge.

This is a production-grade HTTPS setup running entirely on your home router, made practical by a YouFibre FTTP connection with a static IP. The total additional cost is zero - ACME, Let’s Encrypt, and Cloudflare DNS are all free, and HAProxy is included in the OPNsense plugin ecosystem at no charge.

If you're not yet on YouFibre, this whole setup becomes possible once you have a reliable full-fibre connection with a static IP. Referral code KCR5KH is available for new customers.

Check Availability at YouFibre

← Back to blog

Code copied to clipboard!