Why Shouldn't Your FastAPI App Speak in Code?

Secure Your FastAPI App with HTTPS and SSL for Seamless Deployment

Why Shouldn't Your FastAPI App Speak in Code?

So, deploying your FastAPI app with HTTPS and SSL is pretty much non-negotiable these days if you care about keeping your web API secure. Let’s dive into this, breaking it all down in a simpler, more casual way to get your FastAPI app running safely.

First off, let’s clear up some tech lingo. HTTPS stands for Hypertext Transfer Protocol Secure. Unlike its cousin HTTP, HTTPS is like chatting in code; it encrypts the data between your browser and the web server. This nifty encryption stuff is handled by SSL (Secure Sockets Layer) or its more modern buddy TLS (Transport Layer Security). Think of SSL/TLS as digital bodyguards for your data.

Start simple. Make sure you have a FastAPI application to work with. Here’s a basic example:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Hello, World!"}

This neat little script sets up FastAPI with a single endpoint that says, “Hello, World!” when you visit it.

Now, before getting all the HTTPS goodness, you need a reverse proxy server to handle the traffic. NGINX, Apache, Traefik, and Caddy are popular choices, but let’s stick with NGINX for this example. Next is gathering your tools. You’re going to need NGINX, Gunicorn (or Uvicorn for ASGI), and Certbot to grab those precious SSL certificates. If you’re on a Debian-based system like Ubuntu, start like this:

sudo apt update
sudo apt install nginx gunicorn certbot python3-pip

FastAPI likes ASGI, so let’s get Uvicorn running too. Here’s the drill:

First, install Uvicorn:

pip install uvicorn

Set up Gunicorn and Uvicorn with Systemd. Create a service file at /etc/systemd/system/gunicorn.service:

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=your_username
Group=www-data
WorkingDirectory=/path/to/your/project
ExecStart=/usr/bin/gunicorn --workers 3 --bind unix:/run/gunicorn.sock -m 007 your_app:app

[Install]
WantedBy=multi-user.target

Don’t forget to replace your_username and /path/to/your/project with your actual details.

Create another file for the socket at /etc/systemd/system/gunicorn.socket:

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Reload Systemd and start the service:

sudo systemctl daemon-reload
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket

Time to configure NGINX. We’ll make it act as a reverse proxy to sling that HTTPS traffic over to your FastAPI app.

Set up an NGINX configuration file at /etc/nginx/sites-available/your_app with this:

server {
       listen 80;
       server_name your_domain.com;

       location / {
           proxy_pass http://unix:/run/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;
       }

       location /static/ {
           alias /path/to/your/project/static/;
       }
   }

   server {
       listen 443 ssl;
       server_name your_domain.com;

       ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
       ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;

       location / {
           proxy_pass http://unix:/run/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;
       }

       location /static/ {
           alias /path/to/your/project/static/;
       }
   }

   server {
       if ($host = your_domain.com) {
           return 301 https://$host$request_uri;
       }

       listen 80;
       server_name your_domain.com;
       return 404; # managed by Certbot
   }

Remember to customize your_domain.com and /path/to/your/project/static/ to match your specifics.

To activate your config, create a link and reload NGINX:

sudo ln -s /etc/nginx/sites-available/your_app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

With that out of the way, let’s hook up the SSL stuff. To get a free SSL certificate, we use Certbot. Installing it goes like this:

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Now, generate your SSL certificate:

sudo certbot --nginx

Follow through with the prompts, and Certbot will auto-configure NGINX for SSL.

Finally, test the renewal of your certificate to make sure everything’s smooth-sailing:

sudo certbot renew --dry-run

Now, your FastAPI app is ready to roll. Start it using Gunicorn and Uvicorn:

gunicorn --workers 3 --bind unix:/run/gunicorn.sock -m 007 your_app:app

But, since you set up a Systemd service earlier, you can simply kick off the service like this:

sudo systemctl start gunicorn

Head over to your browser, type in https://your_domain.com, and you should see your FastAPI app up, running securely over HTTPS.

Bonus tips:

  1. Redirect HTTP to HTTPS by ensuring the NGINX config above forces all traffic through HTTPS.
  2. Explore other reverse proxies like Traefik or Caddy if NGINX isn’t your jam. They offer similar routes with Let’s Encrypt for SSL.
  3. For a development environment, self-signed certificates are handy. Tools like mkcert can whip these up for you effortlessly.

Wrapping it up, deploying FastAPI with HTTPS and SSL might sound a bit like a marathon at first, but breaking it down piece-by-piece makes it a rewarding sprint. With NGINX, Gunicorn, and Certbot, you’ve got a robust, secure setup that’s ready to rock. Just be sure to test thoroughly to iron out any kinks before you go live. Happy coding!