Python + Uvicorn + Nginx howto

uvicorn

Let's say we have a python (ex. FastAPI) app running on VPS with Ubuntu.

$ uvicorn main:app --reload

There is also nginx installed with some default configuration files. Let's configure nginx to work and serve our webapp on the internet.

1. Look around and find out what configs you already have

Login to your server via ssh:

$ ssh username@ip_address

Look at the /etc/nginx/conf.d/ and identify all the configs related to your website.

At this time you have to decide whether you will be using single config or differrent configs for HTTP and HTTPS.

I am personally using one config file located at /etc/nginx/conf.d/example.com.conf

2. Setup nginx like a proxy server

2.1. Create http proxy

Open your config and add:

server {
    listen 80;
    server_name example.com www.example.com;
    
    # Forward all HTTP requests to HTTPS
    return 301 https://$host$request_uri;
}

Here we say that the server must forward all HTTP requests to HTTPS.

2.2. Create https proxy

Now let's create our “production” HTTPS config. Open your config and add:

server {
    listen 443 ssl;
    server_name example.com www.example.com;
    root /path/to/your/website;

    # Path to SSL certificates
    ssl_certificate /path/to/ssl/cert/fullchain.pem;
    ssl_certificate_key /path/to/ssl/cert/privkey.pem;

    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;
    }

    location /static/ {
        proxy_pass http://127.0.0.1:8000;
        alias /path/to/your/website;
        proxy_set_header Content-Security-Policy upgrade-insecure-requests;
    }

    # Location for Let's Encrypt verification
    location ~ /\.(?!well-known\/|file) {
        deny all;
        return 404;
    }

}

2.3. Create and save SSL certificates

Let's Encrypt has brief guide about how to use Certbot to generate SSL certificates and setup them on a server.

2.4. Add your certificates to the server config

Again, open your config and add paths to your SSL certs to the main “server” section:

server {
    ...

    # Path to SSL certificates
    ssl_certificate /path/to/ssl/cert/fullchain.pem;
    ssl_certificate_key /path/to/ssl/cert/privkey.pem;

    location / {
    
    ...
}

3. That's all

Restart nginx

$ sudo systemctl restart nginx

And then – restart your app.

Overall config file

/etc/nginx/conf.d/example.com.conf

server {
    listen 80;
    server_name example.com www.example.com;
    
    # Forward all HTTP requests to HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com www.example.com;
    root /path/to/your/website;

    # Path to SSL certificates
    ssl_certificate /path/to/ssl/cert/fullchain.pem;
    ssl_certificate_key /path/to/ssl/cert/privkey.pem;

    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;
    }

    location /static/ {
        proxy_pass http://127.0.0.1:8000;
        alias /path/to/your/website;
        proxy_set_header Content-Security-Policy upgrade-insecure-requests;
    }

    # Location for Let's Encrypt verification
    location ~ /\.(?!well-known\/|file) {
        deny all;
        return 404;
    }

}

Links: Python | FastAPI | Uvicorn | Certbot | Let's encrypt