If you are new to FastAPI and more familiar with cPanel hosting than a VPS or server, you can still deploy FastAPI on cPanel using Uvicorn instead of WSGI. You don’t need dedicated Python hosting. Follow the steps below to save both time and money.
Deploy FastAPI on cPanel
To keep things quick, let’s start with a simple FastAPI project that has 2 files:
main.py
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
@app.post("/items/")
async def create_item(item: Item):
return item
requirements.txt
fastapi
pydantic
uvicorn

Step 1: Make sure your domain points to your hosting’s IP address and that you have added the domain to your hosting. Don’t forget to enable HTTPS for the domain.

Step 2: Upload your project files to your domain’s folder in File Manager.

Step 3: Create a Python application. Go to Setup Python App in cPanel.

Click the CREATE APPLICATION button to create a Python application in cPanel.

Just set Application root and Application URL to your domain and click the CREATE button. You don’t need to worry about the other fields.

Step 4: Install the packages in the requirements.txt file. This step includes 2 small steps as follows:
- Type “requirements.txt” and click the Add button.
- Click the Run Pip Install button and select requirements.txt.

Step 5: Click the STOP APP button and copy the command that enters the app’s virtual environment.
You need to stop the app because FastAPI doesn’t work well with WSGI. No matter how you configure the passenger_wsgi.py file, you will still get an error like [UID:1003][2014879] Child process with pid: 2021889 was killed by signal: 15, core dumped: no. We only use Setup Python App to create a valid virtual environment on cPanel.

Step 6: Run FastAPI in Terminal.
Open Terminal in cPanel.

Paste and run the command you copied in step 5. You can also install other packages with Pip here.
# Copy from your Python app
source /home/fysyrgiz/virtualenv/api.domain.com/3.11/bin/activate && cd /home/fysyrgiz/api.domain.com
Then run Uvicorn using this command.
uvicorn main:app --host 0.0.0.0 --port 8000
If you get the error “address already in use”, another application is already using that port. Just pick a higher port, for example 8001.

If you want it to keep running in the background, use the nohup command.
nohup uvicorn main:app --host 0.0.0.0 --port 8000 &
Once Terminal is error-free, access your FastAPI in the domain:port or domain:port/docs format. It’s great that your FastAPI is finally working, but there are still two issues to deal with:
- Without HTTPS (SSL), the browser shows “Not Secure”.
- The port at the end makes the URL look unprofessional and unfinished.

Step 7: Enable HTTPS and set up a reverse proxy that points your domain to the local FastAPI address. Add this code to the .htaccess file in your domain directory. Remember to replace fastapi.lucidgen.com:8001 with your local FastAPI address.
RewriteEngine On
# Force HTTPS
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# Reverse Proxy
RewriteRule ^(.*)$ http://fastapi.lucidgen.com:8001/$1 [P,L]

If you don’t see the .htaccess file, it may be hidden. Click the Settings button in File Manager and enable Show Hidden Files (dotfiles). If there is no .htaccess file at all, just create one.
Step 8: Open your FastAPI domain. HTTPS is now enabled, and the port is no longer in the URL.

Create a bash file for easy control
To make it easier to control FastAPI on the server, I created a run.sh file with the following arguments:
-a: Activate the virtual environment and move to the domain directory.-s: Start FastAPI withnohup.-r: Restart FastAPI withnohup.-f: Start FastAPI in the foreground.-k: Kill the FastAPI process.
Replace VENV_PATH and APP_DIR in this file with your own values.
#!/bin/bash
# ========== CONFIG ==========
VENV_PATH="/home/username/virtualenv/api.domain.com/3.11/bin/activate"
APP_DIR="/home/username/api.domain.com"
UVICORN_CMD="uvicorn main:app --host 0.0.0.0 --port 8000"
# ========== FUNCTIONS ==========
activate_env() {
echo "[Activating virtualenv and changing dir]"
source "$VENV_PATH" && cd "$APP_DIR"
}
kill_uvicorn() {
echo "[Killing uvicorn process]"
pkill -f "$UVICORN_CMD"
}
nohup_start() {
echo "[Starting uvicorn with nohup in background]"
activate_env
nohup $UVICORN_CMD &
echo "[Started with nohup]"
}
restart_uvicorn() {
echo "[Restarting uvicorn with nohup]"
activate_env
kill_uvicorn
nohup $UVICORN_CMD &
echo "[Restarted]"
}
run_foreground() {
echo "[Running uvicorn in foreground]"
activate_env
$UVICORN_CMD
}
# ========== PARSE ARGS ==========
if [ $# -eq 0 ]; then
echo "Please provide an argument."
echo "Valid arguments: $0 [-a] [-s] [-r] [-f] [-k]"
echo " -a Activate virtualenv and cd"
echo " -s Start uvicorn with nohup"
echo " -r Restart uvicorn with nohup"
echo " -f Run uvicorn in foreground"
echo " -k Kill uvicorn"
exit 1
fi
while getopts "asrfk" opt; do
case $opt in
a)
activate_env
;;
k)
kill_uvicorn
;;
s)
nohup_start
;;
r)
restart_uvicorn
;;
f)
run_foreground
;;
*)
echo "Argument is invalid"
echo "Valid arguments: $0 [-a] [-s] [-r] [-f] [-k]"
exit 1
;;
esac
done
Example of usage:
Only activate the environment and move to the domain directory:
source ~/domain.com/run.sh -a
Restart FastAPI:
bash ~/domain.com/run.sh -r
Conclusion
I came up with this way to deploy FastAPI on cPanel almost by accident, and luckily it works. To be honest, I’m not an expert in hosting, VPS, or servers. If you find this article useful, please share it on forums to help others.
So far, small and medium-sized FastAPI projects run very well on cPanel this way. I don’t have any large-scale, high-traffic FastAPI project yet to test how stable this setup is. If you find any problems with this way, please share with me and everyone through the comments below.





