Deploying a Next.js/React/Express App on EC2
October 15, 2025
This script is written for an Ubuntu EC2 instance.
1. System update and Nginx install:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install nginx2. Install Node.js via NVM, generate an SSH key, and clone the project:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
source ~/.bashrc
nvm install 20.15.1
nvm use 20.15.1
ssh-keygen -t rsa -b 4096 -C "your_email@example.com" -f ~/.ssh/id_rsa -N ""
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pubAdd the printed public key to your GitHub account settings, then:
git clone <repo-url> ~
cd <project-folder-name>
npm i
npm run build3. Configure Nginx as a reverse proxy (replace {folder_name} with your
project's name):
server {
listen 80;
server_name your_domain_name_or_public_ipv4;
location / {
proxy_pass http://127.0.0.1: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;
}
}sudo ln -s /etc/nginx/sites-available/{folder_name} /etc/nginx/sites-enabled
sudo nginx -t
sudo service nginx restart4. Process management with PM2:
npm i -g pm2
pm2 start npm --name "my-app" -- startMake sure your domain's DNS (e.g. AWS Route 53) points to the instance's public IPv4 address before this step.
5. HTTPS with Certbot:
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your_domain_namePM2 commands for other frameworks:
| Framework | PM2 command |
|---|---|
| Vite project | pm2 start npm --name "vite-app" -- run preview |
| Next.js server | pm2 start npm --name "next-app" -- start |
| Create React App | pm2 start "serve -s build -l 3000" --name react-app |
| Express.js server | pm2 start server.js --name "express-api" |
Redeploying after code changes:
cd <project-folder-name>
git pull
npm i
npm run build
pm2 list
pm2 restart <app_name_or_id>
pm2 list
pm2 logs <app_name_or_id> # if something looks wrongStatic PHP site, for reference:
server {
listen 80;
server_name your_domain_name_or_public_ip;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}
}