The First Time "Localhost" Isn't Enough
There's a moment every developer hits.
Your project works. It runs perfectly on your machine. You're proud of it. And then someone asks — "Cool, can I see it?"
And you realize... you have no answer. Because it only lives on your laptop.
That was me not too long ago. I had a working Node.js/Express app, a GitHub repo, and zero idea how to put it on the actual internet. AWS kept coming up everywhere — tutorials, job descriptions, YouTube videos — but it felt enormous and intimidating.
So I decided to just try it. Break things. Figure it out.
This blog is exactly what I wish I had that day. A plain, honest, step-by-step guide to deploying your first Node.js app on AWS — from local machine to live URL.
Let's go.
What We're Working With
Before we start, here's what this guide assumes:
- You have a Node.js/Express app that runs locally with
npm start - Your project is (or will be) on GitHub
- You have an AWS account (free tier works perfectly for this)
That's it. No prior cloud experience needed.
Here's the full journey we'll take:
Local machine → GitHub → AWS EC2 → Live on the internet
Step 1: Test Your App Locally First
This sounds obvious, but it matters more than you think.
Before touching AWS, make sure your app runs cleanly on your machine:
npm install
npm start
Open http://localhost:3000 (or whatever port you're using) and confirm everything works. Check your routes, test your endpoints, make sure there are no crashes.
Why this matters: Debugging on a remote server is ten times harder than debugging locally. Fix all issues here first — it'll save you hours later.
Also make sure your package.json has a proper start script:
"scripts": {
"start": "node index.js"
}
Step 2: Push Your Project to GitHub
Your EC2 server will pull your code directly from GitHub, so this step is essential.
If you haven't already:
git init
git add .
git commit -m "initial commit"
git remote add origin https://github.com/yourusername/your-repo.git
git push -u origin main
⚠️ Important: Make sure your .env file is in .gitignore before pushing. You never want secret keys, database passwords, or API credentials on GitHub — even in a private repo.
# .gitignore
node_modules/
.env
Push your code, verify it's visible on GitHub, and move to the next step.
Step 3: Create Your AWS EC2 Instance
This is where the cloud part begins. EC2 is essentially a virtual computer that lives in AWS's data center — and you're about to rent one.
- Log into AWS Console
- Search for EC2 and click Launch Instance
- Fill in the details:
-
Name: give it something meaningful like
my-first-app - AMI: choose Ubuntu Server 22.04 LTS (free tier eligible)
-
Instance type:
t2.micro(free tier — perfect for this)
-
Name: give it something meaningful like
-
Key pair: Create a new key pair, name it, and download the
.pemfile. Don't lose this — it's the only way to SSH into your server. - Leave everything else as default for now and click Launch Instance
Your server will be up and running in about a minute.
Step 4: SSH Into Your Server
Now we're going to remotely connect to your EC2 instance — like opening a terminal on a computer that lives in Amazon's data center.
First, find your server's Public IPv4 address from the EC2 dashboard.
Then in your local terminal:
chmod 400 your-key-file.pem
ssh -i your-key-file.pem ubuntu@your-public-ip
Replace your-key-file.pem with your actual key file name and your-public-ip with your EC2's IP address.
If everything is set up correctly, you'll see a welcome screen from Ubuntu. You're now inside your server. 🎉
Step 5: Update the Server
First things first — always update a fresh server before installing anything:
sudo apt update && sudo apt upgrade -y
This pulls the latest package lists and upgrades any outdated packages. It takes a minute or two. Let it finish.
Step 6: Install Node.js and npm
Your server is a fresh Ubuntu machine — it has nothing installed. Let's add Node.js:
sudo apt install -y nodejs npm
Verify the installation:
node -v
npm -v
You should see version numbers for both. If you do, you're ready to move on.
Step 7: Clone Your Project from GitHub
Now let's bring your code onto the server:
git clone https://github.com/yourusername/your-repo.git
cd your-repo
Then install your project's dependencies:
npm install
This recreates your node_modules folder on the server using your package.json.
Step 8: Create Your .env File
Remember how we kept .env out of GitHub? Now we need to recreate it manually on the server.
nano .env
Type out your environment variables:
PORT=3000
DATABASE_URL=your_database_url
API_KEY=your_api_key
Save and exit: Ctrl + X, then Y, then Enter.
This is the correct way to handle secrets on a server — never in your repo, always added manually.
Step 9: Start Your App
The moment of truth:
npm start
If everything is configured correctly, you'll see your server start up — the same output you see locally, but now it's running on AWS.
Open your browser and visit:
http://your-public-ip:3000
Your app is live on the internet. 🚀
Step 10: App Running but Still Not Visible? Fix Your Security Group
This is the most common gotcha for first-time deployments.
Your app is running fine on the server — npm start shows no errors — but when you open http://your-public-ip:3000 in the browser, it just times out or refuses to connect.
The fix: open port 3000 in your EC2 Security Group.
AWS blocks all incoming traffic by default. You have to explicitly allow it:
- Go to your EC2 Dashboard → click your instance
- Go to the Security tab → click the Security Group link
- Click Edit Inbound Rules and add:
| Type | Protocol | Port | Source |
|---|---|---|---|
| SSH | TCP | 22 | My IP |
| HTTP | TCP | 80 | Anywhere (0.0.0.0/0) |
| Custom TCP | TCP | 3000 | Anywhere (0.0.0.0/0) |
- Click Save rules
Now refresh your browser — your app should load instantly.
Port 22 lets you SSH in. Port 3000 lets the world reach your app. Port 80 is for standard HTTP — useful when you later point a domain to your server.
💡 If your app uses a different port (like 5000 or 8080), open that port instead of 3000.
One More Thing: Keep It Running
There's one problem with npm start — the moment you close your terminal, the app stops.
To keep it running even after you disconnect, install pm2:
sudo npm install -g pm2
pm2 start index.js
pm2 startup
pm2 save
Now your app will keep running in the background — even if the server restarts.
The Full Deployment Checklist
✅ App tested locally with npm start
✅ .env added to .gitignore
✅ Code pushed to GitHub
✅ EC2 instance launched (Ubuntu, t2.micro)
✅ Key pair downloaded safely
✅ SSH into server
✅ Server updated (apt update && upgrade)
✅ Node.js and npm installed
✅ Repo cloned and npm install run
✅ .env file created manually on server
✅ npm start — app is running on server
✅ Security group inbound rules configured (ports 22, 80, 3000)
✅ App visible at public-ip:3000
✅ pm2 set up to keep it running
Closing Thoughts
The first deployment always feels like climbing a mountain. There are a dozen steps, a few moments of panic, and at least one "why isn't this working" that turns out to be a typo.
But when that URL opens in your browser and your app loads — on a real server, accessible to anyone in the world — it's a completely different feeling from seeing it on localhost.
That gap between "it works on my machine" and "it works on the internet" is where a lot of beginners get stuck. Hopefully this guide helps you cross it a little faster than I did.
Deploy something. Break it. Fix it. That's how it works. ☁️
Have questions or got stuck at a specific step? Drop a comment and I'll do my best to help! 👇
I'm Anany Dubey — a student documenting my learning journey one deployment at a time. Follow along for more.
Top comments (2)
"Cool, can I see it?" and realizing it only lives on your laptop is the exact moment localhost stops being enough, and you captured why AWS feels so intimidating: it's not one skill, it's a dozen unfamiliar concepts (regions, security groups, IAM, SSH keys) arriving at once, right when you just wanted a URL to share. The "just try it, break things, figure it out" approach is genuinely the fastest way through, because the fear is mostly of the unknown and the unknown shrinks the instant you've done it once. Two things worth adding to a guide like this as you grow it: lock down the security group early (an open 0.0.0.0 SSH port is the most common beginner footgun and gets scanned within minutes), and set a billing alert day one so a forgotten instance doesn't surprise you. Both are cheap insurance against the two ways first deploys actually hurt people. I care about exactly this gap with Moonshift, the leap from "works on my machine" to "live and safe on the internet" is where most builders stall. What part of the AWS setup ended up being less scary than it looked once you'd done it?
Probably SSH. Before deploying, key pairs and terminal access felt intimidating, but after my first successful login it was surprisingly straightforward. Same with security groups—they sounded complex until I realized they're basically just firewall rules. Looking back, AWS wasn't hard because of any one concept; it was the number of new concepts hitting at once.