Skip to main content

Set up a Let's Encrypt ClusterIssuer

Inspect 1.36

A Let's Encrypt ClusterIssuer enables cert-manager to obtain free, trusted certificates for every ingress in the cluster. Let's Encrypt is a free certificate authority. cert-manager communicates with it over a protocol called ACME, which proves you control a domain before Let's Encrypt signs a certificate for it. You create the issuer once, annotate an Ingress, and cert-manager handles the rest. This assumes .

Start on staging#

Let's Encrypt rate-limits how many certificates you can request for a domain, and a misconfigured issuer can exhaust that limit quickly. Use the staging endpoint 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.

A certificate at the edge is one layer of the cluster's . Once the Secret exists, the ingress uses it to , and cert-manager renews it before it expires without requiring you to track the date.

Where to go next#