DEV Community

react-stockholm
react-stockholm

Posted on • Updated on

Setup a Next.js project with PM2, Nginx and Yarn on Ubuntu 18.04

So, I recently had to deploy a Next.js project to a Ubuntu-server. Quite straight forward but you might run into some quirks.

We tend to deploy our projects on Now since it is super convenient but there might be instances where You need to deploy things to Your own servers. This is a short tutorial on how You can easily setup a working environment in no time.

We tend to deploy our projects on Now since it is super convenient but there might be instances where You need to deploy things to Your own servers. This is a short tutorial on how You can easily setup a working environment in no time.

  1. Install Nginx
  2. Install Yarn
  3. Install PM2
  4. Use Git to fetch our Next.js project from Github
  5. Run our project with PM2 and serve a browsable version with Nginx
  6. Run PM2 automatically whenever we boot/reboot the machine

Install Nginx

sudo apt install nginx
Enter fullscreen mode Exit fullscreen mode

Install Yarn on Ubuntu

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install yarn
Enter fullscreen mode Exit fullscreen mode

Install PM2 globally on your machine

yarn global add pm2
Enter fullscreen mode Exit fullscreen mode

Fetch project repo from Github and install all the dependencies

git clone github:<YOUR_ORGANIZATION>/<YOUR_PROJECT> project
cd project
yarn install
Enter fullscreen mode Exit fullscreen mode

NOTE: If You have Your latest code in a different branch you need to checkout that branch so if Your code resides in a branch named development you need to run git checkout development

NOTE: After yarn install you have to run yarn build so that You get a runnable version of the Next.js app

Start the Next.js project with Yarn and PM2

Our package.json looks like this

{
  "name": "nextjs-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "node server.js",
    "build": "next build",
    "start": "next start -p 8000",
    "test": "NODE_ENV=test jest",
    "test:watch": "NODE_ENV=test jest --watch",
    "test:coverage": "NODE_ENV=test jest --coverage",
    "test:cypress": "NODE_ENV=test cypress open",
    "lint": "eslint .",
    "lint:watch": "esw . --watch --cache",
    "lint:watchAll": "esw . --watch",
    "circleci:run": "circleci local execute --job $JOB"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/willandskill/nextjs-example.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/willandskill/nextjs-example/issues"
  },
  "homepage": "https://github.com/willandskill/nextjs-example#readme",
  "dependencies": {
    ...
  },
  "devDependencies": {
    ...
  }
}
Enter fullscreen mode Exit fullscreen mode

We have some extra stuff that You can ignore for now in our package.json. The line that matters to us is "start": "next start -p 8000" under scripts and in order for us to run it from the command line we would run yarn start but if we want PM2 to run it for us we need to run pm2 start yarn --name "nextjs" --interpreter bash -- start

To run our Next.js project and see if the process is kicking we need to run the commands below

pm2 start yarn --name "nextjs" --interpreter bash -- start
pm2 show nextjs
Enter fullscreen mode Exit fullscreen mode

The output should be something like

root@willandskill-example:# pm2 show nextjs
 Describing process with id 0 - name nextjs
┌───────────────────┬──────────────────────────────────┐
│ status            │ online                           │
│ name              │ nextjs                           │
│ version           │ N/A                              │
│ restarts          │ 2                                │
│ uptime            │ 93m                              │
│ script path       │ /usr/bin/yarn                    │
│ script args       │ start                            │
│ error log path    │ /root/.pm2/logs/nextjs-error.log │
│ out log path      │ /root/.pm2/logs/nextjs-out.log   │
│ pid path          │ /root/.pm2/pids/nextjs-0.pid     │
│ interpreter       │ bash                             │
│ interpreter args  │ N/A                              │
│ script id         │ 0                                │
│ exec cwd          │ /root/project                    │
│ exec mode         │ fork_mode                        │
│ node.js version   │ N/A                              │
│ node env          │ N/A                              │
│ watch & reload    │ ✘                                │
│ unstable restarts │ 0                                │
│ created at        │ 2019-03-13T15:02:40.278Z         │
└───────────────────┴──────────────────────────────────┘
 Add your own code metrics: http://bit.ly/code-metrics
 Use `pm2 logs next [--lines 1000]` to display logs
 Use `pm2 env 0` to display environement variables
 Use `pm2 monit` to monitor CPU and Memory usage next
Enter fullscreen mode Exit fullscreen mode

If You want to monitor what is happening in real time, You can run the command pm2 monit. This command is quite handy if You want to see the logs
generated in real time or see how Your hardware resources is utilized in normal/heavy traffic.

pm2 monit
Enter fullscreen mode Exit fullscreen mode

How You deploy a new version

git pull
yarn install
yarn build
pm2 restart nextjs
Enter fullscreen mode Exit fullscreen mode

Setting up a basic Nginx config file

# /etc/nginx/sites-available/nextjs-example.willandskill.eu

server {
    server_name nextjs-example.willandskill.eu;
    access_log /opt/nextjs/logs/access.log;
    error_log /opt/nextjs/logs/error.log error;

    location /_next/ {
        alias /opt/nextjs/project/.next/;
        expires 30d;
        access_log on;
    }

    location / {
        # reverse proxy for next server
        proxy_pass http://localhost:8000;
        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;

        # we need to remove this 404 handling
        # because next's _next folder and own handling
        # try_files $uri $uri/ =404;
    }
}
Enter fullscreen mode Exit fullscreen mode

The important line in this Nginx config file is to map the traffic to http://localhost:8000 with the line proxy_pass http://localhost:8000; under the location / block.

If you want PM2 to start on startup

pm2 startup
Enter fullscreen mode Exit fullscreen mode

You can also run the command below to freeze the processes You want to run on startup

pm2 save
Enter fullscreen mode Exit fullscreen mode

This article was originally posted on Will & Skill Blog - Setup a Next.js project with PM2, Nginx and Yarn on Ubuntu 18.04

Top comments (5)

Collapse
 
dance2die profile image
Sung M. Kim

Hi @react-stockholm

We encourage the entire article to be published on DEV.to (if you have proper rights), with a link back if appropriate. Otherwise, we recommend original material, such as original commentary on the article. From the Terms of Use:

Users must make a good-faith effort to share content that is...not designed primarily for the purposes of promotion or creating backlinks. Additionally, posts must contain substantial content — they may not merely reference an external link that contains the full post.

Posts that are simply intended to encourage readers to view an external resource are discouraged.

Thank you.

Collapse
 
reactstockholm profile image
react-stockholm

Ill make sure to post the whole article here :)

Collapse
 
r1si profile image
Elia "r1si" Baragiola

With this pm2 setup, will don't works the ENV configs.
Use this insteed:
github.com/vercel/next.js/discussi...

The only "bug" open is the app version... (with my config will show nextjs version)

Collapse
 
danielsdesk profile image
danielsdesk

is the --interpreter bash flag necessary? I've never seen this need to be used when running next.js with pm2 before

Collapse
 
mittalyashu profile image
Yashu Mittal • Edited

In the recent version of pm2 (as of this date), you don't need to use --interpreter flag.

You can directly use pm2 start "yarn server".