OPNsense Trust Certificates
This role manages SSL/TLS certificates on OPNsense via the Trust API.
OPNsense Trust Certificates Role
Overview
This role manages SSL/TLS certificates on OPNsense via the Trust API. It provides full lifecycle management: creating new certificates signed by an existing OPNsense CA, reissuing certificates when configuration changes or they expire, and deleting certificates not defined in configuration. Certificate and private key files are saved locally for deployment to services.
Purpose
- Certificate as Code: Define all certificates in version-controlled configuration
- Automatic Creation: New certificates are created and signed by OPNsense CA
- Automatic Reissue: Certificates are reissued when configuration changes or on expiry
- Cleanup: Certificates not in configuration are automatically deleted
- File Export: Certificate and private key files saved for deployment
- Idempotent: Safe to run multiple times, only changes what’s needed
- Secure: Private keys never appear in Ansible logs (
no_log: true)
Requirements
- Ansible 2.14 or higher
- OPNsense firewall with API access enabled
- API key and secret stored in Ansible Vault
- Network connectivity to OPNsense (VLAN10)
- An existing Certificate Authority configured in OPNsense
gather_facts: truein playbook (required for expiry check)
Role Variables
Required Variables
| Variable | Required | Description |
|---|---|---|
vault_opnsense_bjoffrey_user_api_key | Yes | OPNsense API key (in vault) |
vault_opnsense_bjoffrey_user_api_secret | Yes | OPNsense API secret (in vault) |
opnsense_trust_certificates_list | Yes | List of certificate definitions (in vars file) |
Optional Variables
| Variable | Default | Description |
|---|---|---|
opnsense_trust_certificates_ca_name | OPNsense_CA | Name of the signing CA in OPNsense |
opnsense_trust_certificates_validate_certs | true | Validate SSL certificates for API calls |
opnsense_trust_certificates_output_dir | /home/bjoffrey/Documents/ansible/homelab | Directory for exported .crt/.key files |
Default Certificate Settings
Applied to all certificates unless overridden per-certificate:
| Variable | Default | Description |
|---|---|---|
key_type | 2048 | RSA key size |
digest | sha256 | Signature digest algorithm |
cert_type | server_cert | Certificate type |
lifetime | 1200 | Certificate validity in days (~3.3 years) |
private_key_location | firewall | Where the private key is stored |
country | FR | Subject country |
state | Rhone-Alpes | Subject state |
city | Lyon | Subject city |
organization | Home | Subject organization |
organizationalunit | Home | Subject organizational unit |
email | admin@example.com | Subject email |
Certificate Definition
Each certificate in opnsense_trust_certificates_list:
| Field | Required | Description |
|---|---|---|
descr | Yes | Certificate description (used as identifier) |
commonname | Yes | Certificate Common Name (CN) |
altnames_dns | No | DNS Subject Alternative Names |
altnames_ip | No | IP Subject Alternative Names |
altnames_uri | No | URI Subject Alternative Names |
altnames_email | No | Email Subject Alternative Names |
key_type | No | Override default key type |
digest | No | Override default digest |
cert_type | No | Override default cert type |
lifetime | No | Override default lifetime |
Certificate Examples
Simple Certificate (Single DNS/IP)
- descr: "Navidrome"
commonname: "server.homelab"
altnames_dns: "server.homelab"
altnames_ip: "192.168.x.x"
Certificate with Multiple SANs
- descr: "Centreon"
commonname: "server.homelab"
altnames_dns: |
server.homelab
server.homelab
altnames_ip: |
192.168.x.x
192.168.x.x
Dependencies
This role has no dependencies on other Ansible roles.
Example Playbook
---
- name: Configure OPNsense Trust Certificates
hosts: mint-vm
gather_facts: true
vars_files:
- ../../roles/opnsense_trust_certificates/vars/certificates.yml
tasks:
- name: Manage SSL/TLS certificates
ansible.builtin.include_role:
name: opnsense_trust_certificates
What This Role Does
- Fetch CA list and look up CA by name to get
refid - Fetch existing certificates from OPNsense and build lookup by description
- Create new certificates that exist in config but not in OPNsense
- Signs with the configured CA
- Saves .crt and .key files locally
- Check existing certificates for reissue need:
- Common name changed
- DNS/IP/URI/email SANs changed
- Certificate type, key type, or digest changed
- Certificate expired (
valid_to< current timestamp)
- Reissue certificates that need updating
- Generates new certificate (keeps same private key)
- Saves updated .crt and .key files locally
- Delete certificates not defined in configuration
- Display summary of created, reissued, and deleted certificates
Reissue Triggers
A certificate is reissued when any of these change:
| Field | Description |
|---|---|
commonname | Certificate Common Name |
altnames_dns | DNS Subject Alternative Names |
altnames_ip | IP Subject Alternative Names |
altnames_uri | URI Subject Alternative Names |
altnames_email | Email Subject Alternative Names |
cert_type | Certificate type (server_cert, etc.) |
key_type | Key type/size |
digest | Signature digest algorithm |
| expired | Certificate valid_to is in the past |
Note: lifetime changes alone do NOT trigger reissue. The new lifetime is applied on the next reissue.
OPNsense API Endpoints
Search Certificates
GET /api/trust/cert/search
Authorization: Basic (API key:secret)
Returns all certificates with their properties.
Get Certificate Details
GET /api/trust/cert/get/{uuid}
Authorization: Basic (API key:secret)
Returns full certificate details including crt_payload and prv_payload.
Create Certificate
POST /api/trust/cert/add
Authorization: Basic (API key:secret)
Content-Type: application/json
Request body:
{
"cert": {
"action": "internal",
"descr": "My Certificate",
"caref": "ca-refid-here",
"commonname": "server.homelab",
"altnames_dns": "server.homelab",
"altnames_ip": "192.168.x.x",
"key_type": "2048",
"digest": "sha256",
"cert_type": "server_cert",
"lifetime": "1200"
}
}
Reissue Certificate
POST /api/trust/cert/set/{uuid}
Authorization: Basic (API key:secret)
Content-Type: application/json
Same body as create, but with "action": "reissue" and existing payloads included.
Delete Certificate
POST /api/trust/cert/del/{uuid}
Authorization: Basic (API key:secret)
Search Certificate Authorities
GET /api/trust/ca/search
Authorization: Basic (API key:secret)
Returns all CAs. The role uses refid (not uuid) as the caref when signing certificates.
File Output
Created and reissued certificates are saved to the output directory:
{output_dir}/{descr}.crt # Certificate (PEM format)
{output_dir}/{descr}.key # Private key (PEM format)
Spaces in descr are replaced with underscores. Files are created with mode 0600.
Example:
/home/bjoffrey/Documents/ansible/homelab/OPNsense_Web_UI.crt
/home/bjoffrey/Documents/ansible/homelab/OPNsense_Web_UI.key
Idempotency
Role is fully idempotent:
- First run: Creates all certificates, reports changes
- Subsequent runs:
- Skips existing certificates with matching configuration
- Only reissues if configuration changed or certificate expired
- Only deletes certificates removed from config
- Reports
okif no changes needed
Multiline SAN values (using YAML |) are normalized before comparison to avoid false positives from trailing whitespace.
Security Considerations
- API Credentials: Stored in Ansible Vault
- HTTPS: Uses SSL/TLS for API calls
- no_log: Certificate and private key content never appears in Ansible output
- File Permissions: Output files created with mode 0600
- Private Keys: Exported keys should be handled securely
- Certificate Validation: Enabled by default
Troubleshooting
Certificates reissued unnecessarily
Cause: Multiline SAN format mismatch between YAML and API response
Solution: The role normalizes multiline values (trim, split, sort, join) before comparing. If issues persist, verify the exact format returned by the API.
CA not found
Cause: opnsense_trust_certificates_ca_name doesn’t match any CA in OPNsense
Solution: Check CA names in OPNsense UI (System > Trust > Authorities) and update the variable.
Certificate files not created
Cause: Output directory doesn’t exist or wrong permissions
Solution: Ensure opnsense_trust_certificates_output_dir exists and is writable.
Related Roles
This role is often used with:
- deploy_ssl_certificates: Deploy certificates to servers
- opnsense_conf_backup: Backup OPNsense configuration
- opnsense_dashboard: Dashboard shows certificate status widget
License
MIT
Author
Created for homelab infrastructure management.