How I Deployed My First Full Stack Node.js App on AWS EC2: A Complete Guide

Gedion DanielGedion Daniel
4 min read

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:

  1. Log into AWS Console and go to EC2

  2. Click "Launch Instance"

  3. Choose "Ubuntu Server 22.04 LTS" (I find it most beginner-friendly)

  4. Select t2.micro for the free tier

  5. Create a new key pair (save the .pem file safely!)

  6. 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)

  1. Connection Refused Errors

    • Check if MySQL is running: sudo systemctl status mysql

    • Verify port availability: sudo netstat -tulpn | grep LISTEN

  2. Permission Issues

    • Use sudo chown -R ubuntu:ubuntu /var/www/html

    • Check logs: sudo tail -f /var/log/nginx/error.log

  3. 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! ๐Ÿš€

0
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.