Introduction
Deploying a FastAPI application with Nginx on AWS EC2 can be challenging for beginners. This guide will walk you through setting up an EC2 instance, installing necessary dependencies, configuring Nginx as a reverse proxy, and setting up a CI/CD pipeline with GitHub Actions.
Prerequisites
Before you begin, ensure you have the following:
- An AWS account (Create one here)
- A GitHub repository with your FastAPI application
- Basic knowledge of Linux and SSH
Step 1: Launch an AWS EC2 Instance
- Log in to the AWS Console.
- Navigate to EC2 Dashboard.
- Click Launch Instance.
- Choose an Ubuntu 22.04 AMI.
- Select an instance type (e.g.,
t2.micro
for free-tier users). - Configure security groups to allow ports 22 (SSH), 80 (HTTP), and 8000 (FastAPI).
- Download and save the
.pem
key securely. - Launch the instance and connect via SSH:
ssh -i your-key.pem ubuntu@your-instance-ip
Step 2: Install Dependencies
Run the following commands on the instance:
sudo apt update && sudo apt install -y nginx python3 python3-venv python3-pip
Verify that Nginx is installed:
nginx -v
Start and enable Nginx:
sudo systemctl start nginx
sudo systemctl enable nginx
Step 3: Deploy the FastAPI Application
- Clone your repository:
git clone https://github.com/your-repo.git fastapi-app
cd fastapi-app
- Set up a virtual environment and install dependencies:
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
- Create a
systemd
service file for FastAPI:
sudo nano /etc/systemd/system/fastapi.service
Add the following content:
[Unit]
Description=FastAPI application
After=network.target
[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/fastapi-app
ExecStart=/home/ubuntu/fastapi-app/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000
Restart=always
[Install]
WantedBy=multi-user.target
- Start the FastAPI service:
sudo systemctl daemon-reload
sudo systemctl enable fastapi
sudo systemctl start fastapi
sudo systemctl status fastapi
Step 4: Configure Nginx as a Reverse Proxy
- Create a new Nginx configuration file:
sudo nano /etc/nginx/sites-available/fastapi
Add the following configuration:
server {
listen 80;
server_name your-domain-or-ip;
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;
}
}
- Enable the configuration:
sudo ln -s /etc/nginx/sites-available/fastapi /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Test if Nginx is serving the FastAPI app:
curl http://localhost
Step 5: Set Up CI/CD with GitHub Actions
Create .github/workflows/ci.yml
for Continuous Integration:
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.10'
- name: Install dependencies
run: |
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
- name: Run Tests
run: |
source venv/bin/activate
pytest
Create .github/workflows/cd.yml
for Continuous Deployment:
name: CD
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_IP }}
username: ubuntu
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /home/ubuntu/fastapi-app
git pull origin main
source venv/bin/activate
pip install -r requirements.txt
sudo systemctl restart fastapi
sudo systemctl restart nginx
Step 6: Adding Secrets to GitHub
Go to your repository settings on GitHub and add the following secrets under Settings -> Secrets and Variables -> Actions
:
-
SERVER_IP
: Your EC2 instance IP -
SSH_PRIVATE_KEY
: Your private SSH key (from.pem
file)
Step 7: Test Your CI/CD Pipeline
- Push changes to GitHub:
git add .
git commit -m "Set up CI/CD"
git push origin main
- Go to GitHub Actions to verify CI/CD runs successfully.
- SSH into your instance and check if the application is running:
sudo systemctl status fastapi
sudo systemctl status nginx
Step 8: Fix the Missing book_id
Endpoint
@router.get("/{book_id}", response_model=Book, status_code=status.HTTP_200_OK) # New endpoint
async def get_book(book_id: int):
book = db.books.get(book_id)
if not book:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Book not found"
)
return book
Drawing a Lesson from This Project: Object-Oriented Programming (OOP) Concepts in Action
Throughout this project, we followed a structured and modular approach, which mirrors key principles of Object-Oriented Programming (OOP) in software development. Here’s how:
Encapsulation – Just like OOP encourages bundling data and behavior together in objects, we kept different parts of the system isolated and well-structured. The FastAPI service, Nginx configuration, CI/CD pipelines, and AWS deployment were all handled separately but worked together cohesively.
Abstraction – The CI/CD pipelines abstract away the complexity of deployment. Developers don’t need to manually set up servers every time they push changes. Instead, GitHub Actions automates the process, similar to how OOP hides internal logic behind methods and interfaces.
-
Modularity and Reusability – Our project followed a modular approach:
- The API routes were defined separately.
- The Nginx configuration was structured in a reusable way.
- CI/CD workflows were reusable across different environments. This reflects OOP’s emphasis on writing reusable and maintainable code.
Inheritance and Scalability – OOP allows new classes to extend existing ones without modifying them. Similarly, this deployment can be extended—new features, new API endpoints, or even another service (like a database) can be integrated without breaking the existing setup.
Conclusion
This project teaches an important software engineering lesson: structured, modular, and automated approaches lead to scalable and maintainable systems. Just as OOP helps manage complexity in code, well-structured CI/CD pipelines, infrastructure automation, and API design help manage complexity in real-world applications.
And
You have successfully deployed your FastAPI application on AWS EC2 with Nginx and automated deployment using GitHub Actions. Now, every push to the main
branch will trigger an automated deployment! 🚀
Top comments (2)
boyyyy, this is comprehensive and clear
Thank you, I'm glad it could help 😊
You can help others with it