21+ years in hosting · Jaipur, India · INR billing with 18% GST · 24/7 email support
Blog · WebJi® India

How to Host a Django Website on cPanel

Quick answer

Host a Django website on cPanel from Setup Python App. Point passenger_wsgi.py at your project's WSGI callable, install requirements.txt, set ALLOWED_HOSTS, then run migrate and collectstatic. Restart the application. The domain should show your site, not the sample Python page. Passenger serves it. You do not get a root shell.

A deploy checklist for running one Django app per domain under Passenger, written for cPanel accounts with the Python selector.

✓ In business since 2005
✓ INR + GST billing
✓ 24/7 Email Support — avg reply < 60 min
GuideWebJi®
knowledge
Read time
6 min
Sections
9
Updated
14 Nov 2026
Written by
WebJi® team

Can shared hosting run Django? Yes — through Passenger

If your host provides cPanel with the Setup Python App screen under Software, shared hosting can run one Django application per domain or subdomain: cPanel creates the virtualenv and Passenger loads your WSGI callable — you get no root shell, and the process sleeps when idle. The check for whether your account qualifies takes ten seconds: look under Software for Setup Python App. If the icon is missing, that account is not a Python runtime and no amount of uploading will change it.

On WebJi®, the entry Linux shared plan is not a Python runtime — cPanel hosting is a separate product, and Python projects are quoted per server: email support@webji.services, or read Python hosting. Panel accounts live on cPanel hosting. And a note for the framework-confused: CodeIgniter is PHP and belongs in a document root, not in Setup Python App.

  • One application, one folder, one domain or subdomain.
  • The success test is your Django page on that domain after a restart — not the sample Python page.
  • Passenger stops the process when idle: a brochure site or internal tool fits; a busy API does not.

Step 1: create the Python application in cPanel

Open Setup Python App, click Create Application, and get four choices right — Python version, application root, application URL and the startup file — because they decide whether the domain ever reaches Django.

  1. Choose the Python version your project already runs. Django 5.2 LTS needs Python 3.10 or newer; Django 6.0 needs 3.12 or newer. Do not take an older interpreter just because it is first in the list.
  2. Set Application root to a folder holding manage.py, sitting outside public_html — for example djangoapp. A project inside public_html can leave settings.py downloadable to the world.
  3. Set Application URL to the domain or subdomain that should serve the site; add a path only when the app is part of the domain.
  4. Set the startup file to passenger_wsgi.py and the entry point to application.
  5. Click Create. The new row shows a status, a restart control, and the command that activates the virtualenv.

Set a Passenger log file on that same form — a blank 500 is usually explained there, not in the browser.

Step 2: upload the code and install requirements.txt

Zip the project without the local virtualenv, without __pycache__ and without the laptop's SQLite file, upload it into the application root with File Manager or SFTP, extract it, then install dependencies inside the app's own virtualenv. manage.py must sit directly in that root.

In the app's configuration-files list, add requirements.txt and click Run Pip Install — the panel installs into the app virtualenv, not the system Python. Wait for the success message before migrating. From Terminal, the equivalent is pasting the activation command shown at the top of the app, running pip install -r requirements.txt, and typing deactivate when done. A wheel built on your laptop will not run on this server, so install here.

Create the MySQL database Django will use

Create the database before running migrate: in MySQL Databases, add a database, add a user, grant that user all privileges on that one database, and copy the password — the names usually carry the account prefix cPanel assigns. Confirm the empty database exists in phpMyAdmin.

In settings.py set ENGINE to django.db.backends.mysql, HOST to localhost, and NAME, USER and PASSWORD to the values cPanel shows. Do not upload the laptop's SQLite file — two writes at once lock that single file. If pip stops with "Failed building wheel for mysqlclient", the account cannot compile the MySQL C client: add PyMySQL to requirements.txt and call pymysql.install_as_MySQLdb() in passenger_wsgi.py before Django imports, keeping the same ENGINE. Store the database password as an app environment variable, never in a public repository.

Step 3: wire passenger_wsgi.py and ALLOWED_HOSTS

Passenger loads the callable named application from passenger_wsgi.py, so replace the sample file with one that imports your project's WSGI callable — nothing more. The standard file is three lines:

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "yourproject.settings")
from yourproject.wsgi import application

yourproject is the folder containing settings.py and wsgi.py; save the file in the application root. Then four settings decide whether the public site behaves:

  • ALLOWED_HOSTS: the bare domain and the www host — without them Django returns 400 DisallowedHost.
  • DEBUG: False on the public site; True prints paths and settings to anyone who triggers an error.
  • SECRET_KEY and DB password: set as environment variables on the app screen; they apply only after Restart.
  • CSRF_TRUSTED_ORIGINS: on Django 4 and newer, list https:// plus the domain or form posts are rejected.

