How to Deploy FastAPI Applications with Gunicorn and Nginx on Ubuntu 20.04
Introduction
FastAPI is a Python web framework for building APIs & web applications. It supports modern Python features like async & type hints, making it fast and efficient. In addition, it uses the Asynchronous Server Gateway Interface (ASGI) standard for asynchronous, concurrent connectivity with clients, and it can work with WSGI if needed.
In this article, you will learn everything required to deploy FastAPI Applications using Gunicorn & Nginx on an Ubuntu 20.04 server, such as setting up a FastAPI application in a virtual environment, using Gunicorn as an application server, Nginx as a reverse proxy & securing Nginx using an SSL Certificate. It does not include steps to install any database server for standardization because FastAPI can be used with any database server. You can refer to the following articles for database server installation:
- Install MySQL on Ubuntu 20.04
- Install PostgreSQL on Ubuntu 20.04
- Install MongoDB on Ubuntu 20.04
Prerequisites
- Deploy a fresh Ubuntu 20.04 Server
- Create non-root sudo user
- Point a domain/subdomain to your server's public IP
Caution: Inspect the commands before execution. Some commands might require changes according to your system, such as user, project name, project directory, domain, etc.
Setup FastAPI Application
Initialize Project Directory
You can skip this step if you already have a git repository containing all your code. In that case, you can clone your repository, which will make a new directory for your project. Here we will create a directory to contain everything related to our project, including the codebase & virtual environment.
Create a folder for your project.
$ mkdir /home/demo/fastapi_demo
Open the project directory.
$ cd /home/demo/fastapi_demo
Create Virtual Environment
A virtual environment is a Python tool for dependency management and project isolation. This means that each project can have any package installed locally in an isolated directory instead of being installed globally.
Install Python virtual environment package.
$ sudo apt update $ sudo apt install python3-venv
Create a Python virtual environment for your project.
$ python3 -m venv venv
> Throughout this article, whenever a command is needed to be executed inside the virtual environment, the command snippets will start with (venv) $.
Enter the virtual environment.
$ source venv/bin/activate
Exit the virtual environment.
(venv) $ deactivate
Install Dependencies
Make sure you use only the
pip
command regardless of the version of pip installed on your host machine. When you are inside a virtual environment, the path is modified (until you exit) in such a way that thepip
command will refer to the pip executable file of the isolated virtual environment if you use pip3 or any command other than pip it might execute globally.Install wheel Python package.
(venv) $ pip install wheel
Install fastapi Python package.
(venv) $ pip install fastapi[all]
Make Basic FastAPI Application
You can skip this step if you already have a FastAPI Application ready to deploy. Here we have provided a very basic "Hello World" project code for demonstration purposes.
Create and edit
app.py
$ nano app.py
Paste the following code and save the file using Ctrl + X then Enter.
from fastapi import FastAPI app = FastAPI() @app.get("/") async def home(): return {"message": "Hello World"}
Test Deployment
Deploy a temporary web server for testing.
(venv) $ uvicorn app:app
To verify if everything works, open a duplicate terminal and run.
$ curl http://localhost:8000
The expected output for provided demo code is:
{"message": "Hello World"}
Deploy FastAPI using Gunicorn
Gunicorn is a Python WSGI HTTP Server for UNIX. It makes managing and monitoring a web application much easier. Given its customizable nature, we can use ASGI features by using Uvicorn's worker class.
Install Gunicorn
Install the gunicorn Python package.
(venv) $ pip install gunicorn
Test Deployment
Deploy a temporary web server for testing.
(venv) $ gunicorn app:app -k uvicorn.workers.UvicornWorker
To verify if everything works, open a duplicate terminal and run.
$ curl http://localhost:8000
The expected output for the provided demo code is:
{"message": "Hello World"}
Create Systemd Service
Add configuration file for Gunicorn.
$ nano gunicorn_conf.py
Paste the following code and save the file using Ctrl + X then Enter.
from multiprocessing import cpu_count # Socket Path bind = 'unix:/home/demo/fastapi_demo/gunicorn.sock' # Worker Options workers = cpu_count() + 1 worker_class = 'uvicorn.workers.UvicornWorker' # Logging Options loglevel = 'debug' accesslog = '/home/demo/fastapi_demo/access_log' errorlog = '/home/demo/fastapi_demo/error_log'
Create and edit systemd unit file.
$ sudo nano /etc/systemd/system/fastapi_demo.service
Paste the following code and save the file using Ctrl + X then Enter.
[Unit] Description=Gunicorn Daemon for FastAPI Demo Application After=network.target [Service] User=demo Group=www-data WorkingDirectory=/home/demo/fastapi_demo ExecStart=/home/demo/fastapi_demo/venv/bin/gunicorn -c gunicorn_conf.py app:app [Install] WantedBy=multi-user.target
Start & enable the service.
$ sudo systemctl start fastapi_demo $ sudo systemctl enable fastapi_demo
To verify if everything works run the following command.
$ sudo systemctl status fastapi_demo
Expected output:
Also, you can check the response using the following command.
$ curl --unix-socket unix:/home/demo/fastapi_demo/gunicorn.sock localhost
The expected output for the provided demo code is:
{"message": "Hello World"}
Setup Nginx as Reverse Proxy
Nginx is an open-source, lightweight & powerful web server. It is recommended to use Nginx as a reverse proxy for seamless request handling. Also, you can take advantage of Nginx's vhost / virtual server feature to host multiple web applications on a single host if you wish to do so. You can also offload some load from your WSGI/ASGI server by serving static files directly using the additional location
directive in our server block.
Install Nginx
$ sudo apt update $ sudo apt install nginx
Add vhost configuration
Add vhost file to
sites-available
directory.$ sudo nano /etc/nginx/sites-available/fastapi_demo
Paste the following content (replace your_domain with your actual domain) and save the file using Ctrl + X then Enter.
server { listen 80; server_name your_domain www.your_domain; location / { proxy_pass http://unix:/home/demo/fastapi_demo/gunicorn.sock; } }
Activate vhost configuration
Add a soft link of the vhost file in the
sites-enabled
directory.$ sudo ln -s /etc/nginx/sites-available/fastapi_demo /etc/nginx/sites-enabled/
Test and reload the configuration
Test the configuration.
$ sudo nginx -t
Expected output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Reload Nginx.
$ sudo systemctl reload nginx
Secure Nginx with an SSL Certificate
An SSL Certificate is used to encrypt the traffic between users and the origin server. It is essential for applications dealing with sensitive data. We will use Let's Encrypt to obtain an SSL Certificate for free. Please make sure you have pointed your domain to the server's public IP.
Install Certbot
$ sudo apt install -y certbot python3-certbot-nginx
Install Certificate on Nginx
You will be asked to enter your email address when you run the following command. Please enter your email address and leave the rest set as default.
$ sudo certbot --nginx -d your_domain -d www.your_domain
Verify the Accessibility
You can verify if the SSL Certificate is configured properly or not by opening the following link in your web browser.
https://your_domain
Test Auto-Renewal
Let's Encrypt certificates are only valid for 90 days, but certbot will handle auto-renewals. You can verify if the auto-renewal works by running the following command:
$ sudo certbot renew --dry-run
If the above command doesn't throw an error, it means your SSL certificate will be renewed automatically without any issues.
Conclusion
In this article, you learned how to use virtual environments to isolate dependencies, set up a FastAPI application, use Gunicorn as an application server, Nginx as a reverse proxy server & secure Nginx using an SSL Certificate. For more information related to FastAPI, visit the official FastAPI website.