Introduction
Node.js is a programming environment that runs primarily on JavaScript. The open-source program allows you to build networking applications on platforms running Windows, Linux, macOS, and others. You can use Node.js applications in two main ways: as command line apps or as services.
Using a Node.js app as a service means that it will restart on reboot. This makes it a safer option for most production environments. We will focus on this role of Node.js apps. In this guide, we will cover how you can set up your Node.js application on Ubuntu 20.04 for a production environment. The application we run with Node.js will be managed using PM2. In the end, we will learn how to configure a reverse proxy using Nginx as well. This will enable us to give users safe access to the application.
Let’s start!
Before We Begin
Before you start setting up your Node.js application, there are some prerequisites that you need to take care of. First, you need to have set up your Ubuntu 20.04 server already. Your firewall should be enabled and you should have sudo privileges as a non-root user. Additionally, you must have a domain name for your server’s public IP. In this tutorial, we will represent it as example.com. You can substitute that with your own domain name. To set up the reverse proxy, you need to install Nginx on your system and configure it with SSL using Let’s Encrypt.
1. Install Node.js on Your System
The very first step to set up your Node.js application is to install it on your system. You will be able to find it in the NodeSource package archives right here. You will begin by downloading the NodeSource PPA. After that, you need to access your home directory. Then, extract the installation script for the latest LTS version using the curl
command:
1 2 |
cd ~ curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh |
To inspect the script contents, you can use any text editor. This is how you would use nano
:
1 |
nano nodesource_setup.sh |
Next, you can run the script with sudo
like this:
1 |
sudo bash nodesource_setup.sh |
This will add the PPA to your configuration. You can finally install your Node.js package now that you have Nodesource:
1 |
sudo apt install nodejs |
It is possible for you to check which Node.js version you have. To confirm, use this command:
1 |
nodejs -v |
The output will be the following:
1 |
v14.4.0 |
Since we downloaded the program through the NodeSource PPA, the executable in this case is nodejs
. The nodejs
package has both, the binary and the npm
. The npm
is a built-in package manager. This means you do not have to download an external one to manage your Node modules. It keeps track of any updates using a configuration file. This file is found in your home directory after you run npm
for the first time. You can confirm that npm
is present and running on your system. Use this command for this purpose:
1 |
npm -v |
This is what the output will be:
1 |
6.14.5 |
The output shows you the current version of the manager. Sometimes, you may need the build-essential
package to make npm work. Here is how to install this package:
1 |
sudo apt install build-essential |
With the help of this package, you can use build-essential
packages that need to have code compiled from the source. In addition, here is a more detailed guide on installing Node.js on your Ubuntu server.
2. Build Your Very Own Node.js Application
Now that you installed Node.js and the associated tools, we can start writing the application. Like our previous tutorial, we will consider our “Hello World” application. This app will return “Hello World” as a result of HTTP requests. You can replace it with any application of your own. First, we will create a sample application:
1 2 |
cd ~ nano hello.js |
Next, we will enter this code into our hello.js
application file:
1 2 3 4 5 6 7 8 9 10 11 12 |
const http = require('http'); const hostname = 'localhost'; const port = 3000; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World!\n'); }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); }); |
You can save and exit from the editor now. By default, the app will listen to specific addresses and ports like localhost
and 3000
. The “Hello World” text will be returned with a 200
HTTP success code. Running a localhost
means that remote clients cannot connect to the app. You can test your app with this line of code:
1 |
node hello.js |
Here is the output:
1 |
Server running at http://localhost:3000/ |
You can further test your application using the curl
command. Open a terminal session. Then, connect to the localhost
using curl
as follows:
1 |
curl http://localhost:3000 |
This is the output:
1 |
Hello World! |
If you get the above-mentioned output, it means your app is working fine. It indicates that the application is listening on the right addresses and ports. If you do not get the right output, you will have to make sure the program is listening at the right ports and addresses.
3. Install PM2 for Node.js Applications
Next, we will learn how to install PM2. PM2 itself is a process manager. It helps you better deal with and daemonize Node.js applications. As a result, your apps can work in the background as a service. You will be using npm
to install PM2 as well:
1 |
sudo npm install pm2@latest -g |
Adding -g
to the end means that you are installing the module globally. This means that the module will be available system wide. We can start by telling PM2 to run our hello.js
app in the background. We can do this with the pm2 start
command:
1 |
pm2 start hello.js |
It starts the app in the background. In addition to that, it adds the application to the PM2 process list. It will appear as an output every time you start an app, like this:
Your app will get an App name
and a PM2 id
. This is based on the file name. As you can see, other information it stored includes the status, the memory usage, and the PID
of the process. The benefit of using PM2 is that in case there is a crash or failure, your application will restart automatically. There is another command you can use to make the app launch whenever you start the system. Here is how you use the startup
subcommand:
1 |
pm2 startup systemd |
In the above output, the last line has the command to run superuser privileges so you can have PM2 start on launch. You can run this command. Simply place your username in place of Coudsigma:
1 |
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u cloudsigma --hp /home/cloudsigma |
Run the following command to save the process list and the environments:
1 |
pm2 save |
Now you can start the service with systemct1
:
1 |
sudo systemctl start pm2-cloudsigma |
There may be occasions you may encounter an error. In that case, you have to perform a system reboot with sudo reboot
. On the other hand, you can also check the systemd unit status:
1 |
systemctl status pm2-cloudsigma |
There are a number of additional subcommands which you can use with PM2. Let’s review some of the more useful ones. Use this to stop your application:
1 |
pm2 stop hello |
This command lets you restart the app:
1 |
pm2 restart hello |
Use this to list all of the apps that PM2 is managing right now:
1 |
pm2 list |
If you have the App name
, you can get information about specific applications:
1 |
pm2 info app_name |
Lastly, the following command lets you see the PM2 process monitor with the application status, memory usage, and CPU information:
1 |
pm2 monit |
4. Configure a Reverse Proxy Server
A reverse proxy is what your clients will access the application through. We prefer using Nginx for this purpose. As we mentioned before, you need to configure Nginx beforehand in the /etc/nginx/sites-available/example.com
file. We will start by editing this file:
1 |
sudo nano /etc/nginx/sites-available/example.com |
Find the location/
block in the server
block. Then, enter the following configuration in place of the existing content:
1 2 3 4 5 6 7 8 9 10 |
server { 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; } } |
You can change the port identity as suited. This configuration makes the server respond to requests at its root. Additionally, you can add location
blocks to your server blocks to give access to more applications. Let’s say we want to add another Node.js application at port 3001
:
1 2 3 4 5 6 7 8 9 10 |
server { location /app2 { proxy_pass http://localhost:3001; 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; } } |
Now, you can save and exit. You can check for any syntax errors with this command:
1 |
sudo nginx -t |
To restart Nginx, use the following:
1 |
sudo systemctl restart nginx |
As a result of these configurations, you will be able to access the application through the Nginx reverse proxy. You can test it by going to the public IP address of the server or its URL.
Conclusion
This tutorial covered all of the details when it comes to setting up your Node.js application properly. We started from the procedure of installing Node.js. Then, we covered the associated programs and subcommands. Lastly, we talked about setting up a reverse proxy. This information should equip you with enough knowledge to perform a basic Node.js app setup on an Ubuntu 20.04 server.
For more on programming with JavaScript, take a look at the related blog posts from our blog:
- A Guide on Adding JavaScript to HTML
- Setting up Your Application: How to Choose the Best Server Setup?
- Setting up a Blog Using Ghost
Happy Computing!
- How To Enable, Create and Use the .htaccess File: A Tutorial - March 8, 2023
- An Overview of Queries in MySQL - October 28, 2022
- Introduction to Cookies: Understanding and Working with JavaScript Cookies - October 25, 2022
- An Overview of Data Types in Ruby - October 24, 2022
- The Architecture of Iptables and Netfilter - October 10, 2022