How I Deployed My First Full Stack Node.js App on AWS EC2: A Complete Guide
Hey there! ๐ I remember how overwhelming it felt when I first tried to deploy a full stack application on AWS. After lots of trial and error, I've put together this guide to help you deploy your Node.js app with a React frontend and MySQL database on a single EC2 instance. Let's dive in!
Prerequisites
An AWS account
A Node.js application with React frontend
Basic knowledge of Linux commands
SSH client installed on your computer
Your application code on GitHub
Step 1: Setting Up Your EC2 Instance
First things first, let's get your server ready:
Log into AWS Console and go to EC2
Click "Launch Instance"
Choose "Ubuntu Server 22.04 LTS" (I find it most beginner-friendly)
Select t2.micro for the free tier
Create a new key pair (save the .pem file safely!)
In Security Groups, allow these inbound rules:
SSH (Port 22)
HTTP (Port 80)
HTTPS (Port 443)
Custom TCP (Your Node.js port, typically 3000)
Custom TCP (MySQL port 3306)
Step 2: Connecting to Your Instance
# First, set the right permissions for your key file
chmod 400 your-key.pem
# Connect to your instance
ssh -i your-key.pem ubuntu@your-ec2-public-dns
Step 3: Setting Up the Environment
Let's install everything we need:
# Update package list
sudo apt update
# Install Node.js and npm
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
# Install MySQL
sudo apt install mysql-server
# Install Nginx (we'll use this as a reverse proxy)
sudo apt install nginx
# Install PM2 for process management
sudo npm install -g pm2
Step 4: Setting Up MySQL
Here's how to secure your database:
# Secure MySQL installation
sudo mysql_secure_installation
# Log into MySQL
sudo mysql
# Create your database and user
CREATE DATABASE your_database;
CREATE USER 'your_username'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON your_database.* TO 'your_username'@'localhost';
FLUSH PRIVILEGES;
Step 5: Deploying Your Application
Now for the fun part - getting your code running:
# Clone your repository
git clone your-repository-url
# Install dependencies for backend
cd your-backend-directory
npm install
# Install dependencies for frontend
cd ../your-frontend-directory
npm install
npm run build
# Move your frontend build to Nginx
sudo mv build/* /var/www/html/
Step 6: Setting Up Nginx as Reverse Proxy
Create a new Nginx configuration:
sudo nano /etc/nginx/sites-available/your-app
Add this configuration:
server {
listen 80;
server_name your-domain.com;
# Frontend
location / {
root /var/www/html;
try_files $uri $uri/ /index.html;
}
# Backend API
location /api {
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;
}
}
Enable the configuration:
sudo ln -s /etc/nginx/sites-available/your-app /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl restart nginx
Step 7: Running Your Application
Let's use PM2 to keep your app running:
# Start backend
cd your-backend-directory
pm2 start app.js --name "backend"
# Save PM2 configuration
pm2 save
# Set PM2 to start on boot
pm2 startup
Environment Variables
Don't forget to set up your environment variables! Create a .env file:
nano .env
Add your variables:
DB_HOST=localhost
DB_USER=your_username
DB_PASSWORD=your_password
DB_NAME=your_database
NODE_ENV=production
Common Issues I Faced (And How to Fix Them)
Connection Refused Errors
Check if MySQL is running:
sudo systemctl status mysql
Verify port availability:
sudo netstat -tulpn | grep LISTEN
Permission Issues
Use
sudo chown -R ubuntu:ubuntu /var/www/html
Check logs:
sudo tail -f /var/log/nginx/error.log
Application Not Starting
Check PM2 logs:
pm2 logs
Verify environment variables:
pm2 env 0
Monitoring Your Application
I recommend setting up basic monitoring:
# Monitor processes
pm2 monit
# Check Nginx access logs
sudo tail -f /var/log/nginx/access.log
# Monitor system resources
htop
Final Thoughts
Whew! That was a lot, right? Don't worry if things don't work perfectly the first time - deployment always involves some debugging. Keep your SSH terminal open and watch those logs! Remember to always backup your database regularly and keep your security groups as restrictive as possible.
If you're planning to use this in production, don't forget to:
Set up HTTPS using Let's Encrypt
Configure regular backups
Set up monitoring alerts
Implement proper logging
Good luck with your deployment! Drop a comment below if you run into any issues - I'm happy to help! ๐
Subscribe to my newsletter
Read articles from Gedion Daniel directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Gedion Daniel
Gedion Daniel
I am a Software Developer from Italy.