DEV Community

Cover image for Understanding Nginx: From Simple Concepts to Technical Details and Deploying securely with PM2 and Certbot

Posted on • Originally published at

Understanding Nginx: From Simple Concepts to Technical Details and Deploying securely with PM2 and Certbot

Imagine you have a little shop where you sell lemonade, and you have a big sign that says "Lemonade for Sale." When people see your sign, they come to your shop to buy your lemonade. Now, imagine you're so popular that lots of people come at the same time. You need to make sure everyone gets their lemonade quickly and smoothly, so no one is waiting too long.

Nginx is like the best helper you could ask for in your shop. It's like a smart organizer who helps you handle all the people coming to your shop. When someone comes up to buy lemonade, Nginx quickly figures out who should get lemonade first, and makes sure that even if lots of people come at once, everyone gets their drink fast and without any trouble. It helps you manage the crowd so you can keep everyone happy!


Certainly! Nginx (pronounced as "Engine-X") is a powerful web server software that is also used as a reverse proxy, load balancer, and HTTP cache. It was specifically designed to handle high concurrency, which means it can manage many connections at once, efficiently and without requiring a lot of resources.

Web Server: As a web server, Nginx serves static content, like HTML, CSS, and JavaScript files, directly to clients. It is very efficient at this because of its event-driven architecture, which allows it to handle thousands of simultaneous connections on a single thread without much memory overhead.

Reverse Proxy: As a reverse proxy, Nginx sits between the client (like a web browser) and other servers. It can forward client requests to other servers and deliver the responses back to the client. This setup is useful for hiding the characteristics and location of the origin servers or for load balancing.

Load Balancer: Nginx can distribute incoming network traffic across multiple backend servers (like a group of application servers). This distributes the load, making sure no single server gets overwhelmed, which improves the responsiveness and availability of applications.

HTTP Cache: Nginx can also cache the responses from a server and reuse them to answer identical requests. This reduces the load on the server and speeds up the response time for clients.

Nginx is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption. These qualities make it a popular choice for scaling web applications and improving their performance and reliability.

Lets Use NGINX to run the Sigle File NodeJS Server that we set up here

Nginx, pronounced like “engine-ex”, is an open-source web server that, since its initial success as a web server, is now also used as a reverse proxy, HTTP cache, and load balancer.

Installing Nginx

apt install nginx
Enter fullscreen mode Exit fullscreen mode


Uncomplicated Firewall (UFW) is a program for managing a netfilter firewall designed to be easy to use. It uses a command-line interface consisting of a small number of simple commands, and uses iptables for configuration. UFW is available by default in all Ubuntu installations since 8.04 LTS.[1] UFW has been available by default in all Debian installations since 10.

Install ufw

apt install ufw
ufw enable
Enter fullscreen mode Exit fullscreen mode

Give nginx full control of firewall

ufw allow "Nginx Full"
Enter fullscreen mode Exit fullscreen mode

When you install Nginx, a default configuration file is created at /etc/nginx/sites-available/default. It's a good idea to keep this file for reference, but if you don't want to use it immediately, you should disable it. To disable it, delete the symbolic link in /etc/nginx/sites-enabled/ that points to this default file.

Now let's Create a new config file with name seinglefileserver.conf under /etc/nginx/sites-available/ directory

