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 ~
2. Create a project directory:
$ mkdir fastapi_demo
3. Move into it:
$ cd fastapi_demo
4. Update the APT package index:
$ sudo apt update
5. Install python3-venv:
$ sudo apt install -y python3-venv
6. Create a virtual environment:
$ python3 -m venv venv
7. Activate it:
$ source venv/bin/activate
8. Install FastAPI with all optional dependencies:
$ pip install fastapi[all] wheel
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"}
Save and close the file.
10. Start a temporary dev server with Uvicorn:
$ uvicorn app:app
11. In a new terminal session, test it:
$ curl http://localhost:8000
Output:
{"message": "Hello World"}
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
2. Start a temporary Gunicorn server with the Uvicorn worker:
$ gunicorn app:app -k uvicorn.workers.UvicornWorker
3. In another session, test it:
$ curl http://localhost:8000
Output:
{"message": "Hello World"}
4. Create a Gunicorn config file:
$ nano gunicorn_conf.py
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'
Save and close the file.
6. Create the systemd unit file:
$ sudo nano /etc/systemd/system/fastapi_demo.service
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
Save and close the file.
8. Reload the systemd daemon:
$ sudo systemctl daemon-reload
9. Enable and start the service:
$ sudo systemctl enable --now fastapi_demo
Output:
Created symlink /etc/systemd/system/multi-user.target.wants/fastapi_demo.service → /etc/systemd/system/fastapi_demo.service.
10. Check its status:
$ sudo systemctl status fastapi_demo
11. Test the socket directly:
$ curl --unix-socket /home/linuxuser/fastapi_demo/gunicorn.sock http://localhost
Output:
{"message":"Hello World"}
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
2. Create a virtual host config file:
$ sudo nano /etc/nginx/sites-available/fastapi_demo
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;
}
}
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/
5. Check the Nginx config syntax:
$ sudo nginx -t
Output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
6. Reload Nginx to apply the change:
$ sudo systemctl reload nginx
7. Allow HTTP/HTTPS through the firewall:
$ sudo ufw allow 'Nginx Full'
8. Verify the firewall rules:
$ sudo ufw status
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
2. Request and install a certificate:
$ sudo certbot --nginx -d fastapi.example.com
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
4. Test automatic renewal:
$ sudo certbot renew --dry-run
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)