Deploy Django on cPanel Shared Hosting
Deploy Django on cPanel shared hosting with Setup Python App and Phusion Passenger: create the app and virtualenv, write passenger_wsgi.py, use MySQL or PostgreSQL, serve static files from public_html, and know the hosting limits.
Problem statement
Many people already pay for shared hosting with cPanel, and it often supports Python through the Setup Python App tool, which runs apps with Phusion Passenger. You cannot install Nginx, Gunicorn, or systemd services on shared hosting, so the usual VPS guides do not apply. You can run a Django site, though, if you follow cPanel's model: Passenger loads a passenger_wsgi.py file, cPanel manages a virtualenv for you, and static files are served by the host's web server from your public directory.
- In cPanel, open Setup Python App, create an app with the newest Python version offered, application root (for example
myapp), and URL. - Upload or
git clonethe project into the application root. - Enter the virtualenv using the command cPanel shows, then
pip install -r requirements.txt. - Point
passenger_wsgi.pyat your Django WSGI application. - Create a MySQL (or PostgreSQL, if offered) database in cPanel and set the credentials as environment variables in the app settings.
- Set
STATIC_ROOTinsidepublic_html(or a subfolder), runcollectstatic,migrate, then restart the app.
Step-by-step solution
1. Create the Python app
In cPanel → Software → Setup Python App → Create Application:
- Python version: the newest available (3.11+).
- Application root:
myapp(a folder in your home directory, outsidepublic_html). - Application URL: your domain or a subdomain.
- Application startup file:
passenger_wsgi.py; entry point:application.
cPanel creates a virtualenv under ~/virtualenv/myapp/<version>/ and shows a command to activate it.
2. Upload code and install packages
With SSH (enable it in cPanel if available) or the Terminal feature:
source ~/virtualenv/myapp/3.12/bin/activate
cd ~/myapp
git clone https://github.com/you/myapp.git .
pip install -r requirements.txt
Without SSH, upload files with the File Manager and use the "Run Pip Install" button in Setup Python App. Packages that need compilation may fail on shared hosts without compilers; prefer pure-Python or wheel-available packages, and mysqlclient may need the host's support, with PyMySQL as a fallback.
3. Write passenger_wsgi.py
# ~/myapp/passenger_wsgi.py
import os
import sys
sys.path.insert(0, os.path.dirname(__file__))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
from config.wsgi import application # noqa: E402
Passenger imports this file and calls application for each request, starting worker processes on demand.
4. Database and environment
Create a database and user in MySQL Databases (or PostgreSQL Databases if the host offers it), grant all privileges, and add environment variables in the Setup Python App screen: SECRET_KEY, DATABASE_URL (for example mysql://cpuser_app:pass@localhost/cpuser_myapp), ALLOWED_HOSTS. For MySQL, set OPTIONS = {"charset": "utf8mb4"}.
5. Static files, migrations, restart
STATIC_URL = "/static/"
STATIC_ROOT = os.path.expanduser("~/public_html/static")
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.expanduser("~/public_html/media")
python manage.py migrate
python manage.py collectstatic --noinput
touch ~/myapp/tmp/restart.txt
The host's web server (Apache or LiteSpeed) serves /static/ and /media/ directly from public_html. Restart by touching tmp/restart.txt or clicking Restart in Setup Python App after every code change.
6. HTTPS
Enable AutoSSL (or Let's Encrypt in cPanel) for the domain. Add SECURE_PROXY_SSL_HEADER if the host proxies to Passenger, and force HTTPS with the cPanel Domains "Force HTTPS Redirect" switch.
Verification check: visit the domain over HTTPS, confirm admin CSS loads from /static/, check the Passenger error log (often ~/myapp/stderr.log or under ~/logs/) for startup errors, and edit a template then touch restart.txt to confirm changes appear.
Explanation
Phusion Passenger is an application server that integrates with Apache and LiteSpeed. cPanel's Setup Python App (provided by CloudLinux on many hosts) wraps Passenger with a per-app virtualenv and environment settings. Passenger spawns Python processes as requests arrive and can stop idle ones, which suits shared servers where many accounts share resources. Django runs normally inside it; the constraints come from the shared environment: no root access, capped resources, and no long-running processes of your own.
Edge cases / notes
- 500 errors with no detail: check
stderr.login the app root and set up file logging to a writable path. - Python version is limited to what the host installs; ask the host if you need newer.
- Celery generally cannot run; use cron with management commands for periodic work.
- Database limits on shared plans (connections, size) can bite as traffic grows.
Next steps
- Compare hosting models in Best Hosting Options for Django Deployment.
- A Python-focused alternative is Deploy Django on PythonAnywhere.
FAQ
Can I host Django on cPanel?
Yes, if your host offers Setup Python App (Passenger). Without it, you need a VPS or PaaS.
How do I restart a Django app on cPanel?
Touch tmp/restart.txt in the app root or click Restart in Setup Python App.
Can I use PostgreSQL on cPanel?
Some hosts offer PostgreSQL Databases in cPanel. Otherwise use MySQL with utf8mb4.
Why are my static files not loading?
STATIC_ROOT must be inside public_html (or served by the host), and you must run collectstatic after each change.