DEV Community

Cover image for Deploying a FastAPI Application with Gunicorn and Nginx on Ubuntu 24.04
Sanskriti Harmukh for Vultr

Posted on with Aashish Chaurasiya Originally published at docs.vultr.com

Deploying a FastAPI Application with Gunicorn and Nginx on Ubuntu 24.04

FastAPI is a modern Python web framework for building high-performance APIs and web applications. It supports asynchronous programming with async/await for handling many simultaneous client connections efficiently, is built on the ASGI standard while remaining compatible with WSGI deployments, and ships with automatic, interactive API documentation via Swagger UI. This guide deploys a FastAPI application using Gunicorn as the application server (with a Uvicorn worker class for ASGI support) and Nginx as a reverse proxy on Ubuntu 24.04, then secures it with a free SSL certificate. By the end, you'll have a FastAPI app running as a systemd-managed Gunicorn service behind Nginx, reachable over HTTPS on your own domain.

Prerequisites: an Ubuntu 24.04 server with non-root sudo access, and a domain A record pointed at the server's IP address with your DNS provider (e.g. fastapi.example.com).


1. Set Up the FastAPI Application

1. Navigate to your home directory:

$ cd ~
Enter fullscreen mode Exit fullscreen mode

2. Create a project directory:

$ mkdir fastapi_demo
Enter fullscreen mode Exit fullscreen mode

3. Move into it:

$ cd fastapi_demo
Enter fullscreen mode Exit fullscreen mode

4. Update the APT package index:

$ sudo apt update
Enter fullscreen mode Exit fullscreen mode

5. Install python3-venv:

$ sudo apt install -y python3-venv
Enter fullscreen mode Exit fullscreen mode

6. Create a virtual environment:

$ python3 -m venv venv
Enter fullscreen mode Exit fullscreen mode

7. Activate it:

$ source venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

8. Install FastAPI with all optional dependencies:

$ pip install fastapi[all] wheel
Enter fullscreen mode Exit fullscreen mode

9. Add the following application code (e.g. to app.py):

from fastapi import FastAPI
app = FastAPI()

@app.get("/")
async def home():
    return {"message": "Hello World"}
Enter fullscreen mode Exit fullscreen mode

Save and close the file.

10. Start a temporary dev server with Uvicorn:

$ uvicorn app:app
Enter fullscreen mode Exit fullscreen mode

11. In a new terminal session, test it:

$ curl http://localhost:8000
Enter fullscreen mode Exit fullscreen mode

Output:

{"message": "Hello World"}
Enter fullscreen mode Exit fullscreen mode

2. Deploy FastAPI Using Gunicorn

Gunicorn is a Python WSGI HTTP server for UNIX systems. It manages your FastAPI application process(es) and supports ASGI through a Uvicorn worker class.

1. Install Gunicorn:

$ pip install gunicorn
Enter fullscreen mode Exit fullscreen mode

2. Start a temporary Gunicorn server with the Uvicorn worker:

$ gunicorn app:app -k uvicorn.workers.UvicornWorker
Enter fullscreen mode Exit fullscreen mode

3. In another session, test it:

$ curl http://localhost:8000
Enter fullscreen mode Exit fullscreen mode

Output:

{"message": "Hello World"}
Enter fullscreen mode Exit fullscreen mode

4. Create a Gunicorn config file:

$ nano gunicorn_conf.py
Enter fullscreen mode Exit fullscreen mode

5. Add the following, adjusting the paths for your setup:

from multiprocessing import cpu_count

# Socket path
bind = 'unix:/home/linuxuser/fastapi_demo/gunicorn.sock'

# Worker options
workers = cpu_count() + 1
worker_class = 'uvicorn.workers.UvicornWorker'

# Logging options
loglevel = 'debug'
accesslog = '/home/linuxuser/fastapi_demo/access_log'
errorlog = '/home/linuxuser/fastapi_demo/error_log'
Enter fullscreen mode Exit fullscreen mode

Save and close the file.

6. Create the systemd unit file:

$ sudo nano /etc/systemd/system/fastapi_demo.service
Enter fullscreen mode Exit fullscreen mode