Click Restart, then reload the domain in a private window. Your home view — or a Django error page — means the import worked; the sample Python page means the entry point is still the demo.

Step 4: collectstatic and the /static/ URL

With DEBUG False, Django stops serving CSS and JavaScript the way the development server does, so run collectstatic and then serve STATIC_ROOT through WhiteNoise or a static URL mapping. In the activated virtualenv run python manage.py collectstatic --noinput, or run the same command from the panel's "Execute python script" field.

STATIC_ROOT is a real folder — usually BASE_DIR / "staticfiles" — and STATIC_URL is /static/. Add WhiteNoise middleware, or map /static/ to that folder if the host gives you an alias, then restart. The check is a stylesheet URL returning 200 rather than 404; and because editing a file leaves the old process in memory, always restart before judging the result.

Run migrations and create the superuser

From the same activated virtualenv, run python manage.py migrate to build the tables in the MySQL database, then python manage.py createsuperuser to create the admin login. createsuperuser asks for a username, an email and a password.

If the script runner cannot see manage.py, pass the full path to it. When a command fails, read stderr.log in the application root, fix the setting it names, and run it again — the log line beats a second guess every time. Finish by opening /admin/ on the domain and signing in: a login form proves both the database connection and the session middleware work.

Fix the usual Django errors on cPanel

Every Django failure on cPanel has one of five signatures, and each maps to one fix — change one thing, restart, reload in a private window.

Django error signatures on cPanel and their fixes
What you seeCauseFix
500, blank pagepassenger_wsgi.py imports the wrong project, or a package is missingRead stderr.log or the Passenger log, fix that line, restart
400 DisallowedHostALLOWED_HOSTS omits the domainAdd the bare domain and www, restart
CSS and JavaScript 404DEBUG False and nothing serves STATIC_ROOTcollectstatic, then WhiteNoise or a static map, restart
Failed building wheel for mysqlclientAccount cannot compile the MySQL C clientSwitch the dependency to PyMySQL, restart
Sample Python pageEntry point is still the demo appSet the entry point to application, restart

If the log is empty and the domain still fails, email support@webji.services with the domain, the Python version and the last log line — email support is 24/7 in Hindi and English with a published average first reply under 60 minutes. Do not call the office number for a 500.

When Django should move from cPanel to a VPS

Passenger starts the app when a request arrives and stops it when idle, which fits a brochure site or an internal tool — and does not fit Celery, Django Channels, a websocket that stays open, or any process bound to a port you choose. When your project needs any of those, move it to a VPS server: install the same Python version, run the app under systemd, and put the web server in front of it. The Django project itself needs no rewrite. Choosing that server is covered in Django hosting in India.

FAQ

Frequently asked questions

Can I host Django on cPanel shared hosting?

Yes, when the account has the Setup Python App screen — cPanel creates the virtualenv and Passenger loads passenger_wsgi.py. If that icon is missing, the account is not a Python runtime. On WebJi®, the entry Linux shared plan is not; email support@webji.services for a quoted Python server before uploading the project.

What is Setup Python App in cPanel?

It is the Software screen that creates a Python application: version, application root, URL, startup file and entry point. For Django the startup file is passenger_wsgi.py and the entry point is application. The panel also runs pip against that app's virtualenv, so dependencies install server-side.

Why does my Django app show a 500 on cPanel?

Usually passenger_wsgi.py imports the wrong module or a package from requirements.txt is missing. Open stderr.log in the application root or the Passenger log on the app screen, fix the line it names, and restart. A 400 DisallowedHost is the ALLOWED_HOSTS setting, not a 500.

How do I serve Django static files on cPanel?

Run collectstatic so the files land in STATIC_ROOT — with DEBUG False the development static handler is off. Then add WhiteNoise middleware, or map /static/ to that folder if the host provides the alias, and restart. A stylesheet URL returning 200 is the proof.

Does cPanel support websockets or Celery with Django?

No. Passenger serves the WSGI callable named application and gives you no port to bind — no port 8000, no long-running workers. Celery, Django Channels and open websockets need a VPS, where the same Django project runs under systemd behind a web server without code changes.

Last editorial update: 15 November 2026.

WebJi® since 2005

Ready to get started with WebJi®?

Join 12,000+ businesses across India and overseas. INR pricing, 18% GST shown before payment and 24/7 email support in Hindi and English — average first reply under 60 minutes.