Public ACME Runbook
Cloudflare DNS-01 setup and Let's Encrypt issuance for OPNsense, Proxmox, PBS, and planned Kubernetes workloads.
Public certificate issuance uses one Cloudflare API token scoped to aorxi.io. OPNsense, acme.sh, and cert-manager each complete DNS-01 challenges without an inbound HTTP challenge path.
Cloudflare API Token
Create a custom token under Cloudflare Dashboard → My Profile → API Tokens.
| Permission | Scope |
|---|---|
| Zone → DNS → Edit | aorxi.io only |
| Zone → Zone → Read | aorxi.io |
Scope the Token to aorxi.io Only
Never grant DNS edit permission across all zones. Record the token when it is displayed; Cloudflare shows its value only once.
The examples below refer to the value as <CF_API_TOKEN>.
OPNsense
Install os-acme-client from System → Firmware → Plugins.
Register the ACME Account
Under Services → ACME Client → Accounts, create:
| Field | Value |
|---|---|
| Name | letsencrypt |
<your-email> | |
| ACME URL | https://acme-v02.api.letsencrypt.org/directory |
Save and register the account.
Configure DNS-01
Under Services → ACME Client → Challenge Types, create:
| Field | Value |
|---|---|
| Name | cloudflare-dns01 |
| Challenge Type | DNS-01 |
| DNS Service | Cloudflare |
| API Token | <CF_API_TOKEN> |
Issue and Bind Certificates
Create one certificate entry per firewall:
| Certificate | Alt name | Host |
|---|---|---|
sa-fw-01 | sa-fw-01.core.aorxi.io | Site A OPNsense WebGUI |
sb-fw-01 | sb-fw-01.core.aorxi.io | Site B OPNsense WebGUI |
Use ec-256, the letsencrypt account, cloudflare-dns01, and automatic renewal. After issuance, select the certificate under System → Settings → Administration → SSL Certificate.
The plugin renews through an OPNsense cron job. Verify renewal activity under Services → ACME Client → Log before the certificate reaches 30 days remaining.
Proxmox and PBS
Run the following on each Proxmox or Proxmox Backup Server (PBS) node.
Install and Configure acme.sh
curl https://get.acme.sh | sh -s email=<your-email>
source ~/.bashrc
export CF_Token="<CF_API_TOKEN>"
export CF_Account_ID="<CF_ACCOUNT_ID>"
echo 'export CF_Token="<CF_API_TOKEN>"' >> ~/.acme.sh/account.conf
echo 'export CF_Account_ID="<CF_ACCOUNT_ID>"' >> ~/.acme.sh/account.confThe Cloudflare account ID appears in the dashboard URL.
Issue a Node Certificate
acme.sh --issue \
--dns dns_cf \
-d sa-stor-01.core.aorxi.io \
--keylength ec-256 \
--server letsencryptSubstitute the target node hostname.
Install into Proxmox
acme.sh --install-cert \
-d sa-stor-01.core.aorxi.io \
--cert-file /etc/pve/local/pve-ssl.pem \
--key-file /etc/pve/local/pve-ssl.key \
--reloadcmd "systemctl restart pveproxy"Install into PBS
acme.sh --install-cert \
-d sa-pbs-01.core.aorxi.io \
--cert-file /etc/proxmox-backup/proxy.pem \
--key-file /etc/proxmox-backup/proxy.key \
--reloadcmd "systemctl restart proxmox-backup-proxy"acme.sh installs its renewal cron job. Verify it with:
crontab -l | grep acme
# Expected: 0 0 * * * /root/.acme.sh/acme.sh --cron --home /root/.acme.shKubernetes
Tentative: Clusters Are Not Deployed
cert-manager and ClusterIssuer resources are planned for the Kubernetes phase. The manifests below describe the intended configuration, not observed state.
Install cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--set crds.enabled=trueStore the Cloudflare Token
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token
namespace: cert-manager
type: Opaque
stringData:
api-token: "<CF_API_TOKEN>"Create the ClusterIssuer
Deploy one in each site-local cluster:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-cloudflare
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: <your-email>
privateKeySecretRef:
name: letsencrypt-cloudflare-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-tokenRequest Wildcard Certificates
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: core-wildcard
namespace: cert-manager
spec:
secretName: core-wildcard-tls
issuerRef:
name: letsencrypt-cloudflare
kind: ClusterIssuer
dnsNames:
- "*.core.aorxi.io"
- "core.aorxi.io"
renewBefore: 360h
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: aorxi-wildcard
namespace: cert-manager
spec:
secretName: aorxi-wildcard-tls
issuerRef:
name: letsencrypt-cloudflare
kind: ClusterIssuer
dnsNames:
- "*.aorxi.io"
- "aorxi.io"
renewBefore: 360hReference a shared wildcard Secret from an Ingress:
spec:
tls:
- hosts:
- myapp.core.aorxi.io
secretName: core-wildcard-tlsAlternatively, annotate an Ingress for per-service issuance:
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-cloudflare
spec:
tls:
- hosts:
- myapp.core.aorxi.io
secretName: myapp-tlsLet's Encrypt Rate Limits
The source design records 50 certificates per domain per week and five duplicate certificates per week. Prefer a shared wildcard over repeated per-namespace issuance; validate current limits before deployment.
Operations
Rotate the Cloudflare Token
Update the token in the OPNsense challenge configuration, every node's ~/.acme.sh/account.conf, and the cloudflare-api-token Secret in each cluster. Force a cert-manager renewal when required:
cmctl renew <cert-name> -n cert-managerTest with Staging
Validate DNS-01 Before Production Issuance
Use Let's Encrypt staging to prove propagation and authentication without consuming the production issuance allowance. Staging certificates are not browser-trusted.
acme.sh: add--server letsencrypt_test.- cert-manager: use
https://acme-staging-v02.api.letsencrypt.org/directory.
Monitor Expiry
The source design calls for Prometheus blackbox_exporter TLS probes with alerts at 30 days remaining. The cert-manager Grafana dashboard covers Kubernetes-managed certificates.
Related Pages
- CA & Certificate Infrastructure: issuer boundary and certificate inventory
- Private step-ca Runbook: private IPMI and mTLS issuance
- DNS VMs: internal names under
core.aorxi.io
CA & Certificate Infrastructure
Certificate strategy, issuer boundaries, inventory, network policy, and deployment order for public ACME and private step-ca certificates.
Private step-ca Runbook
Deployment, IPMI certificate issuance, trust distribution, renewal, backup, and network controls for the private step-ca instance.