Site icon Codanics

AI Agents from Idea to Live Product: Build a Two-App Django Website and Deploy It on Hostinger

AI agents · Django · Hostinger VPS

AI Agents from Idea to Live Product: Build a Two-App Django Website and Deploy It on Hostinger

Follow the 18-day journey from a business model canvas to working AI agents, then take the next step: put two apps on one Django website, run it on a Hostinger KVM VPS with your own domain and free HTTPS, and share it with the world.

Subscribe on YouTube
The short answer

Plan the business first, design the screens, build a prototype, add AI agents, control costs, then deploy. For deployment, put both apps in one Django project (for example /agent/ and /analytics/), run it with Gunicorn behind Nginx on a Hostinger KVM VPS running Ubuntu, point your domain’s A records to the VPS’s public IP, and add free HTTPS with Certbot. KVM 2 is a comfortable plan for a first product; KVM 1 is enough to learn.

Buying a Hostinger KVM VPS? Use my referral link to get an extra 20% discount on your plan at checkout.Disclosure: this is my referral link. You get the discount, and I may earn a small commission at no extra cost to you.
Get 20% off Hostinger →
18video lessons from idea to deployment
2Django apps on one domain
KVM 2recommended plan for a first product
FreeHTTPS certificate with Let’s Encrypt
Key facts: deploying an AI agent website on Hostinger
What you buildOne Django project with two apps: an AI assistant at /agent/ and a CSV analytics app at /analytics/
ServerHostinger KVM VPS with Ubuntu 24.04 LTS (KVM 2 recommended, KVM 1 to learn)
Software stackPython, Django, Gunicorn, Nginx, systemd, Certbot
DomainTwo DNS A records (@ and www) pointing to the VPS’s public IP
HTTPSFree Let’s Encrypt certificate with automatic renewal
Time neededAbout 1–2 hours the first time, a minute for later updates
Running costVPS from about $6.49/month on promotion, plus LLM API usage
Want the full path, with live classes and mentorship?This guide is part of Python ka Chilla: Build AI Agents, my course that takes you from Python basics to building and shipping your own AI agents.
Explore the course →

Most students I meet can follow a tutorial and build an AI agent in a notebook. Far fewer can answer the questions that come after: who will pay for it, what should the screen look like, how much will the API cost, and how do I put it on the internet with my own domain? That gap, between “it works on my laptop” and “people use it”, is where most AI projects quietly die.

So I recorded an 18-day series that goes through the whole journey with one real product, the Datajin data analytics app: business model, design, prototype, AI agents, costs, subscriptions and deployment. This guide brings that series together in one place, and then adds the step that students ask me about most: how to build a website with two apps in Django and run it on a Hostinger VPS, with a domain and HTTPS, using a complete example you can copy.

If you are new to Python or AI, start with the free AI and data science roadmap. If you want structured lessons, live help and a community, join Python ka Chilla: Build AI Agents.

Section 1

How do you go from an idea to a working AI product? The 18-day journey

Quick answer

Work in six phases: plan the business (Business Model Canvas), design the user experience (personas, wireframes, UI elements), build a prototype with Claude Code, add AI agents with Python and LangGraph, make the numbers work (LLM costs and subscriptions), and deploy. The playlist covers each phase with one real product, the Datajin data analytics app.

Here is the whole series, grouped by phase. Each lesson is in Urdu/Hindi with practical screens and code. You can also open the full playlist on YouTube.

  1. Day 1PlanBusiness Model Canvas
  2. Days 2–6DesignUI/UX, personas, wireframes
  3. Days 7–8PrototypeBuilt with Claude Code
  4. Days 9–14AI agentsPython, LangGraph, agent teams
  5. Days 15–18Business & shipCosts, subscriptions, deployment
Phase 1 · Day 1

Plan the business

Every product starts as a business question: who pays, for what, and why. On Day 1 we turn a raw idea into a Business Model Canvas and set up the tools: Python, VS Code and Claude Code.

Lesson · 1:20:16
Day-1: Product Development Using Claude Code & Python | Idea to Business Model Canvas. From a raw idea to a Business Model Canvas, plus the developer setup.
Phase 2 · Days 2–6

Design what users will see

Before writing code we design: UI and UX principles, user personas, wireframes and the components users expect. This is the cheapest place to fix mistakes.

Lesson · 37:00
Day-2: UI & UX Design for AI Products using Claude Code. Why UI and UX decide whether people use an AI product.
Lesson · 1:12:05
Day-3: Product Development A-Z | UI/UX Design Do's & Don'ts (Urdu/Hindi). The full UI/UX flow of a real startup idea, with dos and don’ts.
Lesson · 40:25
Day-4: User Personas, UI/UX Elements & Wireframing Tools (Urdu/Hindi). User personas and the best wireframing tools.
Lesson · 1:16:10
Day-5: Build Better AI Apps with Wireframes. Wireframes: the blueprint that saves weeks of coding.
Lesson · 1:22:05
Day-6: Essential UI/UX Elements & Components. The buttons, forms and navigation users expect.
Phase 3 · Days 7–8

Build the prototype

With designs ready, Claude Code helps us turn them into a working prototype, which we then test live.

Lesson · 1:10:25
Day-7: Build an App Prototype with Claude Code. Designs become a working prototype with Claude Code.
Lesson · 11:14
Day-8: Our App Prototype is Ready with Claude Code. Live testing of the first prototype.
Phase 4 · Days 9–14

