Node.js is an opensource a JavaScript runtime environment which can be developed to build a server-side and network application. Linux, Mac OS X, FreeBSD, and Windows are all supported. Though Node.js can be run on the command line, we’ll focus on it running as a service through this tutorial. In this way, they will restart on a reboot or failure and can be used in a production environment.
We will setup production-ready Node.js environment on Ubuntu 20.04 server. We will use PM2 to managed and run a Node.js application, and provide users access to the application through an Nginx web server reverse proxy directive.
Initial Setup
Start by updating the packages to the latest version available.
sudo apt update sudo apt upgrade
Install Specific Node.js version
You can install specific Node.js version from the Node.js repositories.
$ curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
## Installing the NodeSource Node.js 14.x repo...
## Populating apt-get cache...
+ apt-get update
Hit:1 http://us-east-2.ec2.archive.ubuntu.com/ubuntu focal InRelease
Hit:2 http://us-east-2.ec2.archive.ubuntu.com/ubuntu focal-updates InRelease
Hit:3 http://us-east-2.ec2.archive.ubuntu.com/ubuntu focal-backports InRelease
Hit:5 http://security.ubuntu.com/ubuntu focal-security InRelease
Hit:4 https://packages.cloud.google.com/apt kubernetes-xenial InRelease
Reading package lists... Done
## Confirming "focal" is supported...
+ curl -sLf -o /dev/null 'https://deb.nodesource.com/node_14.x/dists/focal/Release'
## Adding the NodeSource signing key to your keyring...
+ curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | gpg --dearmor | tee /usr/share/keyrings/nodesource.gpg >/dev/null
## Creating apt sources list file for the NodeSource Node.js 14.x repo...
+ echo 'deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_14.x focal main' > /etc/apt/sources.list.d/nodesource.list
+ echo 'deb-src [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_14.x focal main' >> /etc/apt/sources.list.d/nodesource.list
## Running `apt-get update` for you...
+ apt-get update
Hit:1 http://us-east-2.ec2.archive.ubuntu.com/ubuntu focal InRelease
Hit:2 http://us-east-2.ec2.archive.ubuntu.com/ubuntu focal-updates InRelease
Hit:3 http://us-east-2.ec2.archive.ubuntu.com/ubuntu focal-backports InRelease
Hit:4 http://security.ubuntu.com/ubuntu focal-security InRelease
Get:5 https://deb.nodesource.com/node_14.x focal InRelease [4583 B]
Hit:6 https://packages.cloud.google.com/apt kubernetes-xenial InRelease
Get:7 https://deb.nodesource.com/node_14.x focal/main amd64 Packages [775 B]
Fetched 5358 B in 1s (10.3 kB/s)
Reading package lists... Done
## Run `sudo apt-get install -y nodejs` to install Node.js 14.x and npm
## You may also need development tools to build native addons:
sudo apt-get install gcc g++ make
## To install the Yarn package manager, run:
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] 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
Now install the NodeJS app with specific version.
$ sudo apt install nodejs
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
nodejs
0 upgraded, 1 newly installed, 0 to remove and 46 not upgraded.
Need to get 25.4 MB of archives.
After this operation, 123 MB of additional disk space will be used.
Get:1 https://deb.nodesource.com/node_14.x focal/main amd64 nodejs amd64 14.19.1-deb-1nodesource1 [25.4 MB]
Fetched 25.4 MB in 1s (46.5 MB/s)
Selecting previously unselected package nodejs.
(Reading database ... 149395 files and directories currently installed.)
Preparing to unpack .../nodejs_14.19.1-deb-1nodesource1_amd64.deb ...
Unpacking nodejs (14.19.1-deb-1nodesource1) ...
Setting up nodejs (14.19.1-deb-1nodesource1) ...
Processing triggers for man-db (2.9.1-1) ...
Verify Services
$ node -v v14.19.1 $ npm -v 6.14.16 $ sudo apt install build-essential
Creating a Node.js Application
$ vim app.js
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Run and verify NodeJS app with the following command.
$ node app.js
Server running at http://localhost:3000/
$ curl http://localhost:3000
Hello World!
Installing PM2
Next let’s install PM2, a process manager for Node.js applications. PM2 makes it possible to daemonize applications so that they will run in the background as a service.
Use npm to install the latest version of PM2 on your server:
$ sudo npm install pm2@latest -g
npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
/usr/bin/pm2 -> /usr/lib/node_modules/pm2/bin/pm2
/usr/bin/pm2-dev -> /usr/lib/node_modules/pm2/bin/pm2-dev
/usr/bin/pm2-docker -> /usr/lib/node_modules/pm2/bin/pm2-docker
/usr/bin/pm2-runtime -> /usr/lib/node_modules/pm2/bin/pm2-runtime
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.3.2 (node_modules/pm2/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
+ pm2@5.2.0
added 182 packages from 182 contributors in 10.129s
Now start the app.js application with PM2.
$ pm2 start app.js
[PM2] Starting /home/ubuntu/app.js in fork_mode (1 instance)
[PM2] Done.
┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ app │ default │ N/A │ fork │ 3234934 │ 0s │ 0 │ online │ 0% │ 26.0mb │ ubuntu │ disabled │
└─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
Verify Node JS Running Port
$ sudo netstat -tulnp | grep 3000 tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN 3234934/node /home/ You can stop NodeJS app with the following command. $ pm2 stop app.js [PM2] Applying action stopProcessId on app [app.js](ids: [ 0 ]) [PM2] [app](0) ✓ ┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐ │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │ ├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤ │ 0 │ app │ default │ N/A │ fork │ 0 │ 0 │ 0 │ stopped │ 0% │ 0b │ ubuntu │ disabled │ └─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
Install Nginx Web Server
sudo apt update sudo apt install nginx systemctl status nginx
Create a Virtual Host
sudo vim /etc/hosts
IP - Domain
sudo vim /etc/nginx/sites-available/app.example.com
server {
server_name app.example.com;
index index.html index.htm;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
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_cache_bypass $http_upgrade;
}
}
Enable newly created virtual host.
sudo ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
sudo pm2 start next
sudo pm2 restart next
sudo pm2 log next
sudo systemctl restart nginx.service
sudo systemctl status nginx.service
Verify Node JS service after applying ProxyPass
$ curl app.example.com Hello World
Conclusion
Reference
https://nodejs.org/en/