FastAPI Deploying to a Cloud Server
Running your app on your local machine is fine for development. Deploying to a cloud server makes it accessible to anyone on the internet, keeps it running 24/7, and scales when traffic grows. This topic covers two paths: deploying a Docker container to a cloud VM, and deploying to a managed platform.
Deployment Options Overview
Option 1: Cloud VM (VPS) Full control. You manage the server. Providers: DigitalOcean, AWS EC2, Linode, Hetzner Best for: custom setups, cost control at scale Option 2: Managed Platform (PaaS) Platform handles servers, scaling, SSL. Providers: Railway, Render, Fly.io, Heroku Best for: fast deployment, small teams, prototypes Option 3: Kubernetes Orchestrates many containers across many machines. Best for: large-scale production systems
Deploying to a Cloud VM (Ubuntu + Docker)
Step 1: Provision the Server
Create an Ubuntu 22.04 VM on your chosen cloud provider. Get the server's IP address and SSH access.
Step 2: Install Docker on the Server
ssh user@your-server-ip # Install Docker curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER
Step 3: Transfer Your App
# Option A: copy files with scp scp -r ./my-fastapi-app user@your-server-ip:/home/user/ # Option B: clone from Git (recommended) git clone https://github.com/yourname/your-repo.git cd your-repo
Step 4: Build and Run
docker build -t my-app . docker run -d -p 8000:8000 --restart always my-app
-d → run in background (detached) --restart always → restart automatically if server reboots
Adding a Reverse Proxy with Nginx
Nginx sits in front of your app, handles HTTPS, and forwards traffic to your container. Port 80 (HTTP) and 443 (HTTPS) cannot be used directly by Docker containers without root — Nginx bridges this gap.
Internet → port 443 → [ Nginx ] → port 8000 → [ FastAPI container ]
# Install Nginx
sudo apt install nginx
# /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;
}
}
Free SSL with Certbot
sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d yourdomain.com # Certbot automatically edits your nginx config # and sets up auto-renewal
After this step, your API is accessible at https://yourdomain.com with a valid SSL certificate.
Deploying to Render (Managed Platform)
Step 1: Push your code to GitHub Step 2: Sign up at render.com Step 3: Create a new "Web Service" → Connect your GitHub repo → Set build command: pip install -r requirements.txt → Set start command: uvicorn main:app --host 0.0.0.0 --port $PORT → Add environment variables (DATABASE_URL, SECRET_KEY) Step 4: Click Deploy → Render builds, deploys, and gives you an HTTPS URL
Deploying to Railway
Step 1: Sign up at railway.app Step 2: New project → Deploy from GitHub repo Step 3: Add a PostgreSQL plugin (one click) Step 4: Set environment variables Step 5: Railway auto-detects FastAPI and deploys Result: live URL in ~2 minutes
Environment Variables for Production
Development (.env file, never committed): DATABASE_URL=sqlite:///./dev.db SECRET_KEY=dev-secret Production (set in cloud dashboard, not in code): DATABASE_URL=postgresql://user:pass@prod-host/db SECRET_KEY=long-random-production-secret DEBUG=false
Health Check Endpoint
Add a simple health check route. Cloud platforms and load balancers ping this to verify your app is alive:
@app.get("/health")
def health():
return {"status": "ok"}
Key Points
- Cloud VMs give full control; managed platforms give speed and simplicity.
- Run containers with
--restart alwayson a VM so they survive reboots. - Use Nginx as a reverse proxy to handle ports 80/443 and forward to your app.
- Use Certbot to get free, auto-renewing SSL certificates from Let's Encrypt.
- Always set production secrets as environment variables in the cloud dashboard — never in code.
