A practical guide to claiming AWS free credits, launching a cost-optimized EC2 instance, and running a production-ready Node.js backend — without breaking the bank.
Whether you're learning DevOps, building a side project, or deploying a Node.js backend, AWS is one of the best places to start — especially when you know how to keep costs near zero.
This guide walks you through:
Head to https://aws.amazon.com and sign up. You'll need:
Once your account is created, AWS automatically gives you:
| Benefit | Details |
|---|---|
| Free Tier | 750 hours/month of t2.micro or t3.micro EC2 for 12 months |
| Free Storage | 30 GB EBS storage per month |
| Free Data Transfer | 100 GB outbound data per month |
| Startup Credits | Up to $100–$1,000 if eligible via AWS Activate |
💡 Tip: AWS Activate is the single best way to get $100–$1,000 in free credits beyond the free tier. It's designed for startups and developers, and is free to apply for.
How to apply:
Other credit sources to check:
Always set a billing alert so you never get a surprise charge.
AWS Console → Billing → Budgets → Create Budget → Cost Budget
Set threshold: $5 (to catch anything slipping past free tier)
Also check Cost Explorer monthly to see where your usage is going.
Log into https://console.aws.amazon.com, search for EC2, and click Launch Instance.
Here's the exact setup that keeps costs minimal while being powerful enough for Node.js + DevOps learning:
Ubuntu Server 24.04 LTS
Architecture: 64-bit (x86)
Ubuntu LTS is preferred because:
t3.micro
Why t3.micro? | |
|---|---|
| Cost | |
| RAM | 1 GB |
| vCPUs | 2 (burstable) |
| Good for | Node.js backend, Nginx, PM2, Jenkins learning |
⚠️ Warning: Avoid
t2.mediumor larger unless absolutely needed — they exit the free tier and cost real money instantly.
Type: RSA
Format: .pem
Critical: Download and store your
.pemfile safely. If you lose it, you permanently lose SSH access to your server.
Recommended: Store it in ~/.ssh/ on your local machine and set permissions:
chmod 400 ~/.ssh/aws-devops-key.pem
Only open what you actually need:
| Port | Protocol | Source | Purpose |
|---|---|---|---|
| 22 | SSH | My IP only | SSH access |
| 80 | HTTP | Anywhere | Web traffic |
| 443 | HTTPS | Anywhere | Secure web traffic |
| 3000 | TCP | Anywhere | Temporary — for backend testing only |
🚨 Important: Always restrict port 22 to your IP only. Exposing SSH to
0.0.0.0/0(Anywhere) is the #1 cause of compromised EC2 instances. Remove port 3000 access once Nginx is configured as a reverse proxy.
8 GB gp3 SSD
gp3 is cheaper and faster than gp2. 8 GB is enough for Ubuntu + Node.js + Jenkins + Docker learning. Don't go above 30 GB or you'll exit the free tier storage limit.
After clicking Launch Instance, wait 1–2 minutes, then grab your Public IPv4 address from the EC2 dashboard.
Connect via SSH:
ssh -i ~/.ssh/aws-devops-key.pem ubuntu@YOUR_PUBLIC_IP
sudo apt update && sudo apt upgrade -y
Always run this first on a fresh instance.
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
Verify:
node -v # Should output v20.x.x
npm -v
sudo apt install git -y
# For traceroute / network apps:
sudo apt install -y traceroute mtr dnsutils net-tools
git clone https://github.com/YOUR_USERNAME/YOUR_REPO.git
cd YOUR_REPO
Create your .env file:
nano .env
PORT=3000
NODE_ENV=production
SUPABASE_URL=YOUR_SUPABASE_URL
SUPABASE_KEY=YOUR_SUPABASE_KEY
OPENAI_API_KEY=YOUR_OPENAI_KEY
ADMIN_API_KEY=SUPER_SECRET_KEY
Save with CTRL+O → ENTER → CTRL+X.
npm install
npm start
Quick test — open in browser:
http://YOUR_PUBLIC_IP:3000/api/health
PM2 is a process manager that keeps your Node.js app running even after reboots.
sudo npm install -g pm2
pm2 start src/server.js --name my-backend
pm2 save
pm2 startup
Run the command that pm2 startup outputs (it starts with sudo env PATH=...).
Install Nginx:
sudo apt install nginx -y
Configure it:
sudo nano /etc/nginx/sites-available/default
Replace the contents with:
server {
listen 80;
server_name _;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Restart Nginx:
sudo systemctl restart nginx
Now your backend is accessible at:
http://YOUR_PUBLIC_IP/api/health
No :3000 needed anymore. You can now remove port 3000 from your Security Group inbound rules.
You'll need a domain name pointed to your EC2's IP for this step.
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx
Certbot will automatically configure SSL and auto-renew certificates.
💡 Tip: The biggest AWS bill surprises come from forgetting resources are running. Build these habits early.
| Habit | Why It Matters |
|---|---|
| Stop EC2 when not in use | Stopped instances don't incur compute charges |
Use t3.micro only | Stays within free tier for 12 months |
| Don't allocate Elastic IPs you're not using | Idle Elastic IPs cost ~$0.005/hr |
| Set 8 GB storage, not more | >30 GB exits the free tier |
| Delete unused snapshots | Snapshots cost $0.05/GB/month |
| Enable billing alerts at $1 and $5 | Get notified before any real charges |
| Use AWS Cost Explorer weekly | Catch unexpected charges early |
| Use free credits for experimentation | Save real money for production |
Once your server is running, this same setup is your playground for:
t3.small when ready)| Step | Action |
|---|---|
| 1 | Create AWS account → get 12 months free tier |
| 2 | Apply to AWS Activate for extra $100–$1,000 credits |
| 3 | Set billing alerts at $5 |
| 4 | Launch t3.micro with Ubuntu 24.04, 8 GB gp3 |
| 5 | Restrict SSH to your IP only |
| 6 | Install Node.js, PM2, Nginx |
| 7 | Use Nginx as reverse proxy (close port 3000) |
| 8 | Optionally add HTTPS via Certbot |
| 9 | Stop instance when not in use |
This setup costs $0/month for the first 12 months with AWS Free Tier, and roughly $7–10/month after that — making it one of the most affordable ways to run a real backend in the cloud.
Happy shipping! 🚀