Skip to main content

FastAPI Nginx Configuration

Introduction

When deploying a FastAPI application to production, running it directly using Uvicorn or Hypercorn might not be the optimal approach. This is where Nginx comes into the picture. Nginx is a powerful web server and reverse proxy that can sit in front of your FastAPI application to handle client requests, manage SSL/TLS termination, serve static files efficiently, and provide load balancing.

In this tutorial, we'll explore how to configure Nginx as a reverse proxy for your FastAPI application and explain why this setup is beneficial for production deployments.

Why Use Nginx with FastAPI?

Before diving into the configuration, let's understand why using Nginx with FastAPI is considered a best practice:

  1. Performance: Nginx excels at serving static content and handling concurrent connections efficiently.
  2. Security: Nginx can provide an additional security layer, protecting your application from various attacks.
  3. SSL/TLS Termination: Nginx can handle HTTPS connections, reducing the complexity in your FastAPI application.
  4. Load Balancing: Distributes traffic across multiple FastAPI instances for better reliability and scalability.
  5. Static File Serving: Serves static files directly without burdening your FastAPI application.

Prerequisites

Before configuring Nginx with FastAPI, ensure you have:

  • A working FastAPI application
  • Nginx installed on your server
  • Basic understanding of server configuration
  • Root or sudo access to your server (for installing and configuring Nginx)

Installation

Install Nginx

On Ubuntu/Debian:

bash
sudo apt update
sudo apt install nginx

On CentOS/RHEL:

bash
sudo yum install epel-release
sudo yum install nginx

Verify the installation:

bash
nginx -v

Output:

nginx version: nginx/1.18.0 (Ubuntu)

Run Your FastAPI Application

Let's assume you have a FastAPI app running on port 8000. You can run it with:

bash
uvicorn main:app --host 0.0.0.0 --port 8000

Your FastAPI app is now accessible at http://your-server-ip:8000.

Basic Nginx Configuration for FastAPI

Now, let's configure Nginx as a reverse proxy for your FastAPI application.

Step 1: Create a New Nginx Configuration File

Create a new file in /etc/nginx/sites-available/:

bash
sudo nano /etc/nginx/sites-available/fastapi_app

Step 2: Add the Basic Configuration

Add the following configuration:

nginx
server {
listen 80;
server_name example.com www.example.com;

location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}

Replace example.com and www.example.com with your actual domain name.

Step 3: Enable the Configuration

Create a symbolic link to enable the configuration:

bash
sudo ln -s /etc/nginx/sites-available/fastapi_app /etc/nginx/sites-enabled/

Step 4: Test and Restart Nginx

Check if the configuration has any syntax errors:

bash
sudo nginx -t

If successful, restart Nginx:

bash
sudo systemctl restart nginx

Now your FastAPI application should be accessible through Nginx at http://your-domain.com.

Advanced Nginx Configuration

Let's enhance our Nginx configuration with some advanced features.

Serving Static Files

To serve static files directly through Nginx (which is more efficient):

nginx
server {
listen 80;
server_name example.com www.example.com;

# Static files
location /static/ {
alias /path/to/your/static/files/;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}

# Media files
location /media/ {
alias /path/to/your/media/files/;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}

# FastAPI
location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}

SSL Configuration

To secure your application with HTTPS:

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

server {
listen 443 ssl;
server_name example.com www.example.com;

# SSL certificates
ssl_certificate /path/to/your/fullchain.pem;
ssl_certificate_key /path/to/your/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';

# Other SSL settings
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;

# Static and application config as before
location /static/ {
alias /path/to/your/static/files/;
expires 30d;
}

location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}

Load Balancing Multiple FastAPI Instances

For scaling your application, you can configure Nginx to distribute traffic across multiple FastAPI instances:

nginx
# Define upstream servers (FastAPI instances)
upstream fastapi_servers {
server localhost:8000;
server localhost:8001;
server localhost:8002;
# Add more servers as needed
}

server {
listen 80;
server_name example.com www.example.com;

location / {
proxy_pass http://fastapi_servers;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}

Rate Limiting and Security

You can add rate limiting to protect your application from abuse:

nginx
# Limit request rate by defining a zone
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

server {
listen 80;
server_name example.com www.example.com;

# Apply rate limiting to the FastAPI endpoints
location / {
# Limit requests with a burst of 20
limit_req zone=api_limit burst=20 nodelay;

proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}

Real-world Example: Complete Configuration

Here's a comprehensive example that combines all the features we've discussed:

nginx
# Define upstream servers for load balancing
upstream fastapi_servers {
server localhost:8000;
server localhost:8001;
}

# Rate limiting configuration
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

# Redirect HTTP to HTTPS
server {
listen 80;
server_name api.example.com;
return 301 https://$host$request_uri;
}

# Main server block
server {
listen 443 ssl;
server_name api.example.com;

# SSL Configuration
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';

# Security headers
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";

# Logging
access_log /var/log/nginx/api.access.log;
error_log /var/log/nginx/api.error.log;

# Serve static files
location /static/ {
alias /var/www/fastapi_app/static/;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}

# API requests
location / {
# Rate limiting
limit_req zone=api_limit burst=20 nodelay;

# Proxy configuration
proxy_pass http://fastapi_servers;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;

# Timeouts
proxy_connect_timeout 75s;
proxy_read_timeout 300s;
}
}

Setting Up a Systemd Service for FastAPI

For production deployments, you should run your FastAPI application as a system service. Create a systemd service file:

bash
sudo nano /etc/systemd/system/fastapi.service

Add the following content:

ini
[Unit]
Description=FastAPI application
After=network.target

[Service]
User=username
Group=username
WorkingDirectory=/path/to/your/app
ExecStart=/path/to/your/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=fastapi
Environment="PATH=/path/to/your/venv/bin"

[Install]
WantedBy=multi-user.target

Enable and start the service:

bash
sudo systemctl enable fastapi
sudo systemctl start fastapi

Summary

In this guide, we've covered how to configure Nginx as a reverse proxy for FastAPI applications. We've explored basic setup, advanced configurations including SSL/TLS, static file serving, load balancing, and security features like rate limiting.

Using Nginx with FastAPI provides numerous benefits including improved performance, better security, and easier scalability. This combination is recommended for any production FastAPI deployment.

Remember to:

  1. Keep your Nginx and FastAPI versions updated
  2. Regularly check your Nginx logs for issues
  3. Test your configuration changes before applying them in production
  4. Secure your server by implementing proper firewall rules and security headers

Additional Resources

Exercises

  1. Set up a basic FastAPI application with Nginx as a reverse proxy.
  2. Configure SSL/TLS for your FastAPI application using Let's Encrypt.
  3. Implement load balancing for multiple FastAPI instances.
  4. Add rate limiting to protect your API endpoints from abuse.
  5. Configure proper logging for both Nginx and your FastAPI application.

Happy coding and deploying!



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)