SSL certificate maximum validity is being reduced to 200 days from March 2026. Read more →

Kubernetes: cert-manager with FairSSL ACME

cert-manager is the native ACME client for Kubernetes. It runs as a controller in the cluster, creates TLS Secrets automatically and keeps certificates renewed via ARI. With FairSSL as the ACME issuer we use External Account Binding (EAB) and AutoDNS so the solver does not need DNS API keys.

Setup

The guide assumes cert-manager is already installed in the cluster (Helm chart or static manifest). If not, follow the cert-manager installation first. Use v1.18 or later for ARI support.

Step 1: Create the EAB secret

Grab the EAB KID and HMAC key from the ACME tab in your FairSSL control panel and create a Kubernetes Secret in the cert-manager namespace.

kubectl create secret generic fairssl-eab-secret \
  --namespace cert-manager \
  --from-literal=secret=YOUR_EAB_HMAC

Step 2: Create the ClusterIssuer

ClusterIssuer is reachable from every namespace. Save as fairssl-issuer.yaml and apply.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: fairssl-acme-issuer
spec:
  acme:
    email: acme-client@fairssl.dk
    server: https://fairssl.dk/acme
    privateKeySecretRef:
      name: fairssl-acme-account-key
    externalAccountBinding:
      keyID: YOUR_EAB_KID
      keySecretRef:
        name: fairssl-eab-secret
        key: secret
    solvers:
    - http01:
        ingress:
          ingressClassName: nginx
kubectl apply -f fairssl-issuer.yaml

Step 3: Configure FairSSL AutoDNS

Make sure every domain you request a certificate for has a CNAME for _dnsauth.<domain> pointing at the FairSSL DNS server in the AutoDNS menu. One-time setup per domain. Even though we use the HTTP-01 solver in Kubernetes, AutoDNS ensures renewals keep working without manual intervention if the Ingress path is temporarily unreachable.

Step 4: Request a certificate

Create a Certificate object that references the ClusterIssuer. cert-manager creates a TLS Secret with the name in secretName automatically, which your Deployments and Ingresses can use.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: www-example-com
  namespace: default
spec:
  secretName: www-example-com-tls
  issuerRef:
    name: fairssl-acme-issuer
    kind: ClusterIssuer
  commonName: www.example.com
  dnsNames:
  - www.example.com
  - example.com

Step 5: Verify and debug

kubectl describe clusterissuer fairssl-acme-issuer
kubectl get certificate www-example-com -n default
kubectl describe certificate www-example-com -n default
kubectl get challenges -A

When the status reads Ready: True, www-example-com-tls holds the certificate and private key, ready to be mounted by your Deployment or referenced by an Ingress. Verify the public certificate with FairSSL\'s SSL scanner.

Frequently asked questions

Find answers to the most common questions about SSL certificates and FairSSL.

cert-manager is a native Kubernetes controller. It issues TLS Secrets as regular Kubernetes objects, so Deployments, Services and Ingresses can reference the certificate without knowing anything about ACME. It is the recommended approach for clusters and replaces ad hoc external-client setups that push PEM files in.
It depends on which solver you choose, and you have two options. With HTTP-01 (via an Ingress) you do need port 80 open from the internet to the Ingress controller that serves the challenge path. With DNS-01 you need no inbound port at all: using FairSSL AutoDNS you set one permanent CNAME per domain, cert-manager places the challenge and FairSSL answers it on our side, so nothing has to be exposed on port 80. For clusters where you would rather not open port 80, DNS-01 with AutoDNS is the recommended path.
From cert-manager v1.18 ACME Renewal Information (ARI) is supported by default. This means the certificate renews when FairSSL recommends it, not on a fixed schedule. If you run an older version, upgrade. ARI matters most for 47-day certificates and for getting early renewal on revocation events.
Yes, use a ClusterIssuer (as our example does) instead of a namespace-bound Issuer. ClusterIssuer is reachable from every namespace.
In the same namespace as cert-manager (usually cert-manager). The ClusterIssuer references the secret via keySecretRef.name. If cert-manager cannot find it, have a cert-manager admin confirm the location with kubectl get secret -n cert-manager.
cert-manager creates an Order which creates a Challenge. Inspect them with kubectl describe certificate <name> and kubectl get challenges -A. The most common issues are the Ingress controller not routing /.well-known/acme-challenge/ to the cert-manager solver, or AutoDNS not configured correctly for the domain.

Ready to automate certificates in Kubernetes?

Create a free account and issue your first certificate in under 10 minutes.