Django App Hosting on cPanel
Deploying a Django project on a shared hosting environment using cPanel (with Python App support) can be a smooth process. Here’s how to do it from start to finish.
Prerequisites
Before we begin, make sure you have:
- A shared hosting plan with cPanel access
- Python App support (look for “Setup Python App” in cPanel)
- Domain or Subdomain ready
- Your Django project (in a standard structure).
- Access to File Manager or SSH (optional but helpful).
Step 1: Prepare Your Django Project
Ensure your project follows this structure:
myproject/
├── manage.py
├── myproject/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── requirements.txtThen:
- Generate
requirements.txt:
pip freeze > requirements.txt- Zip your project (excluding
venv,.git,__pycache__):Shellzip -r myproject.zip myproject/
Step 2: Upload Project to cPanel
- Go to File Manager in cPanel.
- Upload the
myproject.zipfile to a location like:/home/username/myproject/ - Extract the zip file.
- Move the extracted folder to your desired location, e.g.,
/home/username/myproject/if needed.
Step 3: Create a Python App
- Open Setup Python App in cPanel.
- Click Create Application and configure.
- Python version: e.g. 3.11
- Application root:
myproject - Application URL: select a domain or subdomain
- Application startup file:
passenger_wsgi.py(cPanel pre-created) - Application entry point:
application(cPanel pre-created)
- Click Create.
Step 4: Create passenger_wsgi.py
-
Inside your project root (
myproject/), create a file namedpassenger_wsgi.py(most of cPanel provide pre-created file). -
Add this content (update
myprojectto your actual project name):
import sys
import os
project_home = os.path.expanduser('~/myproject')
if project_home not in sys.path:
sys.path.insert(0, project_home)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()If you’re using a subdirectory (e.g., yourdomain.com/backend), append this to the file:
os.environ['FORCE_SECRET_NAME'] = "/backend"And in settings.py:
FORCE_SCRIPT_NAME = "/backend"
STATIC_URL = "/backend/static/"
MEDIA_URL = "/backend/media/"Step 5: Install Dependencies
- In Setup Python App, copy the virtualenv path.
- Open cPanel Terminal or SSH:
source /home/username/virtualenv/myproject/3.11/bin/activate
cd ~/myproject/
pip install -r requirements.txtNo terminal access? Use the Setup Python App interface instead.
- Go to the Configuration Files section.
- Add requirements.txt.
- Click Run Pip Install.
Step 6: Update Django Settings
In myproject/settings.py update the following:
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']
CORS_ALLOWED_ORIGINS = [
"https://yourdomain.com",
"https://www.yourdomain.com",
]
CORS_TRUSTED_ORIGINS = [
"https://yourdomain.com",
"https://www.yourdomain.com",
]
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')Step 7: Collect Static Files
Run the following in terminal:
python manage.py collectstaticYour static files should now be in the staticfiles/ directory.
Step 8: Migrate the Database
python manage.py migrateIf no terminal access, use the Python App interface:
In the Execute python script section, you can run:
For static files:
-m manage collectstatic --noinputFor migrations:
-m manage migrateStep 9: Restart the App
Back in Setup Python App, click Restart next to your Django app.
Done!
Visit your domain/subdomain:
- Example: https://yourdomain.com or htpps://yourdomain.com/subdomain (depending on your setup)
you should see your Django project running 🎉.
Troubleshooting
Got a 500 Error?
Check logs here:
/home/username/myproject/stderr.logCan’t find Python App option?
Your hosting provider may not support it. Contact them or consider upgrading your plan.
Optional: Subdomain .htaccess Routing (I haven’t tested this).
If you’re skipping FORCE_SCRIPT_NAME setup, you may need a .htaccess file:
RewriteEngine On
RewriteBase /backend/
WSGIScriptAlias /backend /home/username/myproject/passenger_wsgi.pyPlace .htaccess in the subdomain’s root directory.
To Serve Media and Static Files
To make your uploaded media and static files accessible via browser, add the following to your urls.py:
from django.views.static import serve
from django.conf import settings
from django.urls import re_path
urlpatterns = [
#Media files (user uploads)
re_path(r"^media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT}),
#Static files (CSS, JS, images)
re_path(r"^static/(?P<path>.*)$", serve, {"document_root": settings.STATIC_ROOT}),
# ... your other URL patterns
]Final Tips
- Set DEBUG = False in production.
- Keep your SECRET_KEY safe.
- Use SQLite for simpler setups or configure MySQL/PostgreSQL via cPanel.
Need Help?
If you get stuck or run into an error, feel free to:
- Check your error logs (
stderr.log) - Revisit each step — a small path or typo might cause issues
- Contact your hosting provider if Python App is not visible
- Ask the Django community on Stack Overflow or Django Discord
Happy coding!