How to Setup Kubernetes Ingress Nginx for Django or ReactJS on UpCloud: Multi-Domain Setup with SSL Certificates, Helm & Terraform
Learn how to deploy python Django on UpCloud Kubernetes with automated ingress nginx controller, TLS certificates, and multi-domain support using Helm and Terraform. Includes Prometheus/Grafana monitoring and CI/CD best practices.
Deploying Django applications in production requires robust infrastructure capable of handling multi-domain routing, automated TLS certificates, and scalable monitoring — without the operational overhead. This guide walks you through a complete cloud-native implementation on UpCloud’s Kubernetes service, leveraging industry-standard tools:
- Infrastructure-as-Code: Provision clusters with Terraform using UpCloud’s high-performance NVMe storage
- Zero-Config TLS: Automate Let’s Encrypt certificates for multiple domains via Cert-Manager and Helm
- Observability: Built-in Prometheus metrics and Grafana dashboards for real-time performance insights
- Django Optimization: Dockerized deployments with Gunicorn, ready for horizontal scaling
You’ll learn how to:
✅ Automate ingress routing for app1.example.com
and app2.example.com
with a single YAML file
✅ Secure traffic with auto-renewing HTTPS certificates
✅ Monitor requests/sec, error rates, and resource usage out-of-the-box
✅ Troubleshoot common issues like DNS propagation and certificate bottlenecks
Designed for DevOps engineers and full-stack developers, this tutorial provides copy-paste-ready code snippets, Terraform modules, and production-tested Helm charts — cutting deployment time from days to hours.
Table of Contents
· 🛠️ Prerequisites
· 🌐 Preface
· 🔧 Prerequisites
∘ 1. Accounts & Tools
∘ 2. Dockerize Django
· Step 1: Pre-Setup Preparation
∘ 1.1 Account & Cluster Setup
∘ 1.2 Domain Configuration
· Why This Matters
· Step 2: Terraform Setup for UpCloud Infrastructure
∘ 2.1 Configure Terraform for UpCloud
∘ 2.2 Initialize & Apply
· Step 3: Helm Setup for Ingress & Cert-Manager
∘ 3.1 Install NGINX Ingress Controller
∘ 3.2 Install Cert-Manager (Let’s Encrypt)
∘ Step 3.3: Configure Let’s Encrypt ClusterIssuer
∘ 💡 Critical Checks If Certificates Fail
· Step 4: Configure DNS & TLS
∘ 4.1 Get LoadBalancer IP
∘ 4.2 Create DNS Records
∘ Complete Automation Script for Kubernetes Ingress & TLS on UpCloud
· Step 5: Deploy Django with Multi-Domain Ingress
∘ 5.1 Django Deployment
∘ 5.2 Multi-Domain Ingress
· Step 6: Monitoring Stack
· 🚨 Troubleshooting
· 🎯 Conclusion
🛠️ Prerequisites
Before starting, ensure you have:
✅ UpCloud account (Sign up here)
✅ upctl
CLI installed (UpCloud’s official CLI)
✅ kubectl
and helm
configured
✅ Basic familiarity with Kubernetes concepts
Source code : https://github.com/prodxcloud/fullstack-devops-cloud-ai-complete-handbook/
🌐 Preface
Why This Guide?
Traditional Django deployments struggle with scaling and SSL management. This tutorial solves:
✅ Multi-domain routing without manual Nginx configs
✅ Auto-renewing TLS via Let’s Encrypt
✅ Infrastructure-as-Code with Terraform
✅ Enterprise monitoring out-of-the-box
Tools Used:
- UpCloud Kubernetes
- Helm (Cert-Manager, NGINX Ingress)
- Terraform
- Prometheus/Grafana
🔧 Prerequisites
1. Accounts & Tools
- UpCloud account (Get $50 free credits)
- Domain access (registrar or UpCloud DNS)
- Installed:
kubectl, helm, terraform, docker, git
2. Dockerize Django
Example Dockerfile
:
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "core.wsgi"]
Build and push:
docker build -t yourusername/django-app:latest .
docker push yourusername/django-app:latest
Step 1: Pre-Setup Preparation
1.1 Account & Cluster Setup
Before proceeding, ensure you’ve:
1️⃣ Created an UpCloud account using our Complete UpCloud Setup Guide
2️⃣ Provisioned a Kubernetes cluster by following Part 1 of this series
1.2 Domain Configuration
For each domain (e.g., app1.prodxcloud.com
, app2.prodxcloud.com
):
- Log in to your domain registrar (GoDaddy, Cloudflare, etc.)
- Navigate to DNS Management
- Create A Records:
- HostTypeValue (LoadBalancer IP)TTL
app1
A94.237.45.123
300app2
A94.237.45.123
300
Verify Propagation (Takes 5–60 mins):
dig +short app1.prodxcloud.com
# Should return your LoadBalancer IP
💡 Pro Tip: Use UpCloud’s DNS hosting for faster propagation and simplified management.
Why This Matters
✅ Smooth Onboarding: Links to your guides reduce setup friction
✅ Clear DNS Steps: Tables make multi-domain setup foolproof
✅ Actionable Verification: dig
command ensures no step is missed
Next: Proceed to Step 2: Terraform Automation
Want me to adjust the DNS instructions for a specific registrar (e.g., Cloudflare)? 😊
(Note: The LoadBalancer IP will be obtained in Step 2 after Ingress installation)
Step 2: Terraform Setup for UpCloud Infrastructure
2.1 Configure Terraform for UpCloud
# main.tf
terraform {
required_providers {
upcloud = {
source = "upcloudltd/upcloud"
version = "2.4.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
}
}
}
provider "upcloud" {
username = var.upcloud_user
password = var.upcloud_password
}
resource "upcloud_kubernetes_cluster" "django" {
name = "django-prod"
zone = "us-sjo1"
network = "10.0.1.0/24"
node_group {
name = "django-nodes"
count = 3
plan = "2xCPU-4GB"
}
}
2.2 Initialize & Apply
terraform init
terraform apply -var="upcloud_user=YOUR_EMAIL" -var="upcloud_password=YOUR_PASSWORD"
The following IP addresses belong to your username. The IP addresses are used to send and receive data to your servers through the public internet. If you want to change your Reverse DNS name, you can do so by clicking the pen icon.
Step 3: Helm Setup for Ingress & Cert-Manager
Understanding Kubernetes Ingress: Your Cluster’s Traffic Cop
What is Ingress?
Ingress is Kubernetes’ built-in solution for smart HTTP(S) traffic management. Think of it as:
- A gatekeeper that routes external web traffic to internal services
- A reverse proxy on steroids with declarative configuration
- The missing link between your cloud LoadBalancer and microservices
Key Capabilities
🔹 Host-based routing: Direct blog.yourdomain.com
and api.yourdomain.com
to different services
🔹 Path routing: Send /admin
and /static
to separate backends
🔹 TLS termination: Handle SSL certificates centrally
🔹 Load balancing: Distribute traffic across pods
How It Works
Ingress vs. Services
When to Use It
✅ Exposing web applications
✅ Managing multiple domains/subdomains
✅ Centralizing SSL management
❌ Non-HTTP traffic (use NodePort/LoadBalancer instead)
3.1 Install NGINX Ingress Controller
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--set controller.service.type=LoadBalancer \
--set controller.service.annotations."service\.beta\.kubernetes\.io/upcloud-loadbalancer-vip"="true"
3.2 Install Cert-Manager (Let’s Encrypt)
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.crds.yaml
helm repo add jetstack https://charts.jetstack.io
helm upgrade --install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.13.2
Step 3.3: Configure Let’s Encrypt ClusterIssuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: operations@prodxcloud.io
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
💡 Critical Checks If Certificates Fail
Verify Ingress Class:
kubectl get ingressclass
# Ensure 'nginx' exists and is DEFAULT
kubectl describe certificate django-tls
kubectl get pods -n cert-manager
kubectl logs -f <cert-manager-pod-name>
Certificate bundles are managed certificates that allow you to easily enable HTTPS support on the Load Balancer frontend. You can create SSL certificate bundles by providing your own certificates or we can create them for you dynamically. Learn more
Step 4: Configure DNS & TLS
4.1 Get LoadBalancer IP
kubectl get svc nginx-ingress-ingress-nginx-controller -n ingress-nginx -w
4.2 Create DNS Records
DomainTypeValueTTLapp1.yourdomain.com
A94.237.45.123
300app2.yourdomain.com
A94.237.45.123
300
Complete Automation Script for Kubernetes Ingress & TLS on UpCloud
For your convenience, here’s a ready-to-run bash script that automates the entire process of setting up NGINX Ingress and Cert-Manager with Let’s Encrypt on UpCloud Kubernetes:
#!/usr/bin/env bash
set -e # Exit immediately if any command fails
# ============================================
# 🚀 COMPLETE INGRESS + TLS AUTOMATION SCRIPT
# ============================================
# This script will:
# 1. Deploy NGINX Ingress Controller with UpCloud optimizations
# 2. Install Cert-Manager for automatic TLS certificates
# 3. Configure a test Let's Encrypt issuer
# ============================================
# =====================
# NGINX Ingress Setup
# =====================
echo "🚀 Deploying NGINX Ingress Controller for UpCloud..."
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm upgrade --install nginx-ingress ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--set controller.publishService.enabled=true \
--set controller.service.type=LoadBalancer \
--set controller.service.annotations."service\.beta\.kubernetes\.io/upcloud-loadbalancer-vip"="true" \
--set controller.config.use-forwarded-headers="true"
echo -e "\n🔍 Checking Ingress Service (Ctrl+C to exit watch mode)..."
kubectl get svc nginx-ingress-ingress-nginx-controller -n ingress-nginx -w
# =====================
# Cert-Manager Setup
# =====================
echo -e "\n🔐 Installing Cert-Manager for automated TLS certificates..."
# Install CRDs first
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.crds.yaml
# Create namespace if not exists
kubectl create namespace cert-manager || true
helm upgrade --install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.13.2 \
--set installCRDs=true \
--set prometheus.enabled=false
# =====================
# Test Configuration
# =====================
echo -e "\n🧪 Creating
Step 5: Deploy Django with Multi-Domain Ingress
5.1 Django Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: django-deployment-basic
labels:
app: django-deployment-basic
spec:
replicas: 2
selector:
matchLabels:
app: django-deployment-basic
template:
metadata:
labels:
app: django-deployment-basic
spec:
containers:
- name: django-app
image: joelwembo/prodxcloud-backend-django:latest
command: ["/bin/sh", "-c"]
args:
- |
python manage.py makemigrations
python manage.py migrate
gunicorn --bind 0.0.0.0:8585 --timeout 3600 multitenantsaas.wsgi:application
imagePullPolicy: Always
ports:
- containerPort: 8585
---
apiVersion: v1
kind: Service
metadata:
name: django-service-basic
spec:
selector:
app: django-deployment-basic
ports:
- protocol: TCP
port: 80
targetPort: 8585
type: LoadBalancer
kubectl apply -f deployment.yml
5.2 Service YAML
Define a Kubernetes Service
YAML file to expose your Django application pods to the outside world.
Here is the result of service created using yaml. we have a new load balancer for our django application
5.3 Multi-Domain Ingress Configuration
Configure your Ingress controller to use the SSL certificates managed by Cert-Manager.
Create a Kubernetes secret to store the SSL certificate and private key
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django-ingress-basic
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": {"Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:region:account:certificate/certificate-id"
alb.ingress.kubernetes.io/ssl-policy: "ELBSecurityPolicy-2016-08"
alb.ingress.kubernetes.io/group.name: "django"
alb.ingress.kubernetes.io/scheme: "internet-facing"
alb.ingress.kubernetes.io/target-type: "ip"
spec:
ingressClassName: nginx
tls:
- hosts:
- test-api.prodxcloud.io
secretName: django-tls-secret
rules:
- host: test-api.prodxcloud.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: django-service-basic
port:
number: 80
Here is the template you can use for multiple domain names with SSL certificate in ingress controller
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
rules:
- host: app1.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: django-service
port:
number: 8000
- host: app2.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: django-service
port:
number: 8000
tls:
- hosts:
- app1.yourdomain.com
- app2.yourdomain.com
secretName: django-tls
5.4.Testing
Access your Django application through your domain name (e.g., https://prodxcloud.com
).
Verify that the SSL certificate is valid and the application is accessible over HTTPS
Check for newly created ingress
kubectl get ingress
Step 6: Monitoring Stack
🚨 Troubleshooting
IssueCommandPending Certificatekubectl describe certificate django-tls
502 Bad Gatewaykubectl logs -l app=django
DNS Problemsdig +short app1.example.com
🎯 Conclusion
You’ve built a scalable Django platform with:
✔ Zero-downtime deployments
✔ Auto-renewing HTTPS
✔ Multi-domain support
✔ Production monitoring
Next Steps:
- Add CI/CD with GitHub Actions
- Configure Django static files
- Set up backup/restore
Resources:
Next
Want to share your implementation or need help scaling your monitoring? Join our DevOps community in the comments! 🚀
Thank You for Reading! 🙌
I truly appreciate your taking the time to go through this guide. If you found it helpful, please Follow, CLAP 👏, SUBSCRIBE, and share it with others who might benefit. Your support means a lot and keeps me motivated to create more useful content!
📢 Want more cloud and DevOps insights? Subscribe to my Medium for the latest updates!
About Me
I’m Joel Wembo, a Cloud Solutions Architect and DevOps Engineer at ProdxCloud, specializing in cloud infrastructure, DevOps, and high-availability solutions.
🔗 Connect with me: LinkedIn | GitHub | Twitter | Portfolio
🚀 Exclusive UpCloud Offer — Get Started with a Discount!
Looking for high-performance cloud hosting with faster speeds, better reliability, and competitive pricing? UpCloud is the perfect choice!
🎉 Sign up today and claim your special discount on your first deposit! 50€ free credits and 30 days extended trial Click here to register now!
👉 Start with a free trial and experience the difference!