Web Hosting Issues

How to Deploy a FastAPI App on cPanel (Setup Python App)

October 23, 2026 · 2 views

FastAPI is an ASGI framework: it normally runs under Uvicorn. cPanel's Setup Python App serves Python apps through Phusion Passenger, which speaks WSGI. The two meet through a small adapter, a2wsgi, which wraps your FastAPI app as a WSGI application. For a normal REST API this works well. Here is the whole setup.

1. Upload the project

Put the code in a folder outside public_html, e.g. /home/youruser/api. A minimal app in main.py:

from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
def health():
    return {"ok": True}

Make sure requirements.txt includes the adapter:

fastapi
a2wsgi

2. Create the Python application

In Setup Python App → Create Application, choose a Python version (3.9 or newer for current FastAPI), set Application root to api, the Application URL to your domain or a sub-path like /api, and keep the startup file passenger_wsgi.py with entry point application.

3. Write passenger_wsgi.py

Replace the generated file's content with:

import os, sys
sys.path.insert(0, os.path.dirname(__file__))

from a2wsgi import ASGIMiddleware
from main import app

application = ASGIMiddleware(app)

4. Install the requirements and restart

In the app's screen, add requirements.txt under Configuration files, press Run Pip Install, then Restart. Open https://yourdomain.com/health. You should get {"ok":true}. The interactive docs are at /docs, so protect or disable them in production (FastAPI(docs_url=None, redoc_url=None)).

Sub-path deployments

If the app lives at /api rather than the domain root, your routes still start at / inside the app. If the interactive docs at /api/docs can't load openapi.json, set FastAPI(root_path="/api") so generated URLs include the prefix.

Environment variables and databases

Add secrets (database URL, API keys) as environment variables in the app's screen and read them with os.environ or pydantic-settings. Create the MySQL database and user in cPanel → MySQL Databases and connect with SQLAlchemy using mysql+pymysql:// (add pymysql to requirements). It needs no compiler, unlike mysqlclient.

What this setup is not for

  • WebSockets: WSGI has no WebSocket support, so @app.websocket routes won't work through Passenger.
  • Long-running background work: BackgroundTasks run after the response inside the same request worker. Keep them short, or use a cron job (cPanel → Cron Jobs) for scheduled work.
  • Server-sent events / long streaming: responses are buffered by the adapter, so heavy streaming APIs belong on a VPS.

For typical JSON APIs, webhooks, admin backends and small SaaS services, this is a cheap, low-maintenance way to run FastAPI with SSL, backups and a database included.

Troubleshooting

  • "ModuleNotFoundError: No module named 'main'": the application root is wrong, or sys.path doesn't include the project folder (check the first two lines of passenger_wsgi.py).
  • 503 or "Incomplete response": an import error at start. Read stderr.log in the app folder, or run python -c "import main" in the app's virtual environment over SSH (the screen shows the command to enter it).
  • Changes don't show up: press Restart after every code change.

Droxin Python hosting comes with Setup Python App, SSH and the CPU, RAM and storage you choose. If your FastAPI or Django app won't start, open a ticket and an engineer fixes it with you. Also see our Django and Flask deployment guide.

Is your website having a similar issue?

We diagnose and fix it within 24 hours — you only pay after the fix is confirmed.

Get a Free Diagnosis

More from the blog