episyche logo



User guide for deploying the Next.js app in production using PM2 and Nginx?

Published on

User guide for deploying the Next.js app in production using PM2 and Nginx?

To make our Nextjs webapp accessible publicly on the internet, we need to push the code to a Linux server. But the Node.js server can’t handle the client request. Hence we use  Nginx to manage the client request and pm2 for running Nextjs in the background in a production environment.

Introduction :

While developing your web app or website local on your machine, it is very easy to see the result appear on the browser, just by typing this command npm run dev. Under the hood runs a local server to provide features like hot-code reloading, error reporting and more.

But the real problem occurs when you think to deploy your application on a cloud server (ubuntu) for production purposes. On the Next.js official documentation, they have done a good job of explaining the commands and use cases. They left out some important things like which tool should I use to manage my application running in the background, which web server should I choose, how to configure a reverse proxy, Virtual host using the domain name and much more.

So don’t worry in this tutorial we are going to see step by step process, of how to deploy the Next.js application or website on a remote server.

Flow Diagram :



Steps :

Step 1: Create a Next.js application or website

In Next.js you have to follow certain rules, such as using the Image Tag provided by the Next.js. Likewise, there are some rules to follow while developing your Next.js web application or website.

Step 2: Upload files to a remote server

If you don’t know about git or Github read this article

On the local machine, Run these commands:

1git add . 2git commit -m "npm run build done" 3git push


On the remote server

  • If you already cloned the repo, execute the below command

1git pull


  • If you have not cloned the repo, execute the below command

1git clone github-repo-url

How to get Github repo URL for cloning. As given in the screenshot below:


Step 3: Install Node.Js

Always use the LTS version for long-term support from the developers. The Node js version used in this tutorial is 16 LTS. Execute the below commands:

1curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - 2sudo apt-get install -y nodejs

Step 4: npm install

Navigate to the project directory/folder and execute the command npm install, to install dependencies required to run the Next.js web application or website.

1cd /project-root-folder 2npm install

Step 5: npm run build

To make the application ready for the production stage, we need to bundle the javascript files. This process is done by Next.js by executing the following command:

Note*: your server must meet the minimum requirement to process the files.

RAM: 1GB and above.

Processor core: 1 and above.

1cd /project-root-folder 2npm run build

The output screenshot is given for your reference.


Step 6: Install PM2

We need a tool to manage the Next.js process running in the background after the terminal is closed. so PM2 is going to do the work.

  • Install PM2 using the below command:

1sudo npm install pm2 -g
  • To verify PM2 installation, execute the following command pm2, you will get a response similar to the screenshot given below.


Step 7: 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: ( The explanation for the below command is given on the image.)

1pm2 start npm --name app1 -- run start -- -p 3000
  • Check the status of app1.

1pm2 list app1


  • To check whether the Next.js application is actually working or not, Enter the public IP of the server along with a port number (3000) in the browser. eg:


  • To stop the app1 process

1pm2 stop app1


  • To start the app1 process

1pm2 start app1
  • To restart the app1 process

1pm2 restart app1
  • To Delete the app1 process

1pm2 delete app1

Step 8: Install the Nginx web server

In order to directly access the application without mentioning the port number on the browser. We need to set up a reverse proxy with a web server. The web server we’re going to use is Nginx to read more about Nginx click here.

The reverse proxy concept is explained below in the image:


Note*: yousite.com will be replaced with the actual domain name.


On the ubuntu server, execute the following command:

  • Update apt packages information

1sudo apt update
  • Install Nginx

1sudo apt install nginx -y
  • Check the status of the Nginx web server

1systemctl status nginx

Example output screenshot :


Step 9: Redirect Nginx request to Next.js

When the user hits the domain or public address of your server, they will be presented with the Nginx sample page. In order to redirect the request to the next.js app running at port 3000. We need to implement a technique called reverse proxy in Nginx.

1cd /etc/nginx/sites-available 2sudo vim default
  • Delete the highlight block, displayed below in the screenshot :


  • Append the new code block, given below:

1 location / { 2 proxy_pass; 3 proxy_read_timeout 60; 4 proxy_connect_timeout 60; 5 proxy_redirect off; 6 7 # Allow the use of websockets 8 proxy_http_version 1.1; 9 proxy_set_header Upgrade $http_upgrade; 10 proxy_set_header Connection 'upgrade'; 11 proxy_set_header Host $host; 12 proxy_cache_bypass $http_upgrade; 13 }

Nginx config file with the changes mentioned is attached below for your reference:

  • Run the Next.js app using the PM2 command.

1pm2 start npm --name app1 -- run start -- -p 3000
  • Restart Nginx to see the result

1sudo systemctl restart nginx


Step 10: Virtual Host

If you want to access your Next.js web application/website using the domain name and not with an IP address. Check out the tutorial on how to set up a virtual host in Nginx.


If the following steps are done correctly, you can access your web application/website with the public IP address on the browser

Example output screenshot :