Add SSL To Kubernetes Deployment
 · 2 min read
step-by-step guide to setting up HTTPS with cert-manager and Let’s Encrypt on your Kubernetes cluster using NGINX Ingress.
📘 Full Guide: Enabling HTTPS with cert-manager + Let’s Encrypt
🧱 Prerequisites
- Kubernetes cluster (e.g., Linode LKE)
 - NGINX Ingress Controller installed via Helm
 - DNS A record pointing to your domain. Mine is 
demo.zemo.app→ your LoadBalancer IP - Helm installed and configured
 
1️⃣ Install cert-manager
kubectl create namespace cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
Verify:
kubectl get pods -n cert-manager
2️⃣ Create a ClusterIssuer
Create k8s/clusterissuer.yaml:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: your-email@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx
Apply:
kubectl apply -f k8s/clusterissuer.yaml
3️⃣ Patch NGINX Config to Allow ACME Challenge
A. Confirm NGINX is installed via Helm
helm list -n default
B. Patch the ConfigMap
kubectl patch configmap ingress-nginx-controller -n default \
  --type merge \
  -p '{"data":{"strict-validate-path-type":"false"}}'
Restart the controller:
kubectl rollout restart deployment ingress-nginx-controller -n default
4️⃣ Disable NGINX Admission Webhook (if blocking cert-manager)
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace default \
  --set controller.admissionWebhooks.enabled=false
Confirm webhook is removed:
kubectl get validatingwebhookconfiguration
5️⃣ Create Your Ingress Resource
Create k8s/ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: zemo-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    cert-manager.io/http01-edit-in-place: "true"
spec:
  ingressClassName: nginx
  rules:
    - host: demo.zemo.app
      http:
        paths:
          - path: /health
            pathType: Prefix
            backend:
              service:
                name: zemo-app-service
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: zemo-app-service
                port:
                  number: 80
  tls:
    - hosts:
        - demo.zemo.app
      secretName: zemo-app-tls
Apply:
kubectl apply -f k8s/ingress.yaml
6️⃣ Monitor Certificate Issuance
Check certificate status:
kubectl get certificate
kubectl describe certificate zemo-app-tls
Check challenge:
kubectl get challenge
kubectl describe challenge <name>
7️⃣ Final Steps
Once the certificate is issued (READY: True):
- Remove 
ssl-redirect: "false"from annotations - Optionally add:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true" 
Reapply Ingress:
kubectl apply -f k8s/ingress.yaml
Visit:
https://demo.zemo.app
🧠 Optional Enhancements
- Use staging issuer for testing:
server: https://acme-staging-v02.api.letsencrypt.org/directory - Add 
cert-manager.io/issue-temporary-certificate: "true"to serve HTTPS while waiting - Automate cert renewal and Ingress updates via GitOps or CI/CD