Simplifying TLS Certificate Management in Kubernetes
Since launching Cloudflare Origin CA in 2016, we've operated a certificate authority built to streamline securing connections between Cloudflare and origin servers. Running our own CA enables fast issuance and renewal, straightforward revocation, and wildcard certificate support. But managing TLS certificates and keys natively in Kubernetes remains a fiddly, error-prone operation: secrets must be formatted exactly as components expect, some domain verification flows demand manual secret rotation, and expiration is easy to overlook.
The cert-manager project addresses these operational hurdles with Kubernetes resources that automate certificate lifecycle management. We've now released origin-ca-issuer, an extension that plugs cert-manager into Cloudflare Origin CA so you can issue and renew certificates for your account's domains with minimal manual effort.
Issuing Certificates with OriginIssuer
Once cert-manager and origin-ca-issuer are installed, you define an OriginIssuer resource to bind cert-manager to the Cloudflare API for a specific account. Because the binding is per resource, you can connect different issuers to different Cloudflare accounts within the same cluster.
apiVersion: cert-manager.k8s.cloudflare.com/v1
kind: OriginIssuer
metadata:
name: prod-issuer
namespace: default
spec:
signatureType: OriginECC
auth:
serviceKeyRef:
name: service-key
key: key
```
This configuration creates an OriginIssuer named prod-issuer that signs certificates with ECDSA keys; authentication to the Cloudflare API uses the service-key secret in the same namespace.
With an issuer in place, you create a cert-manager Certificate resource describing the domains (wildcards included), desired validity period, and renewal timing for the certificate.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com
namespace: default
spec:
# The secret name where cert-manager
# should store the signed certificate.
secretName: example-com-tls
dnsNames:
- example.com
# Duration of the certificate.
duration: 168h
# Renew a day before the certificate expiration.
renewBefore: 24h
# Reference the Origin CA Issuer you created above,
# which must be in the same namespace.
issuerRef:
group: cert-manager.k8s.cloudflare.com
kind: OriginIssuer
name: prod-issuer
cert-manager then manages the whole lifecycle: generating the private key, assembling a certificate signing request (CSR), and submitting it through origin-ca-issuer. After the Cloudflare API signs the CSR, the resulting certificate and private key are stored in the Kubernetes secret named in secretName, ready for use on any origin server proxied by Cloudflare.
If you use an Ingress controller, cert-manager's built-in Ingress support can automatically create and maintain the corresponding Certificate resources from your Ingress definitions.
apiVersion: networking/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/issuer: prod-issuer
cert-manager.io/issuer-kind: OriginIssuer
cert-manager.io/issuer-group: cert-manager.k8s.cloudflare.com
name: example
namespace: default
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: examplesvc
servicePort: 80
path: /
tls:
# specifying a host in the TLS section will tell cert-manager
# what DNS SANs should be on the created certificate.
- hosts:
- example.com
# cert-manager will create this secret
secretName: example-tls
How the External Issuer Works
An external cert-manager issuer is essentially a dedicated Kubernetes controller. cert-manager never talks directly to external issuers — this design lets you build issuers with standard controller development patterns and tooling.
origin-ca-issuer relies on the controller-runtime project and runs two reconciliation controllers.

Watching OriginIssuer Resources
The first controller watches for creation and changes to OriginIssuer custom resources. When one appears, it constructs a Cloudflare API client using the referenced credentials and account details. That client instance later handles certificate signing requests. The controller keeps retrying until client creation succeeds; at that point it updates the OriginIssuer status to ready.
Handling Certificate Requests
The second controller watches cert-manager's CertificateRequest resources, which cert-manager creates automatically during a certificate's lifecycle. The controller filters for requests that reference a known OriginIssuer — this reference is copied from the originating Certificate — and ignores everything else. It checks that the referenced issuer is ready, then converts the certificate request into a Cloudflare API call using the cached API client.
A successful response attaches the signed certificate to the CertificateRequest, which cert-manager uses to populate the target secret. Failed requests are retried on a schedule.
Getting Started
Complete installation instructions and up-to-date documentation are available in the origin-ca-issuer GitHub repository. The project welcomes feedback and contributions. If building Kubernetes controllers like this sounds interesting, Cloudflare has open roles on the team.



