How to Set Up Let's Encrypt TLS with cert-manager in Kubernetes
In this tutorial, you'll learn about How to Set Up Let's Encrypt TLS with cert. We cover key concepts, practical examples, and best practices.
The Problem
Your Kubernetes Ingress uses a self-signed certificate or no TLS at all. Browsers show NET::ERR_CERT_AUTHORITY_INVALID or Not Secure warnings. You need automated, trusted TLS certificates from Let's Encrypt.
Quick Fix
Step 1: Install cert-manager
Deploy cert-manager into your cluster:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
Wait for all pods to be ready:
kubectl get pods -n cert-manager
NAME READY STATUS RESTARTS
cert-manager-5c4b5b6d7c-abcde 1/1 Running 0
cert-manager-cainjector-6f7f8f9f8f-xyzab 1/1 Running 0
cert-manager-webhook-9c8d7e6f5-12345 1/1 Running 0
Step 2: Create a ClusterIssuer for Let's Encrypt
Define a production issuer that auto-renews certificates:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
class: nginx
Step 3: Create a test issuer for staging
Use the staging environment first to avoid rate limits:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-staging-key
solvers:
- http01:
ingress:
class: nginx
Step 4: Annotate the Ingress to request a certificate
Add TLS configuration and cert-manager annotations:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-example-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-service
port:
number: 80
Step 5: Verify the certificate
Check the certificate status:
kubectl get certificate
NAME READY SECRET AGE
app-example-tls True app-example-tls 2m
If READY is False, check the CertificateRequest:
kubectl describe certificaterequest
Alternative Solutions
Use a static TLS secret instead of cert-manager
For one-off certificates, create the secret manually:
kubectl create secret tls my-tls --cert=tls.crt --key=tls.key
Use DNS-01 challenge for wildcard certificates
Wildcard certificates require DNS-01 instead of HTTP-01:
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-token
key: api-token
Common Mistakes to Avoid
Using the staging issuer in production. Staging certificates are not trusted by browsers. Switch to the production issuer for real deployments.
Not waiting for DNS propagation. Let's Encrypt must reach your domain to validate ownership. Wait for DNS to propagate before requesting a certificate.
Hitting Let's Encrypt rate limits. The production environment limits certificates to 50 per week. Use the staging environment for testing.
Pro Tips
Monitor certificate expiry with cert-manager's status. Check kubectl get certificate -A -w to see when certificates are approaching expiry.
Use ClusterIssuer for shared issuers. A ClusterIssuer works across all namespaces, while Issuer is limited to one namespace.
Use the cert-manager approver policy for security. Approve only specific certificate requests that meet your security criteria before they are signed.
Prevention
- Use the Let's Encrypt staging issuer first to test without hitting rate limits.
- Ensure your domain DNS resolves to the Ingress load balancer before requesting certificates.
- Monitor certificate expiry with
kubectl get certificateand set up renewal alerts.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro