DEV Community

AJAY SHRESTHA
AJAY SHRESTHA

Posted on • Edited on

Deploying Next.js App in AWS EC2 with Nginx and PM2

Deploying a Next.js application on an AWS EC2 instance involves several steps. This guide will walk you through setting up an Ubuntu server, installing and configuring Nginx as a reverse proxy, and using PM2 to manage your next.js application process.

Connect to your instance via SSH, and proceed with the necessary setup.

Step 1:Update and Install Dependencies
Update the package lists and install the necessary packages:

sudo apt update
sudo apt upgrade -y
sudo apt install -y nodejs
Enter fullscreen mode Exit fullscreen mode
# Install npm and pm2
sudo apt install npm

sudo npm install pm2@latest -g
pm2 startup
Enter fullscreen mode Exit fullscreen mode

Step 2: Organizing project structure
Create directories for organizing your project:

cd
mkdir repo.git app conf logs
Enter fullscreen mode Exit fullscreen mode

These directories will respectively hold your Git repository, application code, configuration files, and logs, which are neatly separated, making it easier to manage and maintain the application through its lifecycle.

Step 3: Initialize and Configuring Git Repository
Initialize a bare Git repository. A bare repository is used to manage code collaboration without working copies.

cd repo.git
git init --bare
git --bare update-server-info

# Configure the repository to work with our deployment setup
git config core.bare false
git config receive.denycurrentbranch ignore
git config core.worktree /home/ubuntu/app/
Enter fullscreen mode Exit fullscreen mode

The core.bare false configuration makes the repository behave like a non-bare repository. The receive.denycurrentbranch ignore allows us to push to the currently checked-out branch. The core.worktree configuration points to the directory where our application code will live.

Create a Post-Receive Hook
A Git hook is a script that is executed at certain points in the Git workflow. We'll use a post-receive hook to automatically deploy the code whenever a push is made to the repository.

cat > hooks/post-receive <<EOF
#!/bin/bash
git checkout -f
cd /home/ubuntu/app
npm install
npm run build && pm2 restart pm2.json
EOF
Enter fullscreen mode Exit fullscreen mode
# Make the script executable
chmod +x hooks/post-receive
Enter fullscreen mode Exit fullscreen mode

Step 4: Configure pm2 using pm2.json
Create a pm2.json file in app directory.

{
  "apps": [
    {
      "name": "project_name",
      "instances": "max",
      "exec_mode": "cluster",
      "script": "npm",
      "args": "start",
      "cwd": "/home/ubuntu/app/",
      "env": {
        "HOST": "127.0.0.1",
        "PORT": "3000",
        "NODE_ENV": "production"
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Don't Forget to change project name and cwd (current working directory)

Step 5: Adding remote repository in local machine
On your local machine, add the remote repository and push the code:

git remote add prod ubuntu@ip_address:/home/ubuntu/repo.git/
ssh-copy-id ubuntu@ip_address
git push prod master
Enter fullscreen mode Exit fullscreen mode

Step 6: Installing and Configuring Nginx
Install and configure Nginx:

sudo apt install nginx
sudo systemctl enable nginx
sudo rm /etc/nginx/sites-enabled/default
Enter fullscreen mode Exit fullscreen mode
vi conf/nginx.conf
Enter fullscreen mode Exit fullscreen mode

Add the following configuration in nginx.conf:

server {
    listen 80;
    listen [::]:80;
    index index.html;
    server_name domain_name.com;

    access_log /home/ubuntu/logs/nginx.access.log;
    error_log /home/ubuntu/logs/nginx.error.log;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;

        # Headers for WebSocket support
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';

        # Preserve the original host and bypass cache for WebSocket requests
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;

        # Real IP headers
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # Custom buffer and header sizes to handle large headers
        proxy_buffer_size 16k;
        proxy_buffers 4 32k;
        proxy_busy_buffers_size 64k;

        # Timeout settings for handling slow responses
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;

        # Disable response caching
        proxy_no_cache 1;
        proxy_cache_bypass 1;

        # Redirect handling
        proxy_redirect off;
    }
}
Enter fullscreen mode Exit fullscreen mode

Don't forget to replace domain_name with your own domain.

Soft-link this configuration to nginx conf.d directory

sudo ln -s /home/ubuntu/conf/nginx.conf /etc/nginx/conf.d/django_project.conf
Enter fullscreen mode Exit fullscreen mode

Step 6: Securing Server with SSL (Optional)
Install Certbot and configure SSL:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx
# Follow the on-screen instructions to complete the setup.
Enter fullscreen mode Exit fullscreen mode

Step 7: Check configuration and restart nginx
Test the Nginx configuration and restart the service:

sudo nginx -t
sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

By following this guide, you will get successfully deployed your Next.js application on an AWS EC2 instance running Ubuntu, with Nginx as a reverse proxy and PM2 to manage the application process.

Top comments (0)