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:
- Log in to your Cloudflare dashboard and go to My Profile → API Tokens.
- Click Create Token.
- Use the Edit zone DNS template.
- Under Zone Resources, restrict the token to the specific zone (domain) you're issuing certificates for.
- Under Permissions, confirm it has
Zone → DNS → Edit. Remove any other permissions. - 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
- Go to System → Firmware → Plugins.
- Search for
os-acme-client. - Install it.
- 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:
- Go to Services → ACME Client → Accounts.
- Click Add.
- Enter your email address. Let’s Encrypt uses this to send expiry warnings (though with automatic renewal, you shouldn't need them).
- 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.
- Save and click Register to create the account. A green status indicator confirms it registered successfully.
Step 4: Add a Cloudflare DNS challenge method
- Go to Services → ACME Client → Challenge Types.
- Click Add.
- Set the Name to something descriptive, e.g.
cloudflare_dns. - Set the Challenge Type to
DNS-01. - Set the DNS Service to
Cloudflare. - Paste your Cloudflare API token into the API Token field.
- 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_dnsmethod 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:
- Go to Services → HAProxy → Frontend.
- Edit your HTTPS frontend.
- Under SSL Certificates, remove the self-signed certificate and add the Let’s Encrypt certificate issued in Step 5.
- 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:
- Go to Services → ACME Client → Settings.
- Enable HAProxy Integration.
- 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