Add AI agents

The prototype becomes smart: what agents are, how to build one in plain Python, then a stateful agent with LangGraph, eleven example agents, and finally a team of four agents inside the Datajin data analytics app.

Lesson · 1:42:15
Day-9: Use of AI Agents in Data Analytics App. How AI agents read, clean and analyse data inside an app.
Lesson · 1:07:20
Day-10: How to Build an AI Agent in Python & Claude Code. Your first autonomous agent in plain Python.
Lesson · 1:16:50
Day-11: Build an AI Agent A-Z with Python & LangGraph. A complete stateful agent with LangGraph.
Lesson · 21:45
Day 12: AI Agent Ideas to Earn Millions | Era of Agentic AI. Agent ideas with real business potential.
Lesson · 33:37
Day-13: Eleven AI Agents Built with LangGraph (Source Code). Eleven LangGraph agents with source code.
Lesson · 39:39
Day-14: 4 AI Agents Team Integrated in Datajin App. A team of four agents working inside Datajin.
Phase 5 · Days 15–16

Make it a business

Two short but important lessons: control your LLM costs, and charge users a subscription instead of asking for their API keys.

Short lesson · 3:17
Day-15: Cost Balancing for LLMs in AI Apps. Keep your LLM bill under control.
Short lesson · 2:40
Day-16: Collect Subscriptions Instead of API Keys. Charge subscriptions instead of asking for API keys.
Phase 6 · Days 17–18

Ship it

Five more ready-made research agents with source code, and the full journey from development to deployment with a live example.

Lesson · 30:04
Day-17: Top 5 AI Agents Built in Python (Source Code & Materials). Five research agents, with a free book and GitHub code.
Lesson · 1:02:47
Day-18: AI Agent Development to Deployment A-Z (Live Example). From local agent code to a live product.
Get the code: the Day-17 agents come with a free online book, Five Research AI Agents, and a GitHub repository. Day 18 ends with an agent running in the cloud. The rest of this guide is the next step: your own website, your own server, your own domain.
Key takeaways
  • Business model and design come before code.
  • Build a prototype first, then add agents.
  • Plan costs and subscriptions before launch, not after.

↑ Back to topNext: Python ka Chilla: Build AI Agents →

Section 2

Want to learn all of this step by step? Python ka Chilla: Build AI Agents

Quick answer

Python ka Chilla: Build AI Agents is my course on Codanics. It starts from Python basics and goes through AI, LLMs, RAG, prompt engineering, local models, data analysis and machine learning, to building agentic AI projects with Claude Code, with live Zoom classes and a Discord community.

Python ka Chilla: Build AI AgentsFrom your first line of Python to AI agents you can sell, taught in Urdu/Hindi by Dr. Aammar Tufail.
  • Python from scratch: setup, VS Code, GitHub, Copilot, core data types and control flow
  • AI, generative AI, LLMs, RAG and CAG, and what makes AI “agentic”
  • Prompt engineering, context, tools, RAG vs skills vs MCP, and loop engineering
  • Online and local LLMs (Ollama), and choosing the right model and subscription
  • Data gathering, cleaning, visualisation and machine learning crash courses
  • Claude Code and agentic AI for real project development
  • Live Zoom sessions, a Discord community and weekly AI news
Enroll in Python ka Chilla →

The 18-day playlist above shows the product journey in public. The course goes deeper, with assignments, troubleshooting help and the foundations you need to build your own agents instead of only copying mine.

↑ Back to topNext: The example: one Django website, two apps →

Section 3

The example: what are we building and deploying?

Quick answer

A Django website called AgentSite with two apps under one domain: an AI Assistant at yourdomain.com/agent/ that answers questions with an LLM, and a Data Analytics app at yourdomain.com/analytics/ that summarises an uploaded CSV with pandas. Both run in one Django project, served by Gunicorn behind Nginx on a Hostinger KVM VPS, with HTTPS from Let’s Encrypt.

Why two apps in one project? In Django, a project is the website and an app is one feature with its own views, URLs and templates. Putting several apps in one project means one server process, one database, one login system and one domain, which is exactly how most real SaaS products start. Later you can replace the simple assistant with your LangGraph agents from Days 11–14 without touching the deployment.

Visitor’s browser→yourdomain.com (DNS A record)→Hostinger VPS public IP→Nginx :443 (HTTPS)→Gunicorn→Django: /agent/ and /analytics/
URLAppWhat it does
yourdomain.com/Home pageLinks to both apps
yourdomain.com/agent/agentAI assistant: the user asks a question, the server calls the LLM API and shows the answer
yourdomain.com/analytics/analyticsUpload a CSV, get the first rows and summary statistics with pandas
yourdomain.com/admin/Django adminManage users and data
In the examples, replace yourdomain.com with your domain and 203.0.113.10 with your VPS’s IP address (203.0.113.10 is a reserved example address).

↑ Back to topNext: Build the Django project on your laptop →

Section 4

How do you build a Django website with two apps?

Quick answer

Create one Django project, add two apps with startapp, register them in INSTALLED_APPS, include each app’s urls.py under its own path in the project’s urls.py, keep secrets in a .env file, test locally with runserver, and push the code to a private GitHub repository.