server {
  location / {
    proxy_pass http://<Your servers Ip>:6001;
    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;
Enter fullscreen mode Exit fullscreen mode

This Nginx configuration file defines a server block that listens for requests directed to the domain Let's break down each directive:

  1. server: Begins a new server block.

  2. server_name Specifies the domain name for which this server block will be used to handle requests. In this case, it's set to

  3. location /: Defines a location block that matches requests with any URI path.

  4. proxy_pass http://<Your servers Ip>:6001;: This directive instructs Nginx to forward incoming requests to another server. In this case, it forwards requests to the IP address specified (replace <Your servers Ip> with the actual IP address) on port 6001.

  5. proxy_http_version 1.1;: Sets the HTTP version used in proxy communication to HTTP/1.1.

  6. proxy_set_header Upgrade $http_upgrade;: This sets the Upgrade header to the value of the Upgrade header from the client's request. This is often used to enable WebSocket connections.

  7. proxy_set_header Connection 'upgrade';: Sets the Connection header to upgrade. This is also commonly used for WebSocket connections.

  8. proxy_set_header Host $host;: Sets the Host header to the value of the Host header from the client's request.

  9. proxy_cache_bypass $http_upgrade;: Sets conditions under which the request will bypass the cache. In this case, requests with the Upgrade header will bypass the cache.

This configuration essentially sets up a reverse proxy that forwards incoming requests from to another server listening on port 6001. It also includes settings commonly used for WebSocket connections.

Here's a clearer breakdown of how Nginx's configuration files are structured:

  1. Configuration Storage:

    • Available Configurations: All the server block files are stored in /etc/nginx/sites-available/.
    • Enabled Configurations: Nginx will only use configurations that are linked in /etc/nginx/sites-enabled/. These are usually symbolic links to files in the sites-available directory.
  2. Enabling a New Configuration:

    • To activate a configuration file, create a symbolic link from the sites-available directory to the sites-enabled directory using the following command:
     ln -s /etc/nginx/sites-available/<filename> /etc/nginx/sites-enabled/<filename>
  • Replace <filename> with the name of the configuration file you wish to enable.

If you want to unlink the default Nginx configuration, you can use the following command:

sudo unlink /etc/nginx/sites-available/default
Enter fullscreen mode Exit fullscreen mode

Check Nginx Configuration: Before restarting Nginx, it's a good practice to check if the configuration is valid.

    sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

If there are any syntax errors in your configuration file, this command will point them out. Fix any errors before proceeding.

Restart Nginx: Once the configuration is validated, you can restart Nginx to apply the changes.

    sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

This command will restart Nginx and load the new configuration file. From this point onwards, Nginx will handle requests for according to the configuration you provided.

Test the Configuration: After restarting Nginx, you can test whether it's working correctly by accessing in your web browser or by sending requests to this domain using tools like curl.

Be sure that you are running the nodeJS Server for example npm start

That's it! Your Nginx server should now be configured to handle requests for and proxy them to the specified server.

Now Visit (for you it will be something different depends on what you have defined your servers name. Also you have to be sure that you have connected the specified domain from your domain provider with the server)


Now let's take it to the next level and use PM2 to run server in the background

Create at the root of your project a file with name ecosystem.config.cjs

Past this code :

module. Exports = {
  apps: [{
    name: "",
    script: "npm start",
    watch: ["./"],
    ignore_watch: ["node_modules"],
//run this file with pm2 with pm2 start ecosystem.config.cjs
Enter fullscreen mode Exit fullscreen mode
  • module.exports: This syntax is used in Node.js to export modules, making them available to other files. In this case, it's exporting an object that contains PM2 configuration.

  • apps: This key holds an array of objects, where each object represents a configuration for a specific application or microservice that PM2 will manage. You can include multiple configurations in the apps array for different applications.

  • name: A string that specifies the name of the application as it will appear in PM2's process listing. In this case, the application is named "".

  • script: Defines the entry point script for the application. Here, "npm start" is used, which means PM2 will execute the start script defined in your package.json file.

  • watch: If set to true, PM2 will automatically restart the application when file changes in the current directory are detected. Here, it's set to watch all changes in the directory where PM2 is started ("./"). This is useful during development for automatic restarts on file save.

  • ignore_watch: An array of patterns to ignore from watching. In this configuration, changes in the node_modules directory won't trigger a restart. This is important because node_modules can contain a large number of files and frequent changes, which aren't typically necessary to watch for development purposes.

  1. Install PM2: If you haven't already installed PM2, you can do so globally using npm:

    npm install -g pm2
  2. Navigate to Your Project Directory: Open your terminal or command prompt and navigate to your project directory where the ecosystem.config.js file is located.

  3. Start Your Application with PM2: Run the following command to start your application using PM2:

    pm2 start ecosystem.config.cjs

alt text

This command will start your application as defined in the PM2 configuration file (ecosystem.config.js). PM2 will manage your application process and keep it running in the background.

  1. Check Application Status: You can check the status of your application by running:

    pm2 status

This command will show you a list of applications managed by PM2 along with their status.

  1. Monitor Application Logs: To monitor application logs, you can use the following command:

    pm2 logs

More pm2 commands here

Securing Your Node.js Application with SSL

Ensuring that your Node.js application is secure is crucial, especially when dealing with sensitive data. One effective way to secure your application is by implementing SSL/TLS, which encrypts the data transmitted between your server and clients. Below is a step-by-step guide on how to set up SSL for a Node.js application hosted with Nginx using Certbot and Let's Encrypt.

Step 1: Install Certbot and Its Nginx Plugin

First, you need to install Certbot and the Certbot Nginx plugin on your server. Certbot is a free, automated tool that simplifies the process of obtaining and renewing Let’s Encrypt SSL certificates. To install these packages, run:

sudo apt install certbot python3-certbot-nginx
Enter fullscreen mode Exit fullscreen mode

This command installs Certbot along with the Nginx plugin, which allows Certbot to automatically configure SSL for Nginx.

Step 2: Obtain an SSL Certificate

Once the installation is complete, you can proceed to obtain an SSL certificate for your domain. Replace with your actual domain name:

sudo certbot --nginx -d
Enter fullscreen mode Exit fullscreen mode

This command instructs Certbot to authenticate your domain, obtain an SSL certificate, and configure Nginx to use this certificate. Follow the interactive prompts to complete the process. Ensure that your domain is pointed to the server where you are running this command and that port 80 is open, as Certbot uses it to validate domain ownership.

Step 3: Verify Automatic Renewal Setup

Let’s Encrypt certificates are valid for ninety days. Fortunately, Certbot creates a scheduled task to automatically renew certificates before they expire. Check the status of the Certbot timer to confirm it's active:

sudo systemctl status certbot.timer
Enter fullscreen mode Exit fullscreen mode

This command will show you whether the timer is active and when the next renewal attempt is scheduled. It's important that this service is running to avoid any interruptions due to an expired certificate.

Final Step: Confirmation

Congratulations! You have successfully secured your Node.js application with SSL/TLS using Certbot and Let's Encrypt. Your communications are now encrypted, significantly enhancing the security of your application.

Top comments (0)