How to Deploy FastAPI Applications with Gunicorn and Nginx on Ubuntu 20.04

Updated on March 4, 2022
How to Deploy FastAPI Applications with Gunicorn and Nginx on Ubuntu 20.04 header image

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:

Prerequisites

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

  1. 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
  2. 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
  3. 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 the pip 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]
  4. 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"}
  5. 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.

  1. Install Gunicorn

    Install the gunicorn Python package.

     (venv) $ pip install gunicorn
  2. 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"}
  3. 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:

    Systemctl Status Result

    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.

  1. Install Nginx

     $ sudo apt update
     $ sudo apt install nginx
  2. 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;
         }
     }
  3. 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/
  4. 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.

  1. Install Certbot

     $ sudo apt install -y certbot python3-certbot-nginx
  2. 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
  3. 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
  4. 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.