Deploying FASTApi on EC2

6 min read

Local Deployment
# Clone the project repository from GitHub
git clone https://github.com/shadreza/mist-indtr-2k25.git
# Navigate into the cloned project directory
cd mist-indtr-2k25
# Create a virtual environment named 'venv' using Python 3
python3 -m venv venv
# Activate the virtual environment to isolate dependencies
source venv/bin/activate
# Upgrade pip to the latest version
pip install --upgrade pip
# Install all dependencies listed in requirements.txt
pip install -r requirements.txt
# Start the FastAPI application using Uvicorn on port 8005, accessible externally
uvicorn main:app --host 0.0.0.0 --port 8005
As the EC2 was created beforehand, we need to access it using the registered PEM (Privacy Enhanced Mail) file.
Consider the PEM file as mist-indtr-2k25.pem
Now we need to run the following commands
# Set secure permissions to the private key file
# chmod = change mode (modifies file permissions)
# 400 = read-only for the owner
chmod 400 mist-indtr-2k25.pem
# ssh into the ec2 using the username of the ec2
# type yes => [Are you sure you want to continue connecting (yes/no/[fingerprint])?]
ssh -i mist-indtr-2k25.pem ubuntu@52.194.243.212
Why 52.194.243.212 ?
Security Groups Assigned to EC2
Script for simple FastApi Projects Initiation
we will create a new folder as the following
# creating a directory
mkdir mist-indtr-2k25-setup
# go into the folder
cd mist-indtr-2k25-setup
# make the script file
touch setup_fastapi_ec2.sh
paste the following code in the setup_fastapi_ec2.sh
#!/bin/bash
# -------------------------------
# FastAPI EC2 Setup Script
# Description: Automates deployment of 6 FastAPI apps on ports 8000โ8005
# Each app runs as a systemd service using Uvicorn inside a Python virtual environment
# -------------------------------
# ๐ก๏ธ Block 1: Ensure the script is run as root
if [[ "$EUID" -ne 0 ]]; then
# EUID != 0 means current user is not root
echo "โ Please run as root using sudo"
exit 1 # Exit with error code
fi
# ๐ง Block 2: Update and upgrade the OS packages
echo "๐ง [1/9] Updating system packages..."
apt update -y && apt upgrade -y # Non-interactive update and upgrade
echo "โ
System updated."
# ๐ฆ Block 3: Install required packages
echo "๐ฆ [2/9] Installing Python3, venv, pip, and Git..."
apt install -y python3 python3-venv python3-pip git # Install core tools
echo "โ
Python and Git installed."
# ๐ Block 4: Create multiple FastAPI app directories with a sample main.py
echo "๐ [3/9] Creating FastAPI app directories and sample code..."
for i in {0..5}; do
mkdir -p /home/ubuntu/app$i # Create app directories /app0 to /app5
chown ubuntu:ubuntu /home/ubuntu/app$i # Set ubuntu user as owner
# Generate a simple FastAPI app in each directory
cat <<EOF > /home/ubuntu/app$i/main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello from app$i"}
EOF
done
echo "โ
FastAPI app directories created (app0 to app5)."
# ๐ Block 5: Create a shared virtual environment for all apps
echo "๐ [4/9] Creating Python virtual environment..."
python3 -m venv /home/ubuntu/fastapi-venv # Create venv in specified path
chown -R ubuntu:ubuntu /home/ubuntu/fastapi-venv # Set ownership to ubuntu
echo "โ
Virtual environment created at /home/ubuntu/fastapi-venv."
# ๐ฆ Block 6: Install FastAPI and Uvicorn in the virtual environment
echo "๐ฆ [5/9] Installing FastAPI and Uvicorn in the virtual environment..."
/home/ubuntu/fastapi-venv/bin/pip install --upgrade pip # Upgrade pip
/home/ubuntu/fastapi-venv/bin/pip install fastapi uvicorn # Install packages
echo "โ
FastAPI and Uvicorn installed."
# โ๏ธ Block 7: Create a systemd service template to launch apps as services
echo "โ๏ธ [6/9] Creating systemd service template..."
cat <<'EOF' > /etc/systemd/system/fastapi-app@.service
[Unit]
Description=FastAPI App instance on port %i
After=network.target
[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/app%i
ExecStart=/home/ubuntu/fastapi-venv/bin/uvicorn main:app --host 0.0.0.0 --port 800%i
Restart=always
[Install]
WantedBy=multi-user.target
EOF
# The template uses %i to dynamically inject the app number (0 to 5)
# Each app runs on port 8000 + i
echo "โ
systemd service template created: fastapi-app@.service"
# ๐ Block 8: Reload systemd and enable all app instances
echo "๐ [7/9] Reloading systemd and enabling services..."
systemctl daemon-reexec # Reexec systemd (safeguard for upgrades)
systemctl daemon-reload # Reload systemd units
# Enable and start services fastapi-app@0 to fastapi-app@5
for i in {0..5}; do
systemctl enable fastapi-app@$i # Enable service to start on boot
systemctl restart fastapi-app@$i # Start/restart the service immediately
done
echo "โ
Services fastapi-app@0 to fastapi-app@5 enabled and started."
# ๐ Block 9: Allow incoming traffic through UFW (firewall)
echo "๐ [8/9] Configuring UFW firewall..."
ufw allow 22 # Allow SSH connections
ufw allow 8000:8005/tcp # Allow ports used by FastAPI apps
ufw --force enable # Enable UFW without interactive prompt
echo "โ
Firewall enabled. Ports 22 and 8000โ8005 are open."
# ๐ Final message
echo "๐ [9/9] Setup Complete!"
echo "๐ Test locally via: curl http://localhost:8000"
echo "๐ If accessing externally, ensure the EC2 security group allows inbound ports 8000โ8005"
Run Automation Script
# make the script executable
chmod +x ./setup_fastapi_ec2.sh
# run the script
./setup_fastapi_ec2.sh
Check APIs
Simple FAST API Project
See the Repo
What if we want to deploy this project in the EC2?
# Clone the GitHub repository containing the FastAPI project
git clone https://github.com/shadreza/mist-indtr-2k25.git
# Change into the newly cloned project directory
cd mist-indtr-2k25/
# Create a virtual environment named 'venv' using Python 3
python3 -m venv venv
# Activate the virtual environment (enables isolated Python environment)
source venv/bin/activate
# Upgrade pip to the latest version inside the virtual environment
pip install --upgrade pip
# Install all Python dependencies listed in requirements.txt
pip install -r requirements.txt
# Check the current status of the UFW firewall (to see which ports are open)
sudo ufw status
# Allow incoming TCP traffic on port 8006 (your FastAPI app's port)
sudo ufw allow 8006/tcp
# Recheck UFW status to confirm that port 8006 is now allowed
sudo ufw status
# Check if GNU Screen is installed (used to keep processes running in background)
screen --version
# Start a new screen session named 'fastapi' (press Ctrl + A then D to detach)
screen -S fastapi # Press Ctrl+A, then D to detach and leave it running in background
uflow allowed the incoming traffic but the aws network will not allow unless, we update the security group
Test in Ports 8000 ~ 8005
lets modify app0 corresponding to port 8000
# ๐ Navigate to the home directory of the 'ubuntu' user
cd /home/ubuntu
# ๐ List the contents of /home/ubuntu to confirm location and directories
ls
# ๐ Enter the target FastAPI app directory (app0)
cd app0
# ๐ List current files inside app0
ls
# ๐งน Delete all non-hidden files and folders to clear the directory
rm -rf ./*
# ๐ Confirm the directory is empty
ls
# โฌ๏ธ Clone the GitHub repository into the current directory (app0)
git clone https://github.com/shadreza/mist-indtr-2k25.git ./
# โ
Check that files are now cloned correctly in app0
ls
# ๐ Move back to the parent directory
cd ..
# ๐ Navigate into the separate setup directory containing restart script
cd mist-indtr-2k25-setup/
# โถ๏ธ Run the restart script (typically to restart FastAPI services via systemd)
./restart_servers.sh
# โ
Done! You can now retest the FastAPI apps on ports 8000โ8005 (or 8006 if configured)
The magic ๐ช restart_servers.sh
#!/bin/bash
# ๐ Restart Script for FastAPI Apps
# This script restarts FastAPI instances (app0 to app5) managed by systemd.
# Useful after code changes or virtualenv updates.
# ๐ฆ Loop through app indices 0 to 5
for i in {0..5}; do
# ๐ง Display which service is being restarted
echo "Restarting fastapi-app@${i}.service"
# โถ๏ธ Restart the FastAPI systemd service for app$i
sudo systemctl restart fastapi-app@${i}
done
0
Subscribe to my newsletter
Read articles from Shad Reza directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
