Deploy Next.js app on Ubuntu

Although simple, deploying Next.js apps on a Ubuntu 20.04 instance requires some effort. I will help you set up a Production/UAT version of your Next.js application through this blog.

A quick snapshot of the steps to achieve our goal:

  1. Update the server and packages
  2. Create a non-root user with Sudo privileges
  3. Install build-essential package
  4. Install Node.js and NPM
  5. Setup Nginx
  6. Create your Next.js project
  7. Install pm2
  8. Build and run

Let's get started!


Update lists and packages: The following commands are used to download the package lists from the repositories, update them to get information on the newest packages and their dependencies, and install the latest version of the packages installed on the system.

# download the latest package lists
sudo apt-get update 

# install the latest version of the installed packages
sudo apt-get upgrade

Create a non-root user with Sudo privileges: Performing server administration as a non-root user is best for security.

# replace <exmaple_user> with the actual username
$ adduser <example_user>
Adding user `example_user' ...
Adding new group `example_user' (1001) ...
Adding new user `example_user' (1001) with group `example_user' ...
Creating home directory `/home/example_user' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for example_user
Enter the new value, or press ENTER for the default
        Full Name []: Example User
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] y

Note: Try using sudo adduser <example_user> if you see permission related errors.


Install the build-essentials package: This package will install everything required for compiling basic software written in C and C++. This package is a prerequisite for Next.js, so please ensure you install this package.

# Prerequisite package
$ sudo apt-get install build-essential

Install Node.js and NPM:

# Install curl.
$ sudo apt-get install curl

# Add the latest release of NodeJS.
$ curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -

# Install NodeJS
$ sudo apt-get install nodejs

# Verify the installation
$ node -v 
$ npm -v

Install and Setup Nginx web server:

# Install Nginx server
$ sudo apt-get install nginx

# Open the detault nginx config file
$ sudo nano /etc/nginx/sites-available/default

Update the default Nginx config to include a proxy pass. This proxy pass will proxy incoming requests to our application running on port 3000. If you are using a different port, please update the same.

# to be added to /etc/nginx/sites-available/default

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/html;
    index index.html index.htm;

    location / {
            proxy_pass             http://127.0.0.1:3000;
            proxy_read_timeout     60;
            proxy_connect_timeout  60;
            proxy_redirect         off;

            # Allow the use of websockets
            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;
    }
}

Tip: If you decide to create a separate file for your server block, ex. zysk.in, make a symlink to the sites-enabled folder for the configuration to start working.

As another best practice, please test your Nginx configuration before you restart. If you restart the server with errors in the config file, the server might go down, and your website visitors will see an error screen.


Create your Next.js project: This should be straightforward. Follow these commands:

# navigate to home
cd ~

git clone https://github.com/zysk/example-next-js.git

cd example-next-js

#install dependecies and build the app
npm install
npm run build

Install PM2: PM2 is a production process manager for Node.js applications with a built-in load balancer. Configuring PM2 right would provide a 10x performance boost to your Node.js application. Going into the details might make this blog longer than I planned for so, here's a link to the documentation - Unitech/pm2: Node.js Production Process Manager with a built-in Load Balancer. (github.com)

# install pm2 globally
$ npm install pm2 -g

# start the pm2 server
pm2 start npm --name website -- start

website is the unique name I gave this pm2 process. Giving a name would make it easy to reference in the future.

If you face any errors, try building the porject again and don't forget to restart pm2.

npm run build
pm2 restart website


# check pm2 status
pm2 status

If you are seeing "online", pm2 is working fine. Time to conclude the setup, hit the url in the browser and check if your site is working.

I'd love to answer questions if you have any.