Skip to content

Instantly share code, notes, and snippets.

@ShilGen
Last active November 18, 2025 15:09
Show Gist options
  • Select an option

  • Save ShilGen/abaeafe8b130ccd8d43edde4af8d6dce to your computer and use it in GitHub Desktop.

Select an option

Save ShilGen/abaeafe8b130ccd8d43edde4af8d6dce to your computer and use it in GitHub Desktop.
how to deploy fast-api on ubuntu 22.04 for real project? (step-by-step tutorial)

Deploy a FastAPI app on Ubuntu 22.04 VPS

Ubuntu Nginx Gunicorn Python FastAPI

Deploying a FastAPI application on Ubuntu 22.04 for a real project involves several steps, including setting up the server, installing necessary software, configuring the application, and setting up a reverse proxy. Here's a step-by-step tutorial

Step 1: Update System

First, update your system packages:

sudo apt update

Step 2: Install Python and Pip

Install Python and Pip if they are not already installed:

sudo apt install python3 python3-pip

Check it:

python3 --version
pip --version

Step 3: Install and Configure a Virtual Environment

Create a virtual environment for your FastAPI project:

sudo apt install python3.10-venv
python3 -m venv fastapi-env
source fastapi-env/bin/activate

Step 4: Install FastAPI1 and Uvicorn2

Install FastAPI and Uvicorn within your virtual environment:

pip install fastapi
pip install 'uvicorn[standard]'

Step 5: Create a Sample FastAPI Application

Create project folder and main.py file:

mkdir my_fastapi_project
cd my_fastapi_project
touch main.py

Create a sample FastAPI application. For example, edit a file named main.py:

vim main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

Step 6: Test the Application Locally

Run the application locally to ensure it works:

uvicorn main:app --reload

You should be able to access the application at http://127.0.0.1:8000.

For test in any browser run the application with real IP on 80 port:

uvicorn main:app --host 85.159.231.14 --port 80 --workers 4

Step 7: Set Up Gunicorn3 to Serve the FastAPI Application

Install Gunicorn:

pip install gunicorn

Create file gunicorn_conf.py for settings Gunicorn:

vim gunicorn_conf.py
bind = "0.0.0.0:8000"
workers = 4

Run Gunicorn with Uvicorn worker:

gunicorn -k uvicorn.workers.UvicornWorker -c gunicorn_conf.py main:app

Step 8: Install and Configure Nginx4

Install Nginx to act as a reverse proxy:

sudo apt install nginx

Create a new Nginx configuration file for your FastAPI application:

sudo nano /etc/nginx/sites-available/fastapi

Add the following content to the file, replacing your_domain with your actual domain or IP address:

server {
    listen 80;
    server_name your_domain;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable the configuration by creating a symbolic link:

sudo ln -s /etc/nginx/sites-available/fastapi /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

Step 9: Set systemd for autostart

Create a Gunicorn systemd service file:

sudo vim /etc/systemd/system/fastapi.service

Add the following content:

[Unit]
Description=FastAPI service
After=network.target

[Service]
User=root
Group=root
WorkingDirectory=/root/my_fastapi_project
ExecStart=/root/fastapi-env/bin/gunicorn -k uvicorn.workers.UvicornWorker -c /root/my_fastapi_project/gunicorn_conf.py main:app

[Install]
WantedBy=multi-user.target

Replace /path/to/your/project with the actual path to your FastAPI project.

Reload systemd to apply the new service, start it, and enable it to run on boot:

sudo systemctl daemon-reload
sudo systemctl start fastapi
sudo systemctl enable fastapi

Step 10: Open Firewall Ports

If you have a firewall enabled, you need to allow traffic on port 80 (HTTP):

sudo ufw allow 'Nginx Full'
sudo ufw enable

Step 11: Check Your Deployment

Your FastAPI application should now be accessible at your domain or IP address. Open a web browser and go to http://your_domain.

journalctl -u fastapi.service
systemctl status fastapi
vim /var/log/nginx/error.log

Optional: Setting Up HTTPS with Let's Encrypt

For a secure connection, you can set up HTTPS using Let's Encrypt:

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your_domain

Follow the prompts to complete the installation and obtain your SSL certificate.

Conclusion

You've successfully deployed a FastAPI application on Ubuntu 22.04. This setup includes running FastAPI with Gunicorn, serving it behind Nginx as a reverse proxy, and optionally securing it with HTTPS using Let's Encrypt. Make sure to replace placeholder values with your actual domain, paths, and project specifics.

Footnotes

  1. https://fastapi.tiangolo.com/

  2. https://www.uvicorn.org/

  3. https://gunicorn.org/

  4. https://nginx.org/

@ShilGen
Copy link
Author

ShilGen commented Dec 28, 2024

journalctl -xeu nginx.service

@ShilGen
Copy link
Author

ShilGen commented Dec 28, 2024

As the second step, we need to stop the alternate service running. To kill the process listening on port 80, we run the following command as root user.

fuser -k 80/tcp

Similarly, to kill process listening on 443, we can use the command as

fuser -k 443/tcp

@nguyenlamlll
Copy link

Amazing. Thank you very much!

Just a minor thing. In step 9, you mention Replace /path/to/your/project with the actual path to your FastAPI project.
But /path/to/your/project is not in the systemd service file above.

Anyways. I got everything working.

@rauf22750
Copy link

Successfully deployed my FastAPI project! 🚀 Huge thank you so much guided and supported me along the way. This milestone feels amazing and I’m super excited for what’s next. 🙌🔥

@unreal79
Copy link

Are you sure Gunicorn/FastAPI service should be run as root user?

@ShilGen
Copy link
Author

ShilGen commented Sep 28, 2025

Are you sure Gunicorn/FastAPI service should be run as root user?

yes, it's works for pet project,
I recomend set www-data

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment