Skip to main content

Set up a Let's Encrypt ClusterIssuer

Inspect 1.36

Let's Encrypt's ClusterIssuer enables cert-manager to automatically request, validate, and renew publicly trusted TLS certificates across every namespace in your cluster. Using the Automated Certificate Management Environment (ACME) protocol, cert-manager verifies domain ownership with Let's Encrypt before issuing certificates into Kubernetes Secrets. Once configured, you simply annotate an Ingress or Certificate resource, and cert-manager manages the full certificate lifecycle. This guide assumes .

Start on Let's Encrypt's staging server

Let's Encrypt rate-limits how many certificates you can request for a domain on the production environment, and a misconfigured issuer can exhaust that limit quickly. Use the staging environment until the flow works end to end, then switch to production. Staging certificates are not trusted by browsers, which is precisely why they are safe to iterate against.

clusterissuer-staging.yamlyaml
		apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: you@example.com
    privateKeySecretRef:
      name: letsencrypt-staging-account
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx
	

Switch the server to https://acme-v02.api.letsencrypt.org/directory and rename the issuer to letsencrypt-prod once staging issues certificates cleanly.

Prove domain control: HTTP-01 or DNS-01

Before Let's Encrypt signs a certificate, ACME requires cert-manager to prove you control the domain. It runs one of two challenge types, and the one you choose determines whether you can issue wildcards.

HTTP-01 proves control by serving a token over HTTP through your ingress. It works for any host that already points to your load balancer and requires no DNS credentials. cert-manager adds a temporary ingress path for the challenge and removes it afterward. This is the http01 solver in the staging issuer above.

yaml
		solvers:
  - http01:
      ingress:
        ingressClassName: nginx
	

HTTP-01 cannot issue wildcard certificates.

Issue a certificate

Point an Ingress at the issuer with an annotation, and name the Secret that cert-manager should populate:

yaml
		metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts: [app.example.com]
      secretName: app-example-com-tls
	

Verify

cert-manager creates a Certificate object and, once the challenge passes, writes the Secret:

		$ kubectl get certificate
NAME                  READY   SECRET
app-example-com-tls   True    app-example-com-tls
$ kubectl describe certificate app-example-com-tls
	

READY: True means the certificate is issued and the ingress can serve HTTPS. If it remains False, the events on the Certificate and the Order/Challenge objects show which step failed, usually a DNS record that has not yet propagated or a challenge that could not reach the ingress.

Where to go next