How To Deploy Next.js With PM2

Step 1: Initial setup

On local machine:

Install pm2.

npm i pm2 -g

Create a new Next.js app.

npx create-next-app
cd my-app

Push to a private GitHub repo.

On cloud platform:

Launch a compute instance running Ubuntu.

Download the pem key.

On local machine:

Generate the pm2 ecosystem file.

pm2 ecosystem

Replace the values.

module.exports = {
  apps: [
    {
      script: "npm start",
    },
  ],

  deploy: {
    production: {
      key: "key.pem",
      user: "ubuntu",
      host: "SSH_HOSTMACHINE",
      ref: "origin/main",
      repo: "GIT_REPOSITORY",
      path: "/home/ubuntu",
      "pre-deploy-local": "",
      "post-deploy":
        "source ~/.nvm/nvm.sh && npm install && npm run build && pm2 reload ecosystem.config.js --env production",
      "pre-setup": "",
      ssh_options: "ForwardAgent=yes",
    },
  },
};

Check in the file.

git add .
git commit -m "add ecosystem"

Push to GitHub.

Step 2: Provision server

On local machine:

Change pem permission.

chmod 400 key.pem

Copy the pem file into project root.

SSH into server.

ssh -i key.pem ubuntu@[IP_ADDRESS]

On the server:

Install Node, PM2, and Nginx.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
source .bashrc
nvm install --lts
npm i -g pm2
sudo apt-get update
sudo apt-get install -y nginx
sudo service nginx restart

Go to the IP address in browser using http protocol and verify Nginx welcome page.

Configure Nginx.

sudo vim /etc/nginx/conf.d/my-app.conf

Insert the following configuration.

server {
      listen 80;
      server_name IP_ADDRESS;

      location / {
          proxy_pass http://127.0.0.1:3000/;
      }
}

Restart Nginx.

sudo service nginx restart

Step 3: Pick A Deployment Option

Choose one of two deployment options:

Option 1: SSH Agent Forwarding

On local machine:

Edit ssh config.

vim ~/.ssh/config

Insert the following.

Host [IP_ADDRESS]
      ForwardAgent yes

Run ssh-add.

ssh-add

SSH into server.

ssh -i key.pem ubuntu@[IP_ADDRESS]

On the server:

Verify connection to GitHub.

ssh -T git@github.com

Option 2: Deploy Key

On the server:

Run the ssh-keygen procedure.

ssh-keygen

Copy the public key.

cat ~/.ssh/id_rsa.pub

On GitHub:

Go to the repo Settings > Deploy keys > Add deploy key

Paste the public key and click Add key.

Step 4: Deployment

On local machine:

Run pm2 setup.

pm2 deploy production setup

Run deployment.

pm2 deploy production

Step 5: Set up domain

Go to your DNS provider. Point domain to IP address. Wait for DNS propagation. Verify DNS with dig.

dig myapp.fullstackbook.com

Change the Nginx configuration to use domain instead of IP.

server {
      listen 80;
      server_name myapp.fullstackbook.com;

      location / {
            proxy_pass http://127.0.0.1:3000/;
      }
}

Restart Nginx.

sudo service nginx restart

Step 6: Set up SSL

Go to certbot.eff.org.

Select Nginx as the Software and Ubuntu as the System.

Follow the instructions. Below is a condensed version of the commands:

sudo snap install core; sudo snap refresh core
sudo apt-get remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx

References