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
- Spin Up an EC2 Instance
- Configure Security Groups
- Deploy Your Code
- Set Up Node.js Service
- Configure Nginx Reverse Proxy
- Install SSL Certificate
- Testing and Verification
- Conclusion
1. Spin Up an EC2 Instance
Step-by-Step Process
-
Log into AWS Console
- Visit AWS Console
- Select your nearest region (top right corner)
-
Launch Instance
- Search for "EC2" in the services
- Click Launch Instance
-
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
-
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
-
Navigate to Security Groups
- Go to EC2 Dashboard → Instances
- Select your instance → Security Tab
- Click Edit Inbound Rules
-
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
-
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
-
Local Test (on EC2)
curl http://localhost:8080
-
Public Access Test
- Visit
http://yourdomain.com
(should redirect to HTTPS) - Visit
https://yourdomain.com
- Visit
-
Service Status Check
sudo systemctl status myapp.service sudo systemctl status nginx
Troubleshooting
If your app isn't accessible:
-
Check service status:
sudo systemctl status myapp.service
-
View application logs:
sudo journalctl -u myapp.service -f
-
Check Nginx logs:
sudo tail -f /var/log/nginx/error.log
-
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.