How to Host a Node.js Project on AWS EC2: A Complete Guide

How to Host a Node.js Project on AWS EC2: A Complete Guide

Introduction

Hosting your project on the cloud is a significant milestone in your development journey. While it can seem overwhelming at first—especially for beginners—this comprehensive guide will walk you through deploying a Node.js project on AWS EC2, step by step.

What you'll learn:

  • Setting up an EC2 instance
  • Configuring security groups
  • Deploying your code
  • Setting up Nginx as a reverse proxy
  • Installing SSL certificates
  • Creating automated services

Prerequisites:

  • An AWS account
  • A Node.js project ready for deployment
  • Basic familiarity with terminal commands

Table of Contents

  1. Spin Up an EC2 Instance
  2. Configure Security Groups
  3. Deploy Your Code
  4. Set Up Node.js Service
  5. Configure Nginx Reverse Proxy
  6. Install SSL Certificate
  7. Testing and Verification
  8. Conclusion

1. Spin Up an EC2 Instance

Step-by-Step Process

  1. Log into AWS Console

    • Visit AWS Console
    • Select your nearest region (top right corner)
  2. Launch Instance

    • Search for "EC2" in the services
    • Click Launch Instance
  3. Configure Instance

    • Name: Give your instance a meaningful name (e.g., "my-nodejs-app")
    • AMI: Choose Ubuntu Server 22.04 LTS
    • Instance Type: Select t2.micro (Free Tier eligible)
    • Key Pair: Create a new key pair for SSH access
    • Download the .pem file and store it securely
  4. Launch

    • Click Launch Instance

Success: Your EC2 instance is now running!


2. Configure Security Groups

Your Node.js application needs to be accessible from the internet. Let's configure the security groups to allow the necessary traffic.

Required Ports

Port

Purpose

Source

22

SSH Access

Anywhere (0.0.0.0/0)

80

HTTP Traffic

Anywhere

443

HTTPS Traffic

Anywhere

8080

Node.js App

Anywhere

Configuration Steps

  1. Navigate to Security Groups

    • Go to EC2 Dashboard → Instances
    • Select your instance → Security Tab
    • Click Edit Inbound Rules
  2. Add Rules

    Rule 1: SSH (Port 22) - Source: Anywhere
    Rule 2: HTTP (Port 80) - Source: Anywhere
    Rule 3: HTTPS (Port 443) - Source: Anywhere
    Rule 4: Custom TCP (Port 8080) - Source: Anywhere
    
  3. Save Changes

    • Click Save Rules

🔒 Security Note: For production, consider restricting SSH access to your IP address only.


3. Deploy Your Code

Method 1: Using rsync (Recommended)

From your local machine, sync your project to the EC2 instance:

rsync -avz --exclude 'node_modules' --exclude '.git' --exclude '.env' \
-e "ssh -i ~/.ssh/<your-key>.pem" \
. ubuntu@<your-ec2-ip>:~/app

Replace:

  • <your-key> with your actual key filename
  • <your-ec2-ip> with your instance's public IP

Method 2: Using Git (Alternative)

If your code is in a Git repository:

# SSH into your instance
ssh -i ~/.ssh/<your-key>.pem ubuntu@<your-ec2-ip>

# Clone your repository
git clone <your-repo-url> app
cd app

Install Node.js on EC2

SSH into your instance and install Node.js:

# SSH into your instance
ssh -i ~/.ssh/<your-key>.pem ubuntu@<your-ec2-ip>

# Update system packages
sudo apt update && sudo apt upgrade -y

# Install Node.js 20.x
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# Verify installation
node --version
npm --version

Install Dependencies

cd ~/app
npm install --production

4. Set Up Node.js Service

To ensure your application runs continuously and starts automatically on reboot, we'll create a systemd service.

Step 1: Create Environment File

sudo vim /etc/app.env

Add your environment variables:

NODE_ENV=production
PORT=8080
# Add other environment variables as needed

Set proper permissions:

sudo chmod 600 /etc/app.env
sudo chown ubuntu:ubuntu /etc/app.env

