Deploying FASTApi on EC2

Shad RezaShad Reza
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

Port 8000 to Port 8005

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

Port 8006

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)

Port 8000

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

Shad Reza
Shad Reza