New to Django? This section assumes you know the basics: projects, apps, URLs, views and templates. If you don't, start with my free Complete Django tutorials for Beginners (Urdu/Hindi) playlist on YouTube. The short intro below explains why Django is a good framework for AI products, then come back here to build AgentSite.
Django course · 0:58
Django complete course in Urdu/Hindi. Intro to my complete Django course. Watch the full Django playlist.

Step 1: create the project and the two apps

Terminal (your laptop)
mkdir agentsite && cd agentsite
python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install django anthropic python-dotenv pandas gunicorn
django-admin startproject config .
python manage.py startapp agent
python manage.py startapp analytics
pip freeze > requirements.txt
Project structure
agentsite/
├── config/              # project settings and main urls.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── agent/               # App 1: AI assistant (your agent lives here)
│   ├── services.py
│   ├── urls.py
│   └── views.py
├── analytics/           # App 2: CSV data analytics
│   ├── urls.py
│   └── views.py
├── templates/
│   ├── base.html
│   ├── home.html
│   ├── agent/chat.html
│   └── analytics/upload.html
├── .env                 # secrets, never commit this
├── .gitignore
├── manage.py
└── requirements.txt

Step 2: settings that are ready for production

Read every secret and server-specific value from environment variables. That way the same code runs on your laptop and on the VPS, and your API key never goes to GitHub.

config/settings.py
# config/settings.py (only the parts you change)
import os
from pathlib import Path
from dotenv import load_dotenv

BASE_DIR = Path(__file__).resolve().parent.parent
load_dotenv(BASE_DIR / ".env")

SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
DEBUG = os.getenv("DJANGO_DEBUG", "False") == "True"
ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "127.0.0.1,localhost").split(",")
CSRF_TRUSTED_ORIGINS = [f"https://{h}" for h in ALLOWED_HOSTS if "." in h and not h[0].isdigit()]

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "agent",        # App 1
    "analytics",    # App 2
]

TEMPLATES[0]["DIRS"] = [BASE_DIR / "templates"]

STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"     # filled by collectstatic, served by Nginx

CLAUDE_MODEL = os.getenv("CLAUDE_MODEL", "claude-opus-5-5")

# Turn these on only after HTTPS works (Section 9)
if os.getenv("DJANGO_HTTPS", "False") == "True":
    SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
    SECURE_SSL_REDIRECT = True
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True
    SECURE_HSTS_SECONDS = 3600

Step 3: one domain, two apps (URL routing)

config/urls.py
# config/urls.py: one domain, two apps
from django.contrib import admin
from django.urls import include, path
from django.views.generic import TemplateView

urlpatterns = [
    path("", TemplateView.as_view(template_name="home.html"), name="home"),
    path("agent/", include("agent.urls")),          # yourdomain.com/agent/
    path("analytics/", include("analytics.urls")),  # yourdomain.com/analytics/
    path("admin/", admin.site.urls),
]
agent/urls.py and analytics/urls.py
# agent/urls.py
from django.urls import path
from . import views

app_name = "agent"
urlpatterns = [path("", views.chat, name="chat")]


# analytics/urls.py
from django.urls import path
from . import views

app_name = "analytics"
urlpatterns = [path("", views.upload, name="upload")]

Step 4: App 1, the AI assistant

Keep the AI logic in its own file. Today it is a single call to Claude through the official Anthropic Python SDK; tomorrow you can swap in a LangGraph agent with tools, memory and a team of sub-agents, and the rest of the site stays the same. The code handles rate limits, API errors and declined requests so the page never crashes.

agent/services.py
# agent/services.py: the AI part of App 1
# Replace ask_agent() with your LangGraph agent from Days 11-14 when you are ready.
import logging
import os

import anthropic
from django.conf import settings

logger = logging.getLogger(__name__)

# Reads ANTHROPIC_API_KEY from the environment.
# timeout x (max_retries + 1) = 100 s, which stays below Gunicorn's 120 s timeout,
# so a slow answer returns a friendly message instead of a 502 error.
client = anthropic.Anthropic(timeout=50.0, max_retries=1)

SYSTEM_PROMPT = (
    "You are a helpful research assistant for students. "
    "Answer clearly and briefly. If you are not sure, say so."
)

def ask_agent(question: str) -> str:
    if not os.environ.get("ANTHROPIC_API_KEY"):
        return "The AI assistant is not configured yet: ANTHROPIC_API_KEY is missing in .env."
    try:
        response = client.beta.messages.create(
            model=settings.CLAUDE_MODEL,
            max_tokens=16000,
            output_config={"effort": "low"},   # fast, cheaper answers for chat
            system=SYSTEM_PROMPT,
            messages=[{"role": "user", "content": question}],
            # If a request is declined, Anthropic retries it on a suitable fallback model
            betas=["server-side-fallback-2026-07-01"],
            fallbacks="default",
        )
    except anthropic.RateLimitError:
        return "The assistant is busy right now. Please try again in a minute."
    except anthropic.APIStatusError as e:
        logger.warning("Claude API error %s: %s", e.status_code, e.message)
        return f"The AI service returned an error ({e.status_code}). Please try again later."
    except anthropic.APIConnectionError:  # includes timeouts
        logger.warning("Claude API connection error or timeout")
        return "The AI service did not respond in time. Please try again."

    if response.stop_reason == "refusal":
        return "Sorry, I can't help with that request."
    return "".join(block.text for block in response.content if block.type == "text")
agent/views.py
# agent/views.py
from django.shortcuts import render
from .services import ask_agent

