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.

Joel Wembo
11 min readMar 26, 2025

If you are not a medium member, here is the friendly link

How to Setup Kubernetes Ingress Nginx for Django or ReactJS on UpCloud: Multi-Domain Setup with SSL Certificates, Helm & Terraform by prodxcloud
How to Setup Kubernetes Ingress Nginx for Django or ReactJS on UpCloud: Multi-Domain Setup with SSL Certificates, Helm & Terraform.
Automating Kubernetes Ingress Nginx Controller and Cert manager for Django or ReactJS on UpCloud: Multi-Domain Setup with SSL Certificates, Helm & Terraform
Automating Kubernetes Ingress Nginx Controller and Cert manager for Django or ReactJS on UpCloud: Multi-Domain Setup with SSL Certificates, Helm & Terraform

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.

🛠️ 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

How to Set Up Your UpCloud Account: A Complete Guide

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):

  1. Log in to your domain registrar (GoDaddy, Cloudflare, etc.)
  2. Navigate to DNS Management
  3. Create A Records:
  4. HostTypeValue (LoadBalancer IP)TTLapp1A94.237.45.123300app2A94.237.45.123300

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

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

UpCloud SSL Certificate deployment using Kubernetes and Helm Ingress Controller

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.comA94.237.45.123300app2.yourdomain.comA94.237.45.123300

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
Automating Kubernetes Ingress Nginx for Django or ReactJS on UpCloud: Multi-Domain Setup with SSL Certificates, Helm & Terraform
Nginx server

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

Django In Kubernetes Load Balancer
Django In Kubernetes Load Balancer

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

How to Setup Kubernetes Ingress Nginx for Django or ReactJS on UpCloud: Multi-Domain Setup with SSL Certificates, Helm & Terraform
How to Setup Kubernetes Ingress Nginx for Django or ReactJS on UpCloud: Multi-Domain Setup with SSL Certificates, Helm & Terraform
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-tls502 Bad Gatewaykubectl logs -l app=djangoDNS 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!

--

--

Joel Wembo
Joel Wembo

Written by Joel Wembo

Cloud Solutions Architect @ prodxcloud. Expert in Django, AWS, Azure, Kubernetes, Serverless Computing & Terraform. https://www.linkedin.com/in/joelwembo

Responses (2)