Set up a Let's Encrypt ClusterIssuer
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 cert-manager is installed .
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.
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.
solvers:
- http01:
ingress:
ingressClassName: nginx
HTTP-01 cannot issue wildcard certificates.
DNS-01 proves control by writing a TXT record to your zone, so it works even when the host is not reachable over HTTP, and it is the only challenge that can issue a wildcard (*.example.com). Provide cert-manager with a scoped API token for your DNS provider:
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: token
To avoid granting cert-manager access to your entire zone, delegate the _acme-challenge record to a separate zone with a CNAME and set cnameStrategy: Follow on the solver. For wildcard and multi-host certificates and the CNAME delegation setup, see Multi-domain and wildcard certificates .
Issue a certificate
Point an Ingress at the issuer with an annotation, and name the Secret that cert-manager should populate:
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.