How to setup next.js app on nginx + PM2 with letsencrypt

Next.js is a framework for building web applications. Next.js gives you the best developer experience with all the features you need for production: hybrid static & server rendering, TypeScript support, smart bundling, route pre-fetching, and more. No config needed.

Nginx is a web server and reverse proxy that is used to serve HTTP requests. It is a high performance, light-weight, and easy-to-use web server. It is used to serve HTTP requests and to proxy HTTP requests to other servers.

In this tutorial, we will learn how to setup a Next.js app on nginx with PM2 and letsencrypt.

1. Install Nginx, Node and certbot #

In your server console/terminal

cd ~ # go to the current user's home directory
curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh

sudo apt update
sudo apt install nginx nodejs certbot python3-certbot-nginx

Also enable Nginx in ufw firewall.

sudo ufw allow 'OpenSSH' # needed for SSH connections
sudo ufw allow 'Nginx Full' # after installing Nginx!
sudo ufw enable

2. Setup letsencrypt with certbot #

You will need to point your domain to the server's IP by using A record in your DNS setting.

Edit the default Nginx configuration file.

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

You must change example.com to your actual domain name.

server {
    # ...
    server_name example.com www.example.com;
    # ...
}

Check if the nginx syntax is correct

sudo nginx -t

Restart nginx

sudo systemctl restart nginx

Run the following command let certbot to create a certificate for your domain.

sudo certbot certonly --nginx -d example.com -d www.example.com

3. Setup Reverse proxy with Nginx #

Edit the default Nginx configuration file.

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

server {
  # ...
  server_name example.com www.example.com;
  # ...
  location / {
    # Reverse proxy for Next server
    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_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Port $server_port;
  }
  # ...
}

Check and restart Nginx

sudo nginx -t
sudo systemctl restart nginx

4. Setup Next.js with PM2 #

Assuming you have a GitHub repository for the app

git pull https://github.com/user/repo.git myapp
cd myapp
npm install
npm run build

Install PM2

npm install -g pm2

To generate a sample configuration file you can type this command:

pm2 init 

This will generate a sample ecosystem.config.js: Edit the file and add the following lines:

{
  "apps": [
    {
      "name": "myapp",
      "script": "./server.js",
      "args": "start",
      "exec_mode": "cluster", # or fork
      "instances": 2, # Number of cluster instances
      "env": {
        "NODE_ENV": "production"
      }
    }
  ]
}

Start the app with PM2

pm2 start ecosystem.config.js

To stop the app with PM2

pm2 stop myapp