How to Deploy Nextjs on AWS-EC2 (Nginx, Ubuntu, SSL)
Many developers out there could be asking themselves the steps to successfully deploy a Nextjs application in AWS. While Vercel is a known cloud platform, praised for its user-friendly interface and straightforward deployment process, AWS is a comprehensive cloud service provider that offers a wide range of services. It’s true that you could deploy easier your app in Vercel, still, if you are reading this article is because we may share similar perspectives about organization.
Next.js is a web development framework that excels in delivering high-performance web applications. Its key features, including Server-Side Rendering (SSR) and Static Site Generation (SSG), boost your site's speed and SEO ranking. With Next.js, you can reap the benefits of server-generated HTML, leading to faster load times and an SEO-friendly architecture.
Once you have setup a secured connection to your EC2 instance, then follow the steps listed below.
Step 1: This should be your initial screen before heading forward.

Step 2: Update
Run the following command to update all system packages.
sudo apt-get update

Download and import the Nodesource GPG key
sudo apt-get install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
Step 3: Create a deb repository and install any supported Nodejs version
NODE_MAJOR=21
// set the Node version to install
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
// create a deb repository
The Nodejs version is set by running "NODE_MAJOR= #version" - where #version can be 16, 18, 20, 21, etc
Let's set Nodejs version to 21 - NODE_MAJOR=21
sudo apt-get update
// update your system variables
sudo apt-get install nodejs -y
// install Nodejs using the version stated previously

To Uninstall Nodejs you can run the following command
sudo apt-get purge nodejs &&\rm -r /etc/apt/sources.list.d/nodesource.list &&\rm -r /etc/apt/keyrings/nodesource.gpg
// uninstall nodejs entirely
Verify the nodejs version you just installed

Step 4: Create an SSH Key Pair
We need to create an SSH key pair to setup a secured communication with your GitHub repository.
Use the following procedure to generate an SSH key pair on UNIX and UNIX-like systems:
1. Run the ssh-keygen command. You can use the -t option to specify the type of key to create. For example, to create an RSA key, run: ssh-keygen -t rsa
2. You can use the -b option to specify the length (bit size) of the key, as shown in the following example: ssh-keygen -b 2048 -t rsa
ssh-keygen -b 2048 -t rsa
// create your ssh key using this command

Step 5: Copy the value of this public SSH key
Since by default you are located at "./Home" directory, you would only need to access the "./.ssh" directory in order to gather the public key.
cd .ssh
// Enter .ssh directory
ls
// List all files inside this directory
cat id_rsa.pub
// open the file id_rsa.pub and copy its content

Step 6: Open your GitHub repository
Access its "Settings"

Scroll down the side left menu until you find "Deploy keys"
Press the button "Add deploy key"

Then, input a name for this key and enter the value you copied in the text area, under "Key".
There is no need to "Allow write access" since you would be only reading from your remote EC2 Instance.

Step 7: Copy the SSH command linked to your repository

Step 8: Now get back to your Putty session
Write the following command to clone your GitHub repository
git clone "your GitHub copied command"
// Enter .ssh directory

Step 9: Install all dependencies
ls
// List all directories inside
cd "your directory name"
// Access your application main directory
npm i
// Install all dependencies

Step 10: Generate an optimized version of your application for production.
npm run build
npm install sharp
// for nextjs to use automatically over Image optimization

Step 11: Install PM2
We require a solution for handling the Next.js process, ensuring it continues running in the background even after closing the terminal. To fulfill this need, PM2 serves as the ideal tool for managing the process.
• Install PM2 using the below command:
sudo npm install pm2 -g
Step 12: Run Next.js via PM2 in the background
We need to run, stop and restart the Next.js application even after the terminal is closed. This can be achieved using the PM2 tool.
Execute the below code to run Next.js with PM2:
pm2 start npm --name nextjs-app -- run start -- -p 3000
We can also check the status of our nextjs-app by using the below command:
pm2 list nextjs-app

Step 13: Setup a Firewall
sudo ufw enable
// enable Firewall
sudo ufw status
// See firewall status
sudo ufw allow ssh
// Port 22
sudo ufw allow http
// Port 80
sudo ufw allow https
// Port 443

Step 14: Install Nginx
sudo apt install nginx

Step 15: Configure Nginx
Its main function in this deployment is a Reverse Proxy with Caching
Use the command below to modify its default file
sudo nano /etc/nginx/sites-available/default
Once you are inside the file, locate the "server_name" and "location /" part to replace it with the text provided below
server_name yourdomain.com www.yourdomain.com;
location / {
proxy_pass http://localhost:5000; #whatever port your app runs on
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;
}

Now, test the configuration you just changed.
sudo nginx -t
// Test the configuration for Nginx default
sudo service nginx restart
// Restart Nginx to load the new configurations

Step 16: Connect the Domain where you want to deploy this app, to this EC2 Instance
Copy the Public IP address indentifying this EC2 instance

Paste it in the main record "Type A" if you had it created before. If not, feel free to "Create record"

Here if you access your domain you will notice it is not secured. (Port 80 HTTP)

Step 17: Installing Let's Encrypt cerbot
sudo apt install certbot python3-certbot-nginx
//
sudo apt-get update
// update packages
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
// Request SSL/TLS certificates

If you refresh now your browser, you will notice that traffic is secured now.
