Beginner's Guide to Running a Next.js App on AWS EC2 (Ubuntu) with Nginx

Deploying a Next.js app on AWS EC2 can seem daunting, especially if you're working with a lightweight server like a t2.micro instance. This guide simplifies the process by walking you through building your app locally, transferring production-ready files, and configuring Nginx as a reverse proxy. With step-by-step instructions, you'll have your app up and running efficiently and securely.

Prerequisites

Before diving in, make sure you have the following:

  • An AWS Account: Sign up here.
  • A Next.js App: If you don't have one, you can create a new app quickly using the following command:
npx create-next-app@latest

This command scaffolds a basic Next.js app, providing a great starting point.

Step 1: Launch an EC2 Instance

  1. Log in to the AWS Console and navigate to the EC2 Dashboard.
  2. Click Launch Instance to create a new virtual server.
    • Select Ubuntu: Choose Ubuntu 22.04 (or the latest stable version).
    • Instance Type: Use t2.micro (eligible for the free tier).
    • Security Groups: Configure the following:
      • Allow SSH (port 22) from your IP for secure access.
      • Allow HTTP (port 80) and HTTPS (port 443) for web traffic.
    • Key Pair: Create or use an existing key pair to enable secure SSH access.
  3. Launch your instance and note the public IP address for later.

Step 2: Build Locally

Building the app locally reduces server load and ensures a smoother deployment process.

Navigate to your Next.js project on your local machine:

cd your-app

Install all dependencies:

npm install

Build the app for production:

npm run build

This command generates the .next folder, which contains the optimized production build.

Prepare files for deployment by zipping the build and essential files:

zip -r build.zip .next package.json package-lock.json

By only including essential files, you reduce the size of the transferred data.

Step 3: Transfer Build Files to the Server

Transfer the zipped build files to the EC2 instance using scp:

scp -i path/to/key.pem build.zip ubuntu@<your-ec2-ip>:/home/ubuntu

Connect to the server via SSH:

ssh -i path/to/key.pem ubuntu@<your-ec2-ip>

Install the unzip utility (if not already installed):

sudo apt update
sudo apt install unzip -y

Unzip the transferred build:

unzip build.zip

Step 4: Set Up Node.js on EC2

Install the latest LTS version of Node.js (22.x at the time of writing):

curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs

Confirm the installation:

node -v
npm -v

Install PM2 to manage the Next.js app:

sudo npm install -g pm2

Step 5: Start the App

Install only production dependencies to keep the instance lightweight:

npm install --production

Start the Next.js app using PM2:

pm2 start "npm start" --name "nextjs-app"

Save the PM2 process to ensure it restarts on reboot:

pm2 save

Step 6: Install and Configure Nginx

Install Nginx:

sudo apt install nginx -y

Configure Nginx to serve as a reverse proxy:

Open the default configuration file:

sudo nano /etc/nginx/sites-available/default

Add the following configuration:

server {
    listen 80;
    server_name <your-ec2-ip>;

    location / {
        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;
    }
}

Test the Nginx configuration:

sudo nginx -t

Restart Nginx to apply the changes:

sudo systemctl restart nginx

Step 7: Secure Your App with HTTPS

Install Certbot for managing SSL certificates:

sudo apt install certbot python3-certbot-nginx -y

Obtain a free SSL certificate for your domain:

sudo certbot --nginx -d <your-domain>

Restart Nginx to apply the SSL configuration:

sudo systemctl restart nginx

Test SSL auto-renewal with a dry run:

sudo certbot renew --dry-run

To manually renew certificates, use:

sudo certbot renew

After renewing certificates, restart Nginx:

sudo systemctl restart nginx

Conclusion

By building your Next.js app locally and transferring only the production-ready files, you keep your EC2 instance lightweight and efficient. Configuring Nginx as a reverse proxy and securing your app with SSL ensures optimal performance and security.

Wei-Ming Thor

I create practical guides on Software Engineering, Data Science, and Machine Learning.

Creator of ApX Machine Learning Platform

Background

Full-stack engineer who builds web and mobile apps. Now, exploring Machine Learning and Data Engineering. Read more

Writing unmaintainable code since 2010.

Skill/languages

Best: JavaScript, Python
Others: Android, iOS, C, React Native, Ruby, PHP

Work

Engineering Manager

Location

Kuala Lumpur, Malaysia

Open Source
Support

Turn coffee into coding guides. Buy me coffee