Deploy NodeJS Application on CentOS 7

4
136

Deploy NodeJS Application on CentOS 7. When developing software on local machines, we often use node index.js or npm start commands. However, for server environment, running Node is much more complicated. We need to install and configure specifically.

In this article, I will setup NodeJS application on CentOS Server with Nginx and PM2.

  • CentOS 7
  • node v11.12.0
  • nginx/1.15.10
  • pm2 v3.4.1

For other Linux operating systems, the steps are almost the same, just slightly different in syntax.

Now, let’s start.

1. Nginx – Best performance

Nginx handles requests, not Node. With static content(css, img, javascript…) Nginx will deal directly with you without calling NodeJS application. Besides, if you need web support SSL / TLS, you only need Nginx to be enough, no need to configure on Node application.

Serving static files: such as javascript, images, css, If you’ve ever used express, you know that it’s available with express.static to handle these requests. However, using Node with these requests is not effective. It’s expensive, there’s no cache on the server, which makes your application run slow and potentially in the middle.

Setting up an SSL connection: to create this with Nodejs you need to call https and the configuration is quite complicated. However, with Nginx, things are much easier to breathe without affecting logic in the Node application.

Limit the file upload capacity: with some applications you support users to upload files to the server. However, with the web application, we can not trust the user and whether it is intentional or deliberate, they can push the server 1 file 100GB or more and your server is gone. It is not easy to handle this logic on Node.

Maximize the number of cores in the system. Nodejs is famous for running on a single thread. That means you can’t run two at the same time. If your server has multiple cores, you can only run one of them. Too bad. There are two solutions to this problem: Using the cluster feature (pm2 does this very well), Run the application on different ports and you use Nginx as a load balancer.

INSTALL:

First we need to install the necessary packages on the server. You need config repo for RHEL 7.

vim /etc/yum.repos.d/nginx.repo

And add:

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/rhel/7/$basearch/
gpgcheck=0
enabled=1

Now install nginx.

sudo yum install -y nginx

Start Nginx and set the Nginx to start with the server with the command:

sudo systemctl start nginx
sudo systemctl enable nginx

Access the server’s ip address to see if it is available. http://<your_server_ip>

Deploy NodeJS Application on CentOS 7

If you do not receive a response, configure the firewall as follows:

sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload

2. Install NodeJS and NPM

Before installing, turn off SELinux by opening the /etc/sysconfig/selinux file and finding SELINUX= and then editing it as follows:

SELINUX=disabled

Then, type reboot command to restart the server and log in to SSH again.

Now install NodeJS

yum install -y gcc-c++ make
curl -sL https://rpm.nodesource.com/setup_11.x | sudo -E bash -
sudo yum install -y nodejs

3. Install PM2

I will use PM2 to manage NodeJS application. Managing NodeJS with PM2 is easy, as a program.

sudo npm install [email protected] -g

Now, you don’t need to run the node server.js or npm start command. You can use pm2 to run.

pm2 start <app_file>

In this article, I run my application on port 8000. You will be using port in last of Step 5.

Deploy NodeJS Application on CentOS 7

4. Config VirtualHost Nginx

Step 1, create file: block.conf in the /etc/nginx/conf.d directory.

  • block.conf: block files / folders not accessible
# /etc/nginx/conf.d/block.conf
location = /robots.txt  { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; expires 30d; }
location ~ /\.          { access_log off; log_not_found off; deny all; }
location ~ ~$           { access_log off; log_not_found off; deny all; }
location ~ /\.git { access_log off; log_not_found off; deny all; }
location = /nginx.conf { access_log off; log_not_found off; deny all; }

Step 2, create new directory: domains at /etc/nginx and add new default.conf

  • default.conf