def chat(request):
    question, answer = "", None
    if request.method == "POST":
        question = request.POST.get("question", "").strip()[:2000]
        if question:
            answer = ask_agent(question)
    return render(request, "agent/chat.html", {"question": question, "answer": answer})
Cost control: every question costs API tokens. Before you share the link publicly, add a login (Django has one built in) or a daily limit per user, as explained in the Day-15 cost balancing and Day-16 subscriptions lessons.

Step 5: App 2, the data analytics app

A small taste of Datajin: upload a CSV and get a preview and summary statistics. If pandas is new to you, my pandas mastery guide covers everything used here.

analytics/views.py
# analytics/views.py
import pandas as pd
from django.shortcuts import render

MAX_MB = 5

def upload(request):
    context = {}
    csv_file = request.FILES.get("csv_file")
    if request.method == "POST" and csv_file:
        if csv_file.size > MAX_MB * 1024 * 1024:
            context["error"] = f"Please upload a CSV smaller than {MAX_MB} MB."
        else:
            try:
                df = pd.read_csv(csv_file)
                context["shape"] = df.shape
                context["preview"] = df.head(10).to_html(index=False, classes="table")
                context["summary"] = df.describe(include="all").fillna("").to_html(classes="table")
            except Exception as exc:
                context["error"] = f"Could not read this file: {exc}"
    return render(request, "analytics/upload.html", context)

Step 6: templates

