NodeJS

You wrote your entire project in NodeJS, or you have microservices with NodeJS for the main project. It can’t create awesome things if you can’t deploy it. But, no worries. Please close the ChatGPT tab on your browser. Also, you don’t need to be a system administrator or DevOps engineer. Let’s deploy your project step by step.

Prerequisites

  • Ubuntu 24.04
  • Root Access

Installing Nginx

First, make sure everything is up-to-date.

apt-get update
apt-get upgrade

Then, we can start with installing Nginx.

apt install nginx

Open your browser and enter your IP address in the address bar: http://YOURIP.

Deploy NodeJS

If you see the “Welcome to nginx” page, it’s OK.

Installing NodeJS

We need to install NVM (Node Version Manager). Run the following command in your terminal.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash

Export the NVM_DIR and reload your bash profile.

export NVM_DIR="$HOME/.nvm"
source .bashrc

Then, choose a Node.js version. You can choose a major version, and it will install the latest version of that major version.

nvm install 20

Verify the installation.

node -v
npm -v

It should print the Node.js and npm versions.

Installing PM2

Run the following command to install PM2 (process manager).

npm install pm2 -g

Then, verify your installation with the following command.

pm2 --version

Clone or upload your project

I used the Express generator to create a new Express.js project for testing deployment. However, I assume you already have a project. You should navigate to the /var/www directory and create a directory for your project files.

Clone your git repository or upload your files under the directory that you created.

Deploy Nodejs

Run the following command to install the project dependencies.

npm i

Test your project via a web browser. If it works under the specified port, then we can continue to the deployment steps.

npm run start

Create a custom vhost config

Create a custom vhost config file under the sites-available directory. I named it express-test according to my project.

touch /etc/nginx/sites-available/express-test

Then, open the file with nano or your favorite editor and copy/paste the following vhost config. I’ve prepared a vhost config. You should change the server_name, root, access_log, and proxy_pass lines for your own project and domain.

server {
    listen 80;
    server_name express-test.hostname.tr; # YOUR DOMAIN
    root /var/www/express-test/public; # YOUR PROJECT PATH
    access_log /var/log/nginx/express-test.log;

   location / {
      proxy_pass http://localhost:3000; # CHANGE THE PORT FOR YOURS
      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;
   }

   error_page 500 502 503 504 /50x.html;

   location = /50x.html {
      root /usr/share/nginx/html;
   }

   location = /favicon.ico {
        log_not_found off;
        access_log off;
        return 204;
   }
}

Then, enable the config for reading by Nginx.

cd /etc/nginx/sites-enabled
ln -s ../sites-available/express-test

Then, check the Nginx config.

nginx -t

And, if there is no error, you can reload the Nginx config.

nginx -s reload

Setting up Process Manager

Everything is fine, but we can’t keep the terminal open forever. We will use PM2 to run the process in the background. PM2 will handle this task.

You can write your start command between the double quotes, and you can give a name to remember the project on PM2.

pm2 start "npm run start" --name ExpressTest

Deploy Nodejs

Configure your DNS

There is no need to install Bind or PowerDNS on the server for resolving a single website or a couple of websites. I always prefer an external DNS server. Usually, I use Cloudflare for this purpose.

You can point your DNS to your server’s IP address.

134.122.66.17 A express-test.hostname.tr

Conclusion

Deploy Nodejs

We’ve completed the deployment steps. You should wait for the DNS changes to resolve. Then, you’re ready! Also, I suggest blocking port 3000 except for your server and local IP on your firewall (iptables, csf, etc.).