# /etc/nginx/domains/default.conf
server {
    listen       80;
    server_name  127.0.0.1;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;
    root   /usr/share/nginx;

    location / {

    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    include /etc/nginx/conf.d/block.conf;
}

Step 3, open /etc/nginx/nginx.conf and find this line:

include /etc/nginx/conf.d/*.conf;

Change it to:

include /etc/nginx/domains/*.conf;

Next, find this line:

access_log  /var/log/nginx/access.log  main; // you can comment this line for save storage

and add below it

index index.html index.htm;

Now you can restart nginx.

sudo systemctl restart nginx

5. Add domain

This step will repeat each time you add a new domain. We need to unify how the file of each domain is saved for it to be scientific.

I encourage you to go to the /home directory, create a folder named nginx and the directories of each domain will be saved there. For example: /home/nginx/abcxyz.com.

In each directory of the domain, we need to have 2 more directories including:

  • log/ – To store log files for each domain. There will be a file named error.log.
  • public_html/ – Directory containing the code of your web.

So, for example, I need to add the domain abcxyz.com to NGINX, I will run the following commands:

mkdir -p /home/nginx/abcxyz.com/log
touch /home/nginx/abcxyz.com/log/error.log
mkdir -p /home/nginx/abcxyz.com/public_html
chown -R nginx:nginx /home/nginx

Then, copy the file default.conf to abcxyz.com.conf located in the same directory (/etc/nginx/domains/).

cp /etc/nginx/domains/default.conf /etc/nginx/domains/abcxyz.com.conf

Open abcxyz.com.conf and find:

server_name  127.0.0.1;

Replace it

server_name  www.abcxyz.com abcxyz.com;

Find more:

#access_log  /var/log/nginx/log/host.access.log  main;

Add below it

error_log /home/nginx/abcxyz.com/log/error.log error;

Find more:

root   /usr/share/nginx/html;

Replace it

root   /home/nginx/abcxyz.com/public_html;

Config Nginx with Node (Important)

Add to the beginning of the file:

upstream node_nginx {
    ip_hash;
    server 127.0.0.1:8000;
}

8000 is the port I run my NodeJS application. You can change it with your application port that was run with PM2 in Step 3.

Then set the proxy_pass. Add this code in block location / {

proxy_read_timeout 1800;
proxy_connect_timeout 1800;

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;

# prevents 502 bad gateway error
proxy_buffers 8 32k;
proxy_buffer_size 64k;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;


proxy_pass http://node_nginx ;
proxy_redirect off;

You can configure my full configuration as follows:

upstream node_nginx {
    ip_hash;
    server 127.0.0.1:8000;
}
server {
    listen       80;
    server_name  abcxyz.com;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;
    error_log /home/nginx/abcxyz.com/log/error.log error;
    root   /home/nginx/abcxyz.com/public_html;

    location / {
        proxy_read_timeout 1800;
        proxy_connect_timeout 1800;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        # prevents 502 bad gateway error
        proxy_buffers 8 32k;
        proxy_buffer_size 64k;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;

        proxy_pass http://node_nginx ;
        proxy_redirect off;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
    
    include /etc/nginx/conf.d/block.conf;
}

After configuration is complete, CHMOD folders and files as follows: 644 for files, 755 for directories.

find /home/nginx/abcxyz.com/public_html '(' -type f -exec chmod 644 {} ';' ')' -o '(' -type d -exec chmod 755 {} ';' ')'

Finally, you need to restart nginx.

sudo systemctl restart nginx

Note: Each time you add a new domain, simply repeat step 5.

Thank you for reading. If you have any problems with this article, please leave a comment for us to discuss.

4
Leave a Reply

avatar
1 Comment threads
3 Thread replies
1 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
Tricks MagicalJohnny Recent comment authors
newest oldest most voted
Johnny
Guest
Johnny

Hi, thanks for your guide. I followed every step and it worked perfectly! I do have a problem though, and wanted to ask if you know something about it. I bought a domain from Namecheap and pointed it to the web server IP and it works however I can only access the website from inside the server itself, if I try to access it from outside (e.g.: another computer) it doesn’t work. I already set the firewall-cmd rules but it doesn’t seem to work. Do you have any ideas? Thanks for everything!