Deploying FastAPI applications to production on a VPS requires careful configuration. This step-by-step guide will walk you through the entire process.

Prerequisites

  • A VPS with Ubuntu 20.04 or later
  • Domain name (optional but recommended)
  • Basic knowledge of Linux commands

Step 1: Server Setup

Update System

sudo apt update
sudo apt upgrade -y

Install Python and Dependencies

sudo apt install python3.9 python3-pip python3-venv nginx supervisor -y

Step 2: Create Application Directory

mkdir -p /var/www/myapp
cd /var/www/myapp

Create Virtual Environment

python3 -m venv venv
source venv/bin/activate

Step 3: Deploy Your Application

Install Dependencies

pip install fastapi uvicorn[standard] gunicorn

Create Application File

# main.py
from fastapi import FastAPI

app = FastAPI()

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

@app.get("/health")
def health_check():
    return {"status": "healthy"}

Step 4: Configure Gunicorn

Create gunicorn_config.py:

# gunicorn_config.py
bind = "127.0.0.1:8000"
workers = 4
worker_class = "uvicorn.workers.UvicornWorker"
timeout = 120
keepalive = 5

Step 5: Setup Supervisor

Create /etc/supervisor/conf.d/myapp.conf:

[program:myapp]
command=/var/www/myapp/venv/bin/gunicorn -c /var/www/myapp/gunicorn_config.py main:app
directory=/var/www/myapp
user=www-data
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/myapp.log

Start the service:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start myapp

Step 6: Configure Nginx

Create /etc/nginx/sites-available/myapp:

server {
    listen 80;
    server_name yourdomain.com;

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

Enable the site:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

Step 7: Setup SSL with Let’s Encrypt

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com

Step 8: Security Hardening

Firewall Configuration

sudo ufw allow 22
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable

Environment Variables

Create .env file:

# .env
DATABASE_URL=postgresql://user:pass@localhost/dbname
SECRET_KEY=your-secret-key-here

Load in application:

from dotenv import load_dotenv
import os

load_dotenv()

DATABASE_URL = os.getenv("DATABASE_URL")
SECRET_KEY = os.getenv("SECRET_KEY")

Step 9: Monitoring and Logging

Setup Log Rotation

Create /etc/logrotate.d/myapp:

/var/log/myapp.log {
    daily
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data www-data
    sharedscripts
}

Health Check Endpoint

Already included in the application, monitor with:

curl http://localhost:8000/health

Step 10: Performance Optimization

Increase Worker Processes

Adjust in gunicorn_config.py:

workers = (2 * CPU_COUNT) + 1

Enable Caching

from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend

@app.on_event("startup")
async def startup():
    redis = aioredis.from_url("redis://localhost")
    FastAPICache.init(RedisBackend(redis), prefix="myapp-cache")

Troubleshooting

Check Application Logs

sudo tail -f /var/log/myapp.log

Check Supervisor Status

sudo supervisorctl status myapp

Restart Services

sudo supervisorctl restart myapp
sudo systemctl restart nginx

Conclusion

Following these steps will give you a production-ready FastAPI deployment on a VPS. Remember to:

  • Keep your dependencies updated
  • Monitor application logs regularly
  • Set up automated backups
  • Use environment variables for secrets
  • Enable SSL/TLS encryption
  • Configure proper firewall rules

Your FastAPI application is now running in production!