Python + Uvicorn + Nginx howto
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