Step 2: Create Service File

sudo vim /etc/systemd/system/myapp.service

Add the following configuration:

[Unit]
Description=My Node.js Application
After=network.target multi-user.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/app
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production
EnvironmentFile=/etc/app.env
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=myapp
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target

Step 3: Start the Service

# Reload systemd configuration
sudo systemctl daemon-reload

# Enable service to start on boot
sudo systemctl enable myapp.service

# Start the service
sudo systemctl start myapp.service

Step 4: Verify Service Status

# Check service status
sudo systemctl status myapp.service

# View logs
sudo journalctl -u myapp.service -f

# Test the application
curl http://localhost:8080

Success: Your Node.js application is now running as a service!


5. Configure Nginx Reverse Proxy

Nginx will act as a reverse proxy, forwarding traffic from your domain to your Node.js application.

Step 1: Install Nginx

sudo apt install nginx -y

Step 2: Configure Firewall

sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable

Step 3: Create Nginx Configuration

sudo vim /etc/nginx/sites-available/myapp

Add the following configuration:

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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;
        proxy_cache_bypass $http_upgrade;
    }

    # Security: Block access to sensitive files
    location ~* (\.git|\.env|\.sql|\.zip|\.tar\.gz|\.DS_Store) {
        deny all;
    }
}

Step 4: Enable the Site

# Create symbolic link
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/

# Remove default site (optional)
sudo rm /etc/nginx/sites-enabled/default

# Test configuration
sudo nginx -t

# Reload Nginx
sudo systemctl reload nginx

Success: Nginx is now serving your application!


6. Install SSL Certificate

Secure your application with HTTPS using Let's Encrypt certificates.

Step 1: Install Certbot

sudo apt install python3-certbot-nginx -y

Step 2: Obtain SSL Certificate

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Follow the prompts:

  • Enter your email address
  • Agree to terms of service
  • Choose whether to redirect HTTP to HTTPS (recommended)

Step 3: Test Auto-Renewal

sudo certbot renew --dry-run

🔄 Auto-Renewal: Certificates automatically renew every 90 days.


7. Testing and Verification

Test Your Deployment

  1. Local Test (on EC2)

    curl http://localhost:8080
    
  2. Public Access Test

    • Visit http://yourdomain.com (should redirect to HTTPS)
    • Visit https://yourdomain.com
  3. Service Status Check

    sudo systemctl status myapp.service
    sudo systemctl status nginx
    

Troubleshooting

If your app isn't accessible:

  1. Check service status:

    sudo systemctl status myapp.service
    
  2. View application logs:

    sudo journalctl -u myapp.service -f
    
  3. Check Nginx logs:

    sudo tail -f /var/log/nginx/error.log
    
  4. Verify firewall settings:

    sudo ufw status
    

8. Conclusion

🎉 Congratulations! You've successfully deployed a Node.js application on AWS EC2 with:

What You've Accomplished

  • Cloud Deployment: Your app is now running on AWS EC2
  • Continuous Operation: Service automatically starts on reboot
  • Reverse Proxy: Nginx handles incoming traffic efficiently
  • SSL Security: HTTPS encryption with auto-renewing certificates
  • Production Ready: Proper security and performance configurations

Next Steps

  • Monitoring: Set up application monitoring (e.g., PM2, New Relic)
  • Backup Strategy: Implement regular backups
  • CI/CD Pipeline: Automate deployments with GitHub Actions
  • Load Balancing: Scale with multiple instances
  • Database: Add a managed database service

Useful Commands

# Restart your application
sudo systemctl restart myapp.service

# View real-time logs
sudo journalctl -u myapp.service -f

# Update your application
cd ~/app
git pull
npm install
sudo systemctl restart myapp.service

# Check SSL certificate status
sudo certbot certificates

Your Node.js application is now live and accessible to users worldwide! 🌍


Need Help? If you encounter any issues, check the troubleshooting section above or refer to the official documentation for AWS EC2, Nginx, and Certbot.

© 2025 Kumar Amrendram. All rights reserved.