How to Deploy Your FastAPI App to a Live Server
This guide will show you how to take your FastAPI application, built with features like authentication, a PostgreSQL database, and S3 file storage, and make it accessible to the public internet. We will deploy it to a Virtual Private Server (VPS), configure essential security measures, set up a custom domain name, and secure it with an SSL certificate using Nginx. This process provides a fundamental understanding of web application deployment that applies to various VPS providers.
Prerequisites
- A completed FastAPI application (as built in previous tutorials).
- A GitHub account to host your code.
- A registered domain name.
- Basic familiarity with the command line and Git.
Step 1: Add a Health Check Endpoint
Before deploying, it’s crucial to add a health check to your FastAPI application. This endpoint lets monitoring systems and load balancers know if your application is running correctly. For our blog app, we’ll check if the database is reachable.
- Open your main application file (e.g.,
main.py). - Add the necessary import:
from sqlalchemy import text. - Locate where you include your routers. Right after that, add the health check endpoint.
- Paste the following code snippet to create the health check route:
@app.get("/health", tags=["Health"])
async def health_check(db: Session = Depends(get_db)):
try:
# Execute a lightweight query to check database connectivity
await db.execute(text("SELECT 1"))
return {"status": "healthy"}
except Exception:
raise HTTPException(status_code=503, detail="Database unavailable")
This code attempts a simple database query. If it succeeds, it returns a “healthy” status. If it fails (meaning the database is down), it returns a 503 Service Unavailable error.
Step 2: Upload Your Code to GitHub
To easily transfer your project to the server, we’ll use GitHub. You can use a public or private repository; public is fine for this tutorial.
- Create a new repository on GitHub (e.g.,
fastapi-tutorial-18-deployment-vps). - In your local project’s terminal, add the GitHub repository as a remote origin and push your code:
git remote add origin https://github.com/YOUR_USERNAME/YOUR_REPO_NAME.git
git push -u origin main
Expert Note: Ensure your .env file is in your .gitignore file. Never push sensitive credentials to your code repository.
- Commit your latest changes (including the health check) if you haven’t already:
git add . Git commit -m "Add health check endpoint"
git push
Step 3: Set Up Your Virtual Private Server (VPS)
We’ll use a VPS provider like Linode. The concepts apply to DigitalOcean, AWS EC2, etc.
- Sign up for a VPS provider account (e.g., Linode).
- Create a new server instance (a “Linode” on Linode).
- Choose an Image: Select Ubuntu 24.04 LTS for long-term support.
- Choose a Region: Pick a data center geographically close to your expected users.
- Choose a Plan: Start with a basic, affordable plan (e.g., 1GB RAM shared CPU) for small applications. You can upgrade later.
- Add a Label: Give your server a descriptive name (e.g.,
fastapi-blog). - Set a Strong Root Password: Create a secure password and save it.
- Finalize Creation: Review add-ons (like backups) and create the server.
Once the server is provisioned, you will get a public IP address. Note this IP address down.
Step 4: Connect to Your Server via SSH
You’ll connect to your server using SSH (Secure Shell). We’ll initially log in as the root user.
- Open your local terminal.
- Connect using the SSH command, replacing
YOUR_SERVER_IPwith your server’s IP address:
ssh root@YOUR_SERVER_IP
You’ll be asked to confirm the server’s fingerprint; type yes. Then, enter the root password you set during server creation.
Step 5: Initial Server Setup and User Creation
It’s best practice to create a non-root user for daily operations to limit potential damage from mistakes or security breaches.
- Update System Packages: Ensure your server has the latest software and security patches.
sudo apt update && sudo apt upgrade -y
When prompted about configuration files, choose the package maintainer’s version for a clean install.
- Create a New User: Replace
your_usernamewith your desired username.
adduser your_username
Set a strong password for this new user when prompted. You can skip the additional user details by pressing Enter.
- Grant Sudo Privileges: Allow your new user to run administrative commands.
usermod -aG sudo your_username
Verify the user is in the sudo group by running groups your_username.
Step 6: Set Up SSH Key-Based Authentication
SSH keys are more secure than passwords. We’ll generate a key pair on your local machine and copy the public key to the server.
- Generate SSH Key Pair (Local Machine):
ssh-keygen -t ed25519 -C "[email protected]"
Accept the default file location (~/.ssh/id_ed25519) or specify a descriptive name. Enter a strong passphrase when prompted. This passphrase protects your private key.
- Copy Public Key to Server: Use the
ssh-copy-idcommand. Replaceyour_usernameandYOUR_SERVER_IP.
ssh-copy-id -i ~/.ssh/id_ed25519.pub your_username@YOUR_SERVER_IP
Enter the password for your new user on the server when prompted.
- Add Key to SSH Agent (Local Machine): This allows you to use the key without re-entering the passphrase every time.
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
Enter your SSH key passphrase when asked.
- Test SSH Key Login: Try connecting to your server again. You should not be asked for a password.
ssh your_username@YOUR_SERVER_IP
If this works, your SSH key setup is successful.
Step 7: Harden SSH Configuration
To significantly improve security, we’ll disable root login and password authentication entirely, forcing all logins to use SSH keys.
- Edit SSH Daemon Configuration:
sudo nano /etc/ssh/sshd_config
Find and modify the following lines:
PermitRootLogin noPubkeyAuthentication yesPasswordAuthentication noChallengeResponseAuthentication no
Save the file (Ctrl+X, then Y, then Enter).
- Restart SSH Service:
sudo systemctl restart ssh
Critical Warning: Before closing your current SSH session, open a *new* terminal window on your local machine and try to SSH into the server using your SSH key. If you cannot connect, revert the changes in sshd_config using your root login before proceeding. Once you confirm you can still log in, you can close the root session.
Step 8: Configure Firewall (UFW)
A firewall controls network traffic to and from your server. We’ll use UFW (Uncomplicated Firewall).
- Install UFW (if not already installed):
sudo apt install ufw -y
- Set Default Policies: Deny all incoming traffic and allow all outgoing traffic by default.
sudo ufw default deny incoming
sudo ufw default allow outgoing
- Allow Necessary Ports: Crucially, allow SSH, HTTP (port 80), and HTTPS (port 443) traffic.
sudo ufw allow OpenSSH
sudo ufw allow http
sudo ufw allow https
Important: Always allow SSH *before* enabling the firewall to avoid locking yourself out.
- Enable the Firewall:
sudo ufw enable
Confirm with y. Check the status with sudo ufw status verbose.
Step 9: Install and Configure Nginx and SSL
Nginx will act as a reverse proxy, handling incoming web requests and directing them to your FastAPI application. We’ll also set up SSL for HTTPS.
- Install Nginx:
sudo apt install nginx -y
- Configure Nginx for Your App: Create a new Nginx configuration file for your domain. Replace
your_domain.comwith your actual domain name.
sudo nano /etc/nginx/sites-available/your_domain.com
Paste the following configuration, adjusting your_domain.com and the server’s IP address (if needed). Make sure the proxy_pass points to where your FastAPI app will run (e.g., http://127.0.0.1:8000).
server {
listen 80;
server_name your_domain.com www.your_domain.com;
location / {
proxy_pass http://127.0.0.1:8000; # Assuming your app runs on port 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 Nginx Site: Create a symbolic link to enable the configuration.
sudo ln -s /etc/nginx/sites-available/your_domain.com /etc/nginx/sites-enabled/
- Test Nginx Configuration:
sudo nginx -t
If syntax is okay, proceed. If not, fix errors in the configuration file.
- Install Certbot for SSL: Certbot automates obtaining and renewing Let’s Encrypt SSL certificates.
sudo apt install certbot python3-certbot-nginx -y
- Obtain SSL Certificate: Run Certbot to get a certificate for your domain.
sudo certbot --nginx -d your_domain.com -d www.your_domain.com
Follow the prompts. Certbot will automatically update your Nginx configuration to use HTTPS and set up automatic renewal.
Step 10: Deploy Your FastAPI Application
Now we need to get your FastAPI app running on the server and make sure it starts automatically.
- Install Dependencies: On your server, clone your repository (if you haven’t already) and install project dependencies.
git clone https://github.com/YOUR_USERNAME/YOUR_REPO_NAME.git
cd YOUR_REPO_NAME
sudo apt install python3-venv python3-dev build-essential libpq-dev -y
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Make sure your requirements.txt includes fastapi, uvicorn[standard], sqlalchemy, and your database driver (e.g., psycopg2-binary).
- Configure Environment Variables: Set up your production database URL and other secrets in a
.envfile on the server.
Security Tip: Use a tool like python-dotenv to load these variables into your application.
- Run FastAPI with Uvicorn: Start your FastAPI application. Replace
main:appwith your application’s entry point.
uvicorn main:app --host 0.0.0.0 --port 8000 --reload
Test if your application is accessible via your domain name (e.g., http://your_domain.com/health). If not, check Nginx logs (`/var/log/nginx/error.log`) and your application’s output.
- Set Up a Process Manager (Systemd): To ensure your application runs continuously and restarts if it crashes, use a process manager like Systemd. Create a service file.
sudo nano /etc/systemd/system/fastapi_blog.service
Paste the following configuration, adjusting paths and usernames:
[Unit]
Description=FastAPI Blog Service
After=network.target
[Service]
User=your_username
Group=your_username
WorkingDirectory=/home/your_username/YOUR_REPO_NAME
ExecStart=/home/your_username/YOUR_REPO_NAME/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000
Restart=always
[Install]
WantedBy=multi-user.target
- Enable and Start the Service:
sudo systemctl daemon-reload
sudo systemctl enable fastapi_blog.service
sudo systemctl start fastapi_blog.service
sudo systemctl status fastapi_blog.service
Check the status to ensure it’s running. You can view logs using sudo journalctl -u fastapi_blog.service.
Conclusion
Your FastAPI application is now deployed to a VPS, accessible via your custom domain with HTTPS, and secured with a firewall and SSH hardening. This foundation allows real users to interact with your application. For more advanced deployments, consider containerization with Docker in the next tutorial.
Source: Python FastAPI Tutorial (Part 18): Deploy to a VPS – Security, Nginx, SSL, and Custom Domain (YouTube)