On cPanel servers with CloudLinux, Setup Python App runs Python web apps through Phusion Passenger, without root access. This guide shows how to deploy Django on cPanel, and the same steps work for Flask with a smaller WSGI file.
Before you start
- A cPanel account where Software → Setup Python App is available.
- SSH or the cPanel Terminal for installing packages (recommended).
- Your project files and a
requirements.txt. - A MySQL database and user created in cPanel → Databases → Manage My Databases.
Create the Python application
- Open cPanel → Software → Setup Python App and click Create Application.
- Choose a Python version your project supports.
- Application root: a folder in your home directory, e.g.
myproject(keep it outsidepublic_html). - Application URL: the domain or subdomain to serve.
- Application startup file:
passenger_wsgi.py; Entry point:application. - Click Create. cPanel creates the folder, a virtualenv and a sample
passenger_wsgi.py.
The top of the app page shows a command to enter the virtualenv, similar to:
source /home/USER/virtualenv/myproject/3.11/bin/activate && cd /home/USER/myprojectUpload code and install requirements
Upload your project into the application root (File Manager, SFTP or Git). Then, over SSH, run the activation command and install:
pip install -r requirements.txtFor MySQL with Django, mysqlclient needs compiling; if that fails, use PyMySQL and add import pymysql; pymysql.install_as_MySQLdb() to settings.py. You can also add packages from the app page under Configuration files → Run Pip Install.
Edit passenger_wsgi.py
For Django (project package myproject):
import os
import sys
sys.path.insert(0, os.path.dirname(__file__))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()For Flask (app object app in app.py):
import os, sys
sys.path.insert(0, os.path.dirname(__file__))
from app import app as applicationConfigure Django settings
DEBUG = False
ALLOWED_HOSTS = ['example.com', 'www.example.com']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'user_dbname',
'USER': 'user_dbuser',
'PASSWORD': 'strong-password',
'HOST': 'localhost',
}
}
STATIC_URL = '/static/'
STATIC_ROOT = '/home/USER/public_html/static'Add secrets through Environment variables on the Setup Python App page instead of hard-coding them. Then run, inside the virtualenv:
python manage.py migrate && python manage.py collectstatic --noinputStatic files collected into public_html/static are served directly by the web server. If the app URL is the main domain, make sure the folder is reachable at /static/.
Restart and test
Click Restart on the app page after every code or settings change (or touch tmp/restart.txt in the app root). Open the URL; you should see your site.
Troubleshooting
- "We're sorry, but something went wrong": a Passenger startup error. Check
stderr.login the app root (enable it under the app's log settings) and the domain's error log. - ModuleNotFoundError: packages were installed outside the virtualenv. Run the activation command first, then pip.
- DisallowedHost: add the domain to
ALLOWED_HOSTS. - Admin without styling:
collectstaticwas not run orSTATIC_ROOTis not web-accessible. - Long tasks killed: CloudLinux resource limits apply; move heavy jobs to cron.
Python on cPanel FAQ
Can I use PostgreSQL?
Only if the server has PostgreSQL enabled in cPanel. Otherwise use MySQL/MariaDB.
Do WebSockets or Celery work?
Passenger serves standard WSGI requests. WebSockets, Celery workers and other long-running processes need a VPS.
Can I choose the Python version later?
Yes, edit the app and pick another version, then reinstall requirements into the new virtualenv.
