Skip to main content
The cPanel Setup Python App tool registers a Python WSGI app under your account, builds a virtualenv, and hands the running process to Phusion Passenger. CloudLinux ships Python interpreters as alt-python packages. Each app picks its own version, and the virtualenv lives separate from the system Python.

Available versions

Available versions vary by host. Typical rotation:
  • Python 3.11. Active.
  • Python 3.10. Maintained.
  • Python 3.9. Older, still common for legacy apps.
Older alt-python (3.7, 3.8, 2.7) may be available for compatibility. Avoid Python 2 for anything new.

Set up an app

1

Open Setup Python App

From cPanel home, scroll to Software and click Setup Python App.
Setup Python App tool icon
2

Click Create Application

On an empty account, you land on a list page with a + Create Application button.
3

Fill in the form

  • Python version: pick from the dropdown.
  • Application root: directory under your home, e.g. myapp. Created if it doesn’t exist.
  • Application URL: domain dropdown plus optional path. Use / for the root or /api for a sub-path.
  • Application startup file: defaults to passenger_wsgi.py. Leave it as that unless you have a reason.
  • Application Entry point: dotted path plus callable, format module:callable. For Django: <project>.wsgi:application. For Flask: <module>:app.
  • Passenger log file: optional. Useful for catching boot errors.
4

Save

Click Create. Passenger starts the app in the background.

Manage an app

ButtonWhat it does
Run Pip InstallReads requirements.txt and installs into the per-app virtualenv.
Stop AppHalts Passenger for this app. The URL returns 503.
RestartEquivalent to touch tmp/restart.txt. Reloads the running app.
EditReopens the form. Saving overwrites the .htaccess.
DestroyRemoves Passenger registration and the per-app virtualenv.
The Configuration files field accepts paths like requirements.txt (relative to the application root). The Environment variables editor sits below the buttons.

The Passenger contract

Passenger expects a WSGI callable named application. Your passenger_wsgi.py either defines it directly or imports it from your app. For Flask:
passenger_wsgi.py
from myapp import app as application
For Django:
passenger_wsgi.py
import os
import sys

sys.path.insert(0, '/home/<user>/myapp')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
Your code does not run a development server. No app.run(), no manage.py runserver.
Calling app.run() (Flask) or runserver (Django) inside a Passenger-managed app makes Passenger see no application and return a 500 with passenger_wsgi.py did not provide an "application" callable. Remove the call.

ASGI apps

Native ASGI (FastAPI, Starlette, Channels) needs a WSGI shim. The common bridge is asgiref.WsgiToAsgi reversed, but Passenger’s WSGI mode does not handle WebSockets or HTTP/2 streaming over ASGI. For a sync FastAPI subset, wrap with a2wsgi:
passenger_wsgi.py
from a2wsgi import ASGIMiddleware
from main import app as asgi_app

application = ASGIMiddleware(asgi_app)
For real WebSockets, run Daphne or Uvicorn outside the Selector.

Reference: where things live

WhatPath
Activated env script~/virtualenv/<app-root>/<version>/bin/activate
Installed packages~/virtualenv/<app-root>/<version>/lib/...
Restart trigger~/<app-root>/tmp/restart.txt
Passenger config~/<app-root>/.htaccess (Selector-managed)
Boot log (if configured)path you set in Passenger log file
From SSH, activate manually:
source ~/virtualenv/myapp/3.11/bin/activate && cd ~/myapp
pip install -r requirements.txt

Common issues

passenger_wsgi.py doesn’t expose a top-level name application. Either rename your callable to application, or alias it: application = app.
The package was installed against the system Python, not the per-app virtualenv. Run Pip Install from the cPanel UI, or activate the env in SSH first: source ~/virtualenv/<app>/<ver>/bin/activate.
Passenger only serves the WSGI app. Run manage.py collectstatic and serve /static/ directly from Apache. Add to .htaccess:
Alias /static/ /home/<user>/myapp/static/
<Directory "/home/<user>/myapp/static">
  Require all granted
</Directory>
PMEM is ~1 GB. Heavy compiled wheels can OOM. Use prebuilt wheels (the default for pandas / numpy on linux x86_64), avoid --no-binary, and consider installing one package at a time.
Default Passenger startup timeout is 60 seconds. Long migrations or heavy INSTALLED_APPS initialization can exceed it. Bump the timeout in .htaccess:
PassengerStartTimeout 120

Recipes

Deploy Django

Django app, virtualenv, static files.

Deploy Flask

Flask service via passenger_wsgi.py.

Need a hand?

Open a ticket

Best for anything that needs an account check or a config change on our end.

Live chat

Faster for quick questions during business hours.