Environment & Verification Matrix
- Firewall / OS: OPNsense
24.x+ (Business/Community)- ACME Engine:
os-acme-client(acme.shcore)- DNS Provider: Google Cloud Platform (Cloud DNS API)
- IAM Role Scope: Custom DNS Record Admin (Least Privilege)
- Primary Documentation: acme.sh DNS API Guide - Google Cloud DNS
Architectural TL;DR
Securing internal management consoles, edge proxies, and self-hosted services across enterprise or home-lab subnets usually presents a dilemma: expose Port 80 on your WAN interface to satisfy HTTP-01 challenges, or manually rotate certificates every 60 to 90 days.
By leveraging Let’s Encrypt DNS-01 challenges through GCP Cloud DNS, your firewall requests and validates wildcard certificates (*.yourdomain.com) strictly via outbound HTTPS API calls. WAN Port 80 remains completely closed, and the resulting certificates seamlessly deploy to the OPNsense WebGUI, HAProxy, and internal service daemons.
flowchart LR
subgraph LocalNet ["Internal Edge (OPNsense)"]
ACME[os-acme-client]
end
subgraph CloudDNS ["Google Cloud Platform"]
IAM[Least-Privilege Service Account]
API[Cloud DNS API]
Zone[(Managed DNS Zone)]
end
subgraph LetsEncrypt ["Let's Encrypt CA"]
CA[ACME Validation Server]
end
ACME -->|1. Sign with JSON Key| IAM
IAM -->|2. Insert _acme-challenge TXT| API
API -->|3. Update Record Set| Zone
CA -->|4. Query TXT Record| Zone
CA -->|5. Issue Wildcard Cert| ACME1. IAM Hardening: Least-Privilege GCP Service Account
Standard tutorials often recommend granting roles/dns.admin at the project level. For an edge appliance holding long-lived credentials, this violates least-privilege principles.
Instead, create a dedicated service account restricted exclusively to record set modifications, or bind roles/dns.admin only if custom roles are impractical in your workspace.
Provision Identity via Terraform (No Keys in State though)
| |
After running terraform apply, you need to mint yourself a key. This happens out of band:
| |
2. OPNsense ACME Client Configuration
Step A: Install the Plugin
Navigate to System > Firmware > Plugins in the OPNsense WebGUI. Search for and install:
os-acme-client (Let's Encrypt client powered by acme.sh)
Step B: Configure the Validation Method
Navigate to Services > Let’s Encrypt > Validation Methods:
- Click Add (+).
- Name: GCP-CloudDNS-DNS01
- Method: DNS-01
- DNS Service: Google Cloud DNS
- GCP Project ID: your-project-id
- Service Account JSON: Paste the raw contents of opnsense-acme-gcp-key.json.
- Sleep Time: Set to 120 seconds. (Cloud DNS propagates quickly, but giving Google’s authoritative nameservers a 2-minute buffer ensures Let’s Encrypt validation nodes never encounter a stale NXDOMAIN).
Step C: Define the Certificate Set
Navigate to Services > Let’s Encrypt > Certificates:
- Click Add (+).
- Common Name: yourdomain.com
- AltNames: *.yourdomain.com
- Validation Method: GCP-CloudDNS-DNS01
- Auto Renewal: Checked (Default: 60 days).
- Restart / Reload Actions: Select OPNsense Web GUI (or target HAProxy services).
3. Automation Lifecycle & Automation Hooks
- When the renewal cron runs (managed natively by OPNsense’s system crontab), the process executes cleanly:
acme.shauthenticates to GCP using OAuth2 token exchange with the private JSON key. - A temporary TXT record _acme-challenge.yourdomain.com is written to Cloud DNS.
- The client sleeps for 120 seconds.
- Let’s Encrypt queries the public nameservers, validates domain ownership, and issues the signed ECDSA/RSA certificate chain.
acme.shpurges the TXT record from the zone.- The certificate is stored in OPNsense’s Trust Certificate Store, and WebGUI daemons are reloaded automatically.
4. Verification & Receipts
To test the implementation without waiting for the 60-day renewal cycle, trigger a force renewal directly from the OPNsense console or WebGUI.
Inspecting Cloud DNS During Validation
Run a manual check while the 120-second sleep is active:
| |
Inspecting the OPNSense Execution Log
Check Services > Let’s Encryption > Log Files:
| |
The result is a low-touch, low-open-port PKI setup that keeps your firewall perimeter locked down while maintaining always-valid SSL certificates across all internal infrastructure.