7. Add the following:

[Unit]
Description=Gunicorn Daemon for FastAPI Demo Application
After=network.target

[Service]
User=linuxuser
Group=www-data
WorkingDirectory=/home/linuxuser/fastapi_demo
ExecStart=/home/linuxuser/fastapi_demo/venv/bin/gunicorn -c /home/linuxuser/fastapi_demo/gunicorn_conf.py app:app

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

Save and close the file.

8. Reload the systemd daemon:

$ sudo systemctl daemon-reload
Enter fullscreen mode Exit fullscreen mode

9. Enable and start the service:

$ sudo systemctl enable --now fastapi_demo
Enter fullscreen mode Exit fullscreen mode

Output:

Created symlink /etc/systemd/system/multi-user.target.wants/fastapi_demo.service → /etc/systemd/system/fastapi_demo.service.
Enter fullscreen mode Exit fullscreen mode

10. Check its status:

$ sudo systemctl status fastapi_demo
Enter fullscreen mode Exit fullscreen mode

11. Test the socket directly:

$ curl --unix-socket /home/linuxuser/fastapi_demo/gunicorn.sock http://localhost
Enter fullscreen mode Exit fullscreen mode

Output:

{"message":"Hello World"}
Enter fullscreen mode Exit fullscreen mode

3. Set Up Nginx as a Reverse Proxy

Nginx forwards client requests to Gunicorn, serves the app on standard HTTP/HTTPS ports, and can terminate SSL for you.

1. Install Nginx:

$ sudo apt install -y nginx
Enter fullscreen mode Exit fullscreen mode

2. Create a virtual host config file:

$ sudo nano /etc/nginx/sites-available/fastapi_demo
Enter fullscreen mode Exit fullscreen mode

3. Add the following, replacing fastapi.example.com with your actual domain:

server {
    listen 80;
    server_name fastapi.example.com;

    location / {
        proxy_pass http://unix:/home/linuxuser/fastapi_demo/gunicorn.sock;
        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;

        # Optional: Handle WebSocket connections
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Timeout settings
        proxy_connect_timeout 60s;
        proxy_read_timeout 120s;
    }
}
Enter fullscreen mode Exit fullscreen mode

Save and close the file.

4. Symlink it into sites-enabled/ to activate it:

$ sudo ln -s /etc/nginx/sites-available/fastapi_demo /etc/nginx/sites-enabled/
Enter fullscreen mode Exit fullscreen mode

5. Check the Nginx config syntax:

$ sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

Output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Enter fullscreen mode Exit fullscreen mode

6. Reload Nginx to apply the change:

$ sudo systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

7. Allow HTTP/HTTPS through the firewall:

$ sudo ufw allow 'Nginx Full'
Enter fullscreen mode Exit fullscreen mode

8. Verify the firewall rules:

$ sudo ufw status
Enter fullscreen mode Exit fullscreen mode

4. Secure Nginx with an SSL Certificate

Use Certbot to get a free SSL certificate from Let's Encrypt and encrypt traffic to your FastAPI app.

1. Install Certbot and its Nginx plugin:

$ sudo apt install -y certbot python3-certbot-nginx
Enter fullscreen mode Exit fullscreen mode

2. Request and install a certificate:

$ sudo certbot --nginx -d fastapi.example.com
Enter fullscreen mode Exit fullscreen mode

Certbot updates your Nginx configuration automatically. When prompted, enter your email address and agree to the terms of service.

3. Confirm HTTPS works by visiting:

https://fastapi.example.com
Enter fullscreen mode Exit fullscreen mode

4. Test automatic renewal:

$ sudo certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

If no errors appear, the certificate will renew automatically every 90 days.


Next Steps

  • Add structured logging and application monitoring around the Gunicorn service
  • Move secrets and environment-specific config out of source files and into environment variables
  • Tune the number of Gunicorn workers as traffic grows, or add a caching layer in front of the app
  • Set up log rotation for the Gunicorn access/error logs defined in gunicorn_conf.py

For the full guide with additional tips, visit the original article on Vultr Docs.

Top comments (0)