templates/*.html
<!-- templates/base.html -->
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{% block title %}AgentSite{% endblock %}</title>
</head>
<body style="font-family:system-ui;max-width:860px;margin:auto;padding:20px">
  <nav><a href="/">Home</a> · <a href="/agent/">AI Assistant</a> · <a href="/analytics/">Data Analytics</a></nav>
  <hr>
  {% block content %}{% endblock %}
</body>
</html>

<!-- templates/home.html -->
{% extends "base.html" %}
{% block content %}
  <h1>AgentSite</h1>
  <p>Two apps, one website:</p>
  <ul>
    <li><a href="/agent/">AI Assistant</a>: ask a research question</li>
    <li><a href="/analytics/">Data Analytics</a>: upload a CSV and get a summary</li>
  </ul>
{% endblock %}

<!-- templates/agent/chat.html -->
{% extends "base.html" %}
{% block content %}
  <h1>AI Assistant</h1>
  <form method="post">{% csrf_token %}
    <textarea name="question" rows="4" style="width:100%" required>{{ question }}</textarea>
    <button type="submit">Ask</button>
  </form>
  {% if answer %}<h3>Answer</h3><div style="white-space:pre-wrap">{{ answer }}</div>{% endif %}
{% endblock %}

<!-- templates/analytics/upload.html -->
{% extends "base.html" %}
{% block content %}
  <h1>Data Analytics</h1>
  <form method="post" enctype="multipart/form-data">{% csrf_token %}
    <input type="file" name="csv_file" accept=".csv" required>
    <button type="submit">Analyse</button>
  </form>
  {% if error %}<p style="color:#b00">{{ error }}</p>{% endif %}
  {% if shape %}
    <p>{{ shape.0 }} rows × {{ shape.1 }} columns</p>
    <h3>First 10 rows</h3>{{ preview|safe }}
    <h3>Summary statistics</h3>{{ summary|safe }}
  {% endif %}
{% endblock %}

Step 7: secrets, local test and GitHub

.env
# .env (on your laptop now, and later on the server)
DJANGO_SECRET_KEY=paste-a-long-random-string-here
DJANGO_DEBUG=True
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost
DJANGO_HTTPS=False
ANTHROPIC_API_KEY=your-anthropic-api-key
CLAUDE_MODEL=claude-opus-5-5
Terminal (your laptop)
# create a secret key
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"

python manage.py migrate
python manage.py runserver
# open http://127.0.0.1:8000, then /agent/ and /analytics/
.gitignore and first push
# .gitignore
.venv/
.env
db.sqlite3
staticfiles/
__pycache__/

# push to a PRIVATE GitHub repository
git init
git add .
git commit -m "AgentSite: Django project with agent and analytics apps"
git branch -M main
git remote add origin https://github.com/<your-username>/agentsite.git
git push -u origin main
Key takeaways
  • One project, two apps, two URL prefixes: that is all it takes to put two apps on one domain.
  • Secrets live in .env, never in Git.
  • Keep the AI logic in services.py so you can upgrade the agent later.

↑ Back to topNext: Which Hostinger KVM plan do you need? →

Section 5

Which Hostinger KVM VPS plan do you need for your audience?

Quick answer

Start with KVM 2 (2 vCPU, 8 GB RAM, 100 GB NVMe) for a first real product. KVM 1 (1 vCPU, 4 GB RAM) is enough for learning, demos and early users, because the LLM runs on the provider’s servers, not on your VPS. Choose KVM 4 for a growing SaaS with background workers and several projects, and KVM 8 for heavy traffic or experiments with small local models.

Why a VPS and not shared hosting? Shared hosting is built mainly for PHP and WordPress. Django needs a long-running Python process (Gunicorn), Nginx and your own packages, which means you need root access. A Hostinger KVM VPS gives you a full Linux server with root access and its own public IP address. Get 20% off Hostinger KVM VPS with my referral link when you buy.

KVM 1
1 vCPU · 4 GB RAM · 50 GB NVMe · 4 TB bandwidth

Learning and demos. Your portfolio, a class project, or a beta with a small group of users.

Recommended startKVM 2
2 vCPU · 8 GB RAM · 100 GB NVMe · 8 TB bandwidth

Your first real product. A launched SaaS with steady daily users, PostgreSQL and room for a second project.

KVM 4
4 vCPU · 16 GB RAM · 200 GB NVMe · 16 TB bandwidth

Growing SaaS. Background workers (Celery, Redis), Docker, several sites, heavier data processing.

KVM 8
8 vCPU · 32 GB RAM · 400 GB NVMe · 32 TB bandwidth

High traffic or local models. Many concurrent users, or small open models with Ollama (CPU only, so expect slow answers).

PlanPromo price (24-month term)Renews at
KVM 1$6.49/mo$11.99/mo
KVM 2$8.79/mo$14.99/mo
KVM 4$12.99/mo$28.99/mo
KVM 8$25.99/mo$49.99/mo

Specs and prices from Hostinger’s VPS page, checked on 6 November 2026. Prices change with promotions, currency and term length, so confirm on the Hostinger site before you buy.

Buying a Hostinger KVM VPS? Use my referral link to get an extra 20% discount on your plan at checkout.Disclosure: this is my referral link. You get the discount, and I may earn a small commission at no extra cost to you.
Get 20% off Hostinger →

What every plan includes (and what you will use)

  • Full root access: install Python, Nginx, PostgreSQL, anything you need
  • A public IP address: for SSH and for your domain’s DNS records
  • AMD EPYC CPUs and NVMe storage, with a 1 Gbps network
  • Free weekly backups and snapshots you can restore from hPanel
  • Firewall management and DDoS protection
  • Data centres on four continents: choose the one closest to your users
  • A browser terminal in hPanel, useful if SSH ever locks you out
Rule of thumb: sizing depends more on concurrent users than daily users. An AI app spends most of its time waiting for the LLM API, so RAM and Gunicorn workers matter more than raw CPU. Start smaller, watch CPU and RAM graphs in hPanel for a few weeks, and upgrade the plan when you regularly pass about 70%.

↑ Back to topNext: Start your KVM VPS →

Section 6

How do you start a Hostinger KVM VPS and find its public IP?

Quick answer

Buy a KVM plan, open the VPS setup in hPanel, choose the data centre nearest your users, select the plain Ubuntu 24.04 LTS operating system, set a strong root password and add your SSH key, then finish setup. After a few minutes the VPS Overview page shows your public IP address and the SSH command to connect.

  1. Buy the plan. Choose KVM 1 or KVM 2 and a term. Longer terms are cheaper per month. Open Hostinger with my referral link for an extra 20% off before checkout.
  2. Open the setup. In hPanel, go to VPS and click Setup (or Manage) on your new server.
  3. Pick a location. Choose the data centre closest to most of your users. Lower distance means faster pages.
  4. Choose the operating system. Pick a plain OS and select Ubuntu 24.04 LTS. Skip the control panel templates for this guide; we will set everything up ourselves, which teaches you more and keeps the server lean.
  5. Set credentials. Create a strong root password and add your SSH public key (generate one on your laptop with ssh-keygen -t ed25519).
  6. Finish and wait. Setup takes a few minutes. Then open VPS → Overview: you will see the public IP address, the SSH username (root) and a ready-made SSH command.
Two firewalls: Ubuntu has its own firewall (ufw, set up in the next section), and hPanel has a separate VPS firewall. If you turn on the hPanel firewall, add rules that allow ports 22 (SSH), 80 (HTTP) and 443 (HTTPS), or your site will not load even when everything else is correct.

↑ Back to topNext: Set up the server →

Section 7

How do you set up the server and run Django with Gunicorn and Nginx?

Quick answer

Log in over SSH with the public IP, update Ubuntu, create a non-root user, install Python, Nginx and Git, enable the ufw firewall, clone your project into a virtual environment, add the server .env, run migrations and collectstatic, then let systemd run Gunicorn on a Unix socket and let Nginx serve static files and forward requests to Gunicorn.

Step 1: first login and a safe user

Terminal (laptop → VPS as root)
# from your laptop (use the IP shown in hPanel → VPS → Overview)
ssh root@203.0.113.10

# update the server
apt update && apt upgrade -y

# create a normal user for the app and give it sudo
adduser deploy
usermod -aG sudo deploy

# if you added an SSH key in hPanel, copy it to the new user
rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy

Step 2: install packages and turn on the firewall

Terminal (VPS as root)
# install Python tools, Nginx and Git
apt install -y python3-venv python3-pip python3-dev build-essential nginx git

# firewall: allow SSH, HTTP and HTTPS only
ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw enable
ufw status

Step 3: install your project

Terminal (VPS as deploy)
# log in as the app user from now on
ssh deploy@203.0.113.10

cd ~
git clone https://github.com/<your-username>/agentsite.git
cd agentsite
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

nano .env        # paste your .env, with DEBUG=False and the server values below
/home/deploy/agentsite/.env
# /home/deploy/agentsite/.env on the server
DJANGO_SECRET_KEY=a-different-long-random-string
DJANGO_DEBUG=False
DJANGO_ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com,203.0.113.10
DJANGO_HTTPS=False
ANTHROPIC_API_KEY=your-anthropic-api-key
CLAUDE_MODEL=claude-opus-5-5
Terminal (VPS as deploy)
chmod 600 .env
python manage.py migrate
python manage.py collectstatic --noinput
python manage.py createsuperuser

# quick test on port 8000 (close it again afterwards)
sudo ufw allow 8000
gunicorn --bind 0.0.0.0:8000 config.wsgi
# open http://203.0.113.10:8000 in your browser, then press Ctrl+C
sudo ufw delete allow 8000

Step 4: run Gunicorn as a service

Gunicorn is the program that runs your Django code. systemd starts it at boot and restarts it if it crashes, so your site stays up even after a server reboot.

/etc/systemd/system/gunicorn.socket
# /etc/systemd/system/gunicorn.socket
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target
/etc/systemd/system/gunicorn.service
# /etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon for agentsite
Requires=gunicorn.socket
After=network.target

[Service]
User=deploy
Group=www-data
WorkingDirectory=/home/deploy/agentsite
ExecStart=/home/deploy/agentsite/.venv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --timeout 120 \
          --bind unix:/run/gunicorn.sock \
          config.wsgi:application
Restart=on-failure

[Install]
WantedBy=multi-user.target
Terminal (VPS)
sudo systemctl daemon-reload
sudo systemctl enable --now gunicorn.socket
sudo systemctl status gunicorn.socket

# test: this should print your home page HTML
curl --unix-socket /run/gunicorn.sock localhost
How many workers? Start with 2 × CPU cores + 1: three on KVM 1, five on KVM 2. Change --workers, then run sudo systemctl daemon-reload && sudo systemctl restart gunicorn.

Step 5: Nginx in front of Gunicorn

Nginx receives every request on ports 80 and 443, serves CSS and images directly from staticfiles/, and passes everything else to Gunicorn. Because both apps live in one Django project, a single Nginx block serves /agent/, /analytics/ and every other path.

/etc/nginx/sites-available/agentsite
# /etc/nginx/sites-available/agentsite
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    client_max_body_size 10M;          # allow CSV uploads up to 10 MB

    location = /favicon.ico { access_log off; log_not_found off; }

    location /static/ {
        alias /home/deploy/agentsite/staticfiles/;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
        proxy_read_timeout 120s;       # AI answers can take a while
    }
}
Terminal (VPS)
sudo ln -s /etc/nginx/sites-available/agentsite /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo chmod 755 /home/deploy          # lets Nginx read the static files
sudo nginx -t
sudo systemctl restart nginx

Open http://203.0.113.10 in your browser. You should see the AgentSite home page with links to both apps. If not, jump to the troubleshooting table.

Key takeaways
  • Never run the app as root: use a deploy user.
  • Gunicorn runs Django, systemd keeps Gunicorn alive, Nginx faces the internet.
  • One Nginx server block serves both apps because they share one project.

↑ Back to topNext: Connect your domain →

Section 8

How do you connect your domain to the Hostinger VPS?

Quick answer

Create two A records in your domain’s DNS zone: @ (the bare domain) and www, both pointing to the VPS’s public IP. If you bought the domain at Hostinger, do it in hPanel under Domains → DNS / Nameservers. Wait until nslookup returns your VPS IP, which usually takes minutes but can take up to 24–48 hours.

  1. Get a domain. Many Hostinger VPS plans include a free domain for the first year; otherwise buy one at Hostinger or any registrar.
  2. Open the DNS zone. At Hostinger: hPanel → Domains → your domain → DNS / Nameservers → DNS records. At another registrar, open its DNS settings.
  3. Remove old A records for @ and www that point to a parking page.
  4. Add the new records shown below, then save.
  5. Check propagation with nslookup or an online DNS checker until both names show your VPS IP.
DNS records
# DNS records (hPanel → Domains → yourdomain.com → DNS / Nameservers → DNS records)
Type   Name   Points to        TTL
A      @      203.0.113.10     3600
A      www    203.0.113.10     3600

# check from your laptop (repeat until it shows your VPS IP)
nslookup yourdomain.com
nslookup www.yourdomain.com
Domain not changing? If your domain uses another provider’s nameservers (for example Cloudflare), add the A records there, not in hPanel. The DNS zone that counts is the one at the provider your nameservers point to.

↑ Back to topNext: Add HTTPS and go live →

Section 9

How do you add HTTPS and run the app on your domain?

Quick answer

Once the domain points to the VPS, install Certbot with the Nginx plugin and run sudo certbot –nginx -d yourdomain.com -d www.yourdomain.com. Certbot gets a free Let’s Encrypt certificate, adds HTTPS to your Nginx block and renews it automatically. Then set DJANGO_HTTPS=True and restart Gunicorn so Django uses secure cookies and redirects HTTP to HTTPS.

Terminal (VPS)
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# check that automatic renewal works
sudo certbot renew --dry-run

When Certbot asks, allow it to redirect HTTP to HTTPS. Then switch on Django’s secure settings:

Terminal (VPS)
# now switch Django to HTTPS mode
nano ~/agentsite/.env          # set DJANGO_HTTPS=True
sudo systemctl restart gunicorn

Now open https://yourdomain.com. You should see the padlock, and both apps should work:

  • https://yourdomain.com/agent/: ask a question and get an AI answer
  • https://yourdomain.com/analytics/: upload a CSV and see the summary
  • https://yourdomain.com/admin/: log in with the superuser you created
  • http://yourdomain.com redirects to HTTPS automatically
Order matters: set DJANGO_HTTPS=True only after Certbot succeeds. If you turn it on earlier, Django redirects every visitor to an HTTPS address that does not exist yet, and you get a “too many redirects” or “connection refused” error.

Optional: a second, separate app on a subdomain

Sometimes the second app is not a Django app, for example a Streamlit dashboard or a FastAPI service for your agents. Run it on the same VPS as its own systemd service on a local port, and give it a subdomain:

/etc/nginx/sites-available/streamlit-app
# Optional: a separate Streamlit app on app.yourdomain.com
# (DNS: add an A record "app" → 203.0.113.10, run Streamlit on 127.0.0.1:8501 with its own systemd service)
server {
    listen 80;
    server_name app.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8501;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;     # Streamlit uses websockets
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400;
    }
}
# then: sudo certbot --nginx -d app.yourdomain.com
Key takeaways
  • DNS first, then Certbot, then DJANGO_HTTPS=True.
  • Certificates renew automatically; test with certbot renew –dry-run.
  • Use paths for apps inside Django, subdomains for separate programs.

↑ Back to topNext: Updates, logs and the production checklist →

Section 10

How do you update, monitor and secure the live app?

Quick answer

Update with a small deploy script (git pull, install requirements, migrate, collectstatic, restart Gunicorn), read logs with journalctl and the Nginx error log, take a snapshot before big changes, and work through a production checklist: DEBUG off, secrets in .env, HTTPS, firewall, non-root user, backups, PostgreSQL for real users and limits on AI usage.

Deploy updates in one command

deploy.sh
#!/usr/bin/env bash
# ~/agentsite/deploy.sh: run this after every git push
set -e
cd /home/deploy/agentsite
git pull
source .venv/bin/activate
pip install -r requirements.txt
python manage.py migrate --noinput
python manage.py collectstatic --noinput
sudo systemctl restart gunicorn
echo "Deployed ✓"

Make it executable once with chmod +x deploy.sh, then run ./deploy.sh after every push. It asks for the deploy user's password once, for the sudo systemctl restart line.

Read the logs

Terminal (VPS)
sudo journalctl -u gunicorn -f              # Django / Gunicorn logs (live)
sudo tail -f /var/log/nginx/error.log       # Nginx errors
sudo systemctl status gunicorn nginx        # are both running?

Troubleshooting

You seeLikely causeFix
502 Bad GatewayGunicorn is not running or crashed on startsudo journalctl -u gunicorn; often a missing package or a typo in .env
400 Bad RequestThe domain is not in ALLOWED_HOSTSAdd it to DJANGO_ALLOWED_HOSTS in .env and restart Gunicorn
403 CSRF verification failedHTTPS origin not trustedCheck the domain spelling in DJANGO_ALLOWED_HOSTS (it builds CSRF_TRUSTED_ORIGINS)
Page has no stylingStatic files not collected or not readableRun collectstatic, check the alias path ends with /, chmod 755 /home/deploy
413 Request Entity Too LargeCSV larger than Nginx allowsRaise client_max_body_size and reload Nginx
504 Gateway Timeout on the AI pageThe LLM answer took longer than the timeoutsKeep --timeout 120 and proxy_read_timeout 120s, use lower effort, or move long jobs to a background worker
Too many redirectsDJANGO_HTTPS=True before HTTPS worksSet it to False, run Certbot, then set it back to True
Domain does not load, IP doesDNS not updated yet, or wrong DNS zoneCheck with nslookup; edit records where your nameservers point

Production checklist: the features a live AI app needs

  • DEBUG=False and a unique SECRET_KEY on the server
  • API keys only in .env (chmod 600), never in Git
  • HTTPS with automatic renewal, and Django’s secure cookie settings on
  • Firewall allows only 22, 80 and 443 (ufw and, if used, the hPanel firewall)
  • App runs as a non-root user; SSH keys instead of passwords
  • Weekly backups on, plus a manual snapshot before every big change
  • PostgreSQL instead of SQLite once you have real users, logins or payments
  • Login, rate limits or subscriptions on the AI features to control API costs
  • Automatic security updates (sudo apt install unattended-upgrades) and an uptime monitor
  • Run python manage.py check --deploy and fix what it reports
  • Remove the VPS IP from DJANGO_ALLOWED_HOSTS once the domain works, so the site only answers on your domain

Want to go further? Containerise the project with Docker for repeatable deployments (see my Docker guide for AI developers) and learn how teams ship and monitor models in the MLOps beginner’s guide.

Key takeaways
  • One deploy script makes updates safe and boring.
  • Most errors are explained in the Gunicorn or Nginx logs.
  • Limit AI usage before you share the link widely.
Built your first live AI app? Make the next one a product.Python ka Chilla: Build AI Agents covers the Python, LLM, data and Claude Code skills behind everything in this guide, with live classes and a community to help when you get stuck.
Join Python ka Chilla →

All 18 videos: Product Development A-Z

The complete series, in order. Open the playlist on YouTube

Links and tools

Related guides on Codanics

More AI, data science and career guides on the Codanics blog.

Codanics on YouTubeAI agents, Python, data science and product development, in Urdu and Hindi.
Subscribe

Key terms explained

Short definitions of the words used in this guide

AI agent
A program that uses a language model to plan steps, call tools and act towards a goal, not just answer a question.
LangGraph
A Python framework for building stateful, multi-step and multi-agent AI workflows as graphs.
VPS (virtual private server)
Your own virtual Linux server with root access, sharing physical hardware with others but isolated from them.
KVM
Kernel-based Virtual Machine: the virtualisation technology behind Hostinger's VPS plans, giving each server dedicated resources.
Public IP address
The internet address of your VPS. You use it for SSH and in your domain's DNS A records.
A record
A DNS entry that points a domain name, such as yourdomain.com, to an IPv4 address.
Gunicorn
A Python WSGI server that runs your Django code and handles requests with several worker processes.
Nginx
A web server and reverse proxy that faces the internet, serves static files and forwards requests to Gunicorn.
Certbot
A free tool that gets and renews Let's Encrypt HTTPS certificates and configures Nginx for you.
Django app vs project
A project is the whole website; an app is one feature inside it with its own URLs, views and templates.

Frequently asked questions

Which Hostinger VPS plan do I need for a Django AI agent app?

For a first product, KVM 2 (2 vCPU, 8 GB RAM, 100 GB NVMe) is a comfortable start. KVM 1 (1 vCPU, 4 GB RAM) is enough for learning, demos and a small number of users, because the language model runs on the provider's servers, not on your VPS. Move to KVM 4 or KVM 8 when you add background workers, more projects or many concurrent users. Watch CPU and RAM in hPanel and upgrade when you need to. You can get an extra 20% off with my referral link: https://www.hostinger.com?REFERRALCODE=1MUHAMMADAA70

Can I host a Django app on Hostinger shared hosting instead of a VPS?

Shared web hosting is built mainly for PHP and WordPress sites. To run Django with Gunicorn, Nginx and your own Python packages you need root access, which a VPS gives you. That is why this guide uses a KVM VPS.

Does a Hostinger VPS have a public IP address?

Yes. Each VPS gets its own public IP address, shown in hPanel under VPS → Overview. You use it to connect over SSH and point your domain's A records to the server.

How do I connect my domain to the VPS?

Add two A records in your domain's DNS: @ pointing to the VPS IP and www pointing to the same IP. If the domain is at Hostinger, do this in hPanel under Domains → DNS / Nameservers. Changes usually work within minutes but can take up to 24–48 hours to spread everywhere.

How do I add HTTPS to my Django site?

Install Certbot with the Nginx plugin and run sudo certbot –nginx -d yourdomain.com -d www.yourdomain.com. It gets a free Let's Encrypt certificate, updates your Nginx configuration and renews automatically. Then turn on Django's secure settings.

Can two apps run under one URL?

Yes. Inside one Django project, each app gets its own path, such as yourdomain.com/agent/ and yourdomain.com/analytics/, through the main urls.py. If the second app is a different program, such as Streamlit or FastAPI, run it as its own service and point a subdomain such as app.yourdomain.com to it in Nginx.

Where should I keep my API key?

In a .env file on the server that is not committed to Git, readable only by your user (chmod 600). Django reads it with python-dotenv, and the Anthropic SDK picks up ANTHROPIC_API_KEY automatically.

How many Gunicorn workers should I use?

A common starting point is 2 × number of CPU cores + 1: three workers on KVM 1 and five on KVM 2. Use a longer timeout, such as 120 seconds, because AI answers can take longer than normal web requests.

Should I use SQLite or PostgreSQL in production?

SQLite is fine for a demo or a small internal tool. For a product with real users, logins or payments, install PostgreSQL on the VPS and point Django's DATABASES setting to it.

What is an AI agent?

An AI agent is a program that uses a large language model to decide what to do next: it reads a goal, plans steps, calls tools such as search, code or databases, checks the results and continues until the task is done. A chatbot only answers; an agent acts.

How much does it cost to deploy an AI agent app on Hostinger?

Two costs: the VPS and the LLM API. A Hostinger KVM 1 VPS started at about $6.49 per month on a 24-month promotion and KVM 2 at about $8.79 (checked November 2026, before any referral discount). API costs depend on how many questions users ask and which model you use, so add logins, limits or subscriptions before launch.

How long does it take to deploy a Django app on a VPS?

About one to two hours the first time if your code is ready: around 30 minutes to set up the server, 20 minutes for Gunicorn and Nginx, and a few minutes for DNS and HTTPS, plus waiting for DNS to update. Later updates take a minute with a deploy script.

Do I need Docker to deploy Django on Hostinger?

No. This guide uses a plain Ubuntu server with Gunicorn, Nginx and systemd, which is simpler to learn. Docker becomes useful when you run several services or want identical environments on every machine.

How do I update the live app after changing my code?

Push to GitHub, SSH into the VPS and run a small deploy script: git pull, install requirements, migrate, collectstatic and restart Gunicorn. Take a snapshot in hPanel before big changes so you can roll back.

About the author. Dr. Muhammad Aammar Tufail is the founder of Codanics and completed his PhD in a Marie Skłodowska-Curie programme. He teaches Python, AI agents, data science and bioinformatics in Urdu and Hindi, and builds AI products such as the Datajin data analytics app.

Follow him on Facebook, Instagram, TikTok and LinkedIn, see his code on GitHub and Kaggle, and his research on Google Scholar and ResearchGate.

Hostinger plan specs and prices were checked on 6 November 2026 and change often. Commands were written for Ubuntu 24.04 LTS. Always test on your own server and read the official documentation for Django, Nginx and Certbot.

Exit mobile version