Deploying NGINX Ingress with HTTPS on Kubernetes: The Complete Guide
Complete step-by-step guide to deploy NGINX Ingress Controller with Let's Encrypt TLS certificates on Kubernetes using Helm, kubectl & cert-manager
Quick Navigation
Difficulty: 🟡 Intermediate
Estimated Time: 30-45 minutes
Prerequisites: Basic Kubernetes knowledge, kubectl experience, Helm familiarity, Understanding of Ingress resources
What You'll Learn
This tutorial covers essential Kubernetes NGINX Ingress concepts and tools:
- NGINX Ingress Controller - Installation and configuration with Helm
- TLS Certificate Management - Let's Encrypt integration with cert-manager
- Ingress Resource Configuration - HTTP and HTTPS routing setup
- Security Best Practices - Production-ready HTTPS configuration
- Testing and Validation - Verification of secure connections
- Troubleshooting - Common issues and debugging techniques
Prerequisites
- Basic Kubernetes knowledge and cluster administration experience
- kubectl command-line tool experience
- Helm package manager familiarity
- Understanding of Ingress resources and networking concepts
Related Tutorials
- HPA Autoscaling - Scale your applications automatically
- Metrics Server - Monitor cluster performance
- VPA vs HPA - Choose the right autoscaling strategy
- Main Tutorials Hub - Step-by-step implementation guides
Introduction
Kubernetes Ingress is the gateway to your services, enabling controlled access from the outside world. When combined with NGINX Ingress Controller and Let's Encrypt TLS certificates, it becomes a secure, production-ready solution.
This comprehensive guide walks you through installing the NGINX Ingress Controller, setting up a sample NGINX backend, exposing it to the internet, adding HTTPS using Let's Encrypt, and testing with curl.
Whether you're on cloud, Minikube, or bare-metal, this tutorial has got you covered!
Step-by-Step Installation
Step 1: Install the NGINX Ingress Controller
Option 1: With Helm (Recommended)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace
Verify Installation
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
Step 2: Deploy a Sample NGINX Backend (Optional for Testing)
kubectl create deployment nginx-backend --image=nginx
kubectl expose deployment nginx-backend --port=80 --target-port=80 --name=nginx-backend
Step 3: Create a Basic Ingress Resource
Create a file named nginx-ingress.yaml
:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-backend-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: hello-world.example # replace with actual domain
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-backend
port:
number: 80
Apply the Ingress
kubectl apply -f nginx-ingress.yaml
Step 4: Expose It to the World (For Single Node Deployment)
Change ingress type from LoadBalancer to NodePort:
kubectl edit svc -n ingress-nginx
Get Your External IP
Create a script to fetch the service URL:
#!/bin/bash
# Set namespace and service variables
NAMESPACE="ingress-nginx"
SERVICE="ingress-nginx-controller"
# Fetch the NodePort and handle any potential errors
NODE_PORT=$(kubectl get --namespace $NAMESPACE -o jsonpath="{.spec.ports[0].nodePort}" services $SERVICE 2>/dev/null)
if [ -z "$NODE_PORT" ]; then
echo "Error: Unable to fetch the NodePort for service '$SERVICE' in namespace '$NAMESPACE'."
exit 1
fi
# Fetch the Node IP and handle any potential errors
NODE_IP=$(kubectl get nodes --namespace $NAMESPACE -o jsonpath="{.items[0].status.addresses[0].address}" 2>/dev/null)
if [ -z "$NODE_IP" ]; then
echo "Error: Unable to fetch the Node IP in namespace '$NAMESPACE'."
exit 1
fi
# Display the URL
URL="http://$NODE_IP:$NODE_PORT"
echo "Service URL: $URL"
Example Output: Service URL: http://10.9.15.138:30810
Step 5: Test with cURL
curl -H "Host: hello-world.example" http://10.9.15.138:30810
You should see the default NGINX Welcome Page.
Step 6: Enable HTTPS with Let's Encrypt & cert-manager
Install cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--set installCRDs=true
Verify cert-manager Installation
kubectl get pods -n cert-manager
Step 7: Create a ClusterIssuer (Staging)
Create a file named cluster-issuer-staging.yaml
:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
email: your-email@example.com
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-staging-key
solvers:
- http01:
ingress:
class: nginx
Apply the ClusterIssuer:
kubectl apply -f cluster-issuer-staging.yaml
Step 8: Update Your Ingress for HTTPS
Create a file named nginx-ingress-tls.yaml
:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-backend-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-staging
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
tls:
- hosts:
- hello-world.example # replace with actual domain
secretName: nginx-backend-tls
rules:
- host: hello-world.example # replace with actual domain
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-backend
port:
number: 80
Apply the updated Ingress:
kubectl apply -f nginx-ingress-tls.yaml
Check Certificate Status
kubectl describe certificate -A
Expected Output:
Name: nginx-backend-tls
Namespace: fast-api-app
Labels: <none>
Annotations: <none>
API Version: cert-manager.io/v1
Kind: Certificate
Metadata:
Creation Timestamp: 2025-05-20T19:40:37Z
Generation: 1
Owner References:
API Version: networking.k8s.io/v1
Block Owner Deletion: true
Controller: true
Kind: Ingress
Step 9: Test HTTPS with cURL
curl -k -H "Host: hello-world.example" https://10.9.15.138:32243
Use curl https://$HOST
(without -k
) after switching to production issuer.
Step 10: Switch to Let's Encrypt Production
Create a file named cluster-issuer-prod.yaml
:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: your-email@example.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
class: nginx
Apply the production ClusterIssuer:
kubectl apply -f cluster-issuer-prod.yaml
Update Your Ingress Annotation
Change the annotation in your Ingress to:
cert-manager.io/cluster-issuer: letsencrypt-prod
Re-apply to enable real TLS.
Conclusion
You're now running a fully secure, internet-accessible, NGINX-backed service on Kubernetes using Ingress + Let's Encrypt!
Whether it's for dev or prod, this setup gives you a rock-solid foundation.
Key Takeaways
- Secure Gateway - NGINX Ingress Controller with TLS encryption
- Automated Certificates - Let's Encrypt integration with cert-manager
- Production Ready - Staging to production certificate workflow
- Easy Testing - Simple verification with curl commands
- Flexible Configuration - Works across different cluster types
Next Steps
- Test your HTTPS setup with the provided commands
- Configure custom domains for your services
- Implement security headers and additional security measures
- Set up monitoring for your ingress traffic
- Explore advanced features like rate limiting and authentication
Troubleshooting
Common Issues
- Certificate Not Issued: Check cert-manager logs and ClusterIssuer status
- Ingress Not Working: Verify NGINX Ingress Controller pods are running
- TLS Handshake Failures: Ensure proper hostname resolution and certificate validation
Debug Commands
# Check cert-manager status
kubectl get pods -n cert-manager
kubectl logs -n cert-manager deployment/cert-manager
# Check Ingress status
kubectl describe ingress nginx-backend-ingress
kubectl get events --sort-by='.lastTimestamp'
# Verify TLS secret
kubectl get secret nginx-backend-tls -o yaml
Next Steps
- Production Hardening: Configure resource limits and security policies
- Monitoring: Set up Prometheus and Grafana for Ingress metrics
- Automation: Create Helm charts for repeatable deployments
- Advanced Config: Explore NGINX Ingress annotations and custom configurations
Related Tutorials
- HPA Autoscaling - Scale your applications automatically
- Metrics Server - Monitor cluster performance
- VPA vs HPA - Choose the right autoscaling strategy
External Resources
- NGINX Ingress Controller Documentation
- cert-manager Documentation
- Let's Encrypt Documentation
- Kubernetes Ingress Documentation
Tags: #Kubernetes #NGINXIngress #LetsEncrypt #certmanager #CloudNative #DevOps #Minikube #K3s #KubernetesIngress #TLS #HTTPS #nipio #k8s #Helm #Networking