🚀 The Beginning: A Daunting Challenge
If you had told me a few months ago that I’d be deploying a Flask API on an AWS EC2 instance, setting up a reverse proxy with Nginx, and configuring Gunicorn like a pro, I would have laughed and probably asked, "Me? Deploying a full-fledged API? Abeg, be serious." 😅
But here we are. I did it. And I’m still in awe.
I recently started learning Python, and honestly, taking on this project felt like staring at a mountain with no climbing gear. It was intimidating. The thought of wiring everything together—Flask, EC2, Systemd, Gunicorn, Nginx—felt like an impossible task. But if there's anything I've learned, it's that when something looks impossible, you just have to dive in, make mistakes, consult AI (a lot! 😂), and smash bugs until it works.
This is the story of how I locked in, barely remembered to eat, and refused to sleep until I got my FunNumberAPI up and running!
🔗 Full source code available on GitHub: FunNumberAPI
🎯 The Mission: Build & Deploy a Number Classification API
The goal was simple—at least, in theory.
I wanted to build an API that could take a number and tell you fun stuff about it:
✅ Is it Prime?
✅ Is it Perfect?
✅ Is it an Armstrong number? (Yes, I had to Google what that was. 😅)
✅ Is it Odd or Even?
✅ What's its digit sum?
✅ Can we fetch a random fun fact about it?
Sounds fun, right? Well, it was—until I had to deploy it. That’s where the real battle began.
🔥 The Struggle: A Battle with Errors
Everything that could go wrong, went wrong.
First, Flask was fine on my local machine, but when I tried to deploy it… boom. Errors left, right, and centre.
Then Gunicorn started misbehaving.
Then systemd refused to start my service.
Then NGINX acted like it had never met me before.
At some point, I asked myself, "Why am I doing this again?" But the stubborn part of me refused to give up. So I dug deep, Googled endlessly, consulted AI (shoutout to my robotic mentor, ChatGPT 😆), and slowly started making progress.
🔧 The Breakthrough: Step-by-Step Deployment
After hours of debugging, frustration, and moments of victory, I finally got my Flask app LIVE on an AWS EC2 instance! 🎉
Here’s how I did it:
🛠 Step 1: Building the API
I built the backend using Flask, ensuring that it could classify numbers correctly and fetch fun facts. The full implementation, including all helper functions, can be found in my GitHub repository:
🔗 API Implementation: FunNumberAPI/app.py
At this point, the API worked locally. But making it accessible to the world? That’s where the real battle began.
☁ Step 2: Deploying to AWS EC2
I launched an Ubuntu EC2 instance, opened inbound rules for 22 (SSH), 80 (HTTP), and 5000 (Custom TCP) and connected to the instance via SSH
Next, I set up the environment:
sudo apt update && sudo apt upgrade -y # Update system
sudo apt install python3-pip nginx -y # Install Python & Pip
python3 -m venv .venv # Create a virtual environment
source .venv/bin/activate # Activate the virtual environment
pip install flask gunicorn flask_cors requests # Install required libraries
Next, I cloned my repo
git clone https://github.com/MsOluwademilade/FunNumberAPI.git
cd FunNumberAPI
python3 app.py
Then I ran the app
gunicorn --bind 0.0.0.0:5000 app:app
Tested it: http://<public-ip-of-ec2>:5000/api/classify-number?number=371
✅
⚙ Step 3: Setting Up systemd for Service Management
To keep the API running in the background and restart it on failures, I created a systemd service:
sudo nano /etc/systemd/system/flask-app.service
And added:
[Unit] Description=Gunicorn instance to serve Flask app After=network.target
[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/FunNumberAPI ExecStart=/home/ubuntu/.venv/bin/gunicorn --workers 3 --bind 127.0.0.1:5000 app:app
Restart=always
[Install]
WantedBy=multi-user.target
Then, enabled and started the service:
sudo systemctl daemon-reload
sudo systemctl start flask-app
sudo systemctl enable flask-app
Now, even if the server rebooted, my API would start automatically.
🌐 Step 4: Configuring NGINX as a Reverse Proxy
To expose my API on port 80 and avoid manually specifying port 5000, I configured NGINX:
sudo nano /etc/nginx/sites-available/default
Replaced the contents with:
server {
listen 80;
server_name <public-ip-of-ec2>;
location / {
proxy_pass http://127.0.0.1:5000;
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;
}
}
Restarted NGINX
sudo nginx -t
sudo systemctl restart nginx
And finally, my API was live on:
http://<public-ip-of-ec2>/api/classify-number?number=371
🏆 Acknowledgements
- Huge thanks to the HNG12 DevOps mentors for introducing this daunting yet rewarding challenge—it pushed me beyond my limits and taught me so much.
- Flask for making Python APIs a breeze 🍃
- Numbers API for the fun facts 🔢
- You, for checking out this project! 🎉
🗨️ Final Thoughts
Deploying this API wasn’t just a technical challenge—it was a mental endurance test. There were moments when I felt stuck, times when I considered rewriting the entire thing, but pushing through taught me invaluable lessons about Flask, deployment, debugging, and perseverance.
🚀 If you’re new to backend development and cloud deployment, take on projects that scare you. You’ll learn more than you ever thought possible.
If you found this helpful, let’s connect! Drop a comment, share your own deployment struggles, or hit me up on GitHub. Let’s keep building! 🔥
Top comments (0)