Nginx concepts I wish I knew years ago
Aemie Jariwala

Aemie Jariwala @aemiej

About: Just a super curious developer who loves walking everywhere

Location:
Dublin
Joined:
Aug 27, 2019

Nginx concepts I wish I knew years ago

Publish Date: Jan 11 '21
1248 54

Nginx is a web server that is used as a reverse proxy, load balancer, mail proxy, and HTTP cache and follows the Master-Slave Architecture.

Woah! A complicated term and a confusing definition filled with big confusing words, right? Don't worry, I can help out with first understanding the basic barebones of the architectures & terms in Nginx. Then we'll move on to installing and creating Nginx configurations.

Confused

To keep things easy, just remember: Nginx is an amazing web server.

Web server, in simple terms, is like a middleman. Let's say for instance you want to go to dev.to so you type the address https://dev.to, your browser finds out the address of a webserver for https://dev.to and then direct it to a backend server which will give back the response to the client.

Proxy v/s Reverse Proxy

The underlying feature of Nginx is proxies. So it's required to understand what is proxy and reverse proxy now.

Proxy

Alright, so we have clients (>= 1), an intermediate web server(in this case, we call it proxy), and a server. The main thing that happens in this is that the server doesn't know which client is requesting. Bit confusing? Let me explain with a diagrammatic sketch.

Proxy

In this, let client1 & client2 send requests request1 & request2 to the server through the Proxy server. Now the backend server will not know whether request1 is sent by client1 or client2 but performs the operation.

Reverse Proxy

In simplest terms, a reverse proxy is a reverse of what a proxy does. Here, we will have let's say a single client, an intermediate web server, and several backend servers (>=1). Let's do this with a diagrammatic sketch as well!

Reverse proxy

In this, a client will send a request through the webserver. Now the webserver will direct to any of the many servers through an algorithm, one being round-robin (the cutest one!), and send back the response through the webserver to the client. So here, the client isn't aware which backend server it is interacting with.

Load Balancing

Damn another new term but this term is simpler to understand as it is one instance application of reverse proxy itself.

Let's go with the basic difference. In load balancing, you must have 2 or more backend servers but in reverse proxy setup, that's not a necessity. It can work with even 1 backend server.

Let's look at it from behind the scene, if we have a lot of requests from the clients this load balancer checks the status of each backend server and distributes the load of the requests, and sends a response faster to the client.

Stateful v/s Stateless Applications

Okay, guys, I promise I am real close to starting with the Nginx code. Let's get all the barebones clear!

Stateful Applications

This application store an additional variable for saving the information that can work for a single instance of a server only.

Stateful

What I mean is if for a backend server server1 some information is stored it won't be stored for the server server2 thus the client (here Bob) interacting may/may not get the desired result as it could be interacting with server1 or server2. In this case, server1 will allow Bob to view the profile but server2 won't. Thus, even if it prevents many API calls with the database and is faster, it can lead to this problem across different servers.

Stateless Applications

Now stateless is more API calls with the database but fewer problems exist when it comes to the interaction of the client with different backend servers.

Stateless

I know you didn't get what I mean. It's simple if I send a request from a client to let's say backend server server1 through web server it will provide a token back to the client to use to access any further requests. The client can use the token and send a request to the webserver. This web server will send the request along with the token to any of the backend servers and each will provide the same desired output.

What is Nginx?

Nginx is the web server and I have been using the term web server in the entire blog till now. It's like a middleman honestly.

Nginx

The diagram isn't confusing, it's just a combination of all the concepts I have explained till now. In this, we have 3 backend servers running at port 3001, 3002, 3003 and all these backend servers use the same database running at port 5432.

Now when a client sends a requests GET /employees on https://localhost (by default on port 443), it will pass this requests to any of the backend server based on the algorithm and take the information from the database and send the JSON back to the Nginx web server and sent back to the client.

If we're to use an algorithm such as round-robin, what it'll do is let's say client 2 has sent a request to https://localhost then the Nginx server will pass the request first to port 3000 and send the response back to the client. For another request, Nginx will pass the request to 3002 and so on.

Too much information right! But by this point, you have a clear understanding of what Nginx is and the terms used with Nginx. Now we'll move on the understanding the installation and configuration techniques.

Installation Process

We're here at last! I am so proud if you've understood the concept to reach the coding part of Nginx at last.

proud

Okay, let me just tell you the installation process is super duper easy on any system just one-liner honestly. I am a Mac OSX user, so will be writing the commands based on it. But it will be done similarly for ubuntu and windows and other Linux distros.

$ brew install Nginx
Enter fullscreen mode Exit fullscreen mode

This is only required and you have Nginx on your system now! Amazing I am sure!

So easy to run! 😛

To run this and check if Nginx is working on your system, it's again way too simple.

$ nginx 
# OR 
$ sudo nginx
Enter fullscreen mode Exit fullscreen mode

After this, go on your favorite browser and check out http://localhost:8080/ and you'll get the below-observed screen!

start nginx

Basic Configuration Setup & Example

Okay, we will be doing an example and seeing the magic of Nginx.
First, create the directory structure in the local machine as follows:

.
├── nginx-demo
│  ├── content
│  │  ├── first.txt
│  │  ├── index.html
│  │  └── index.md
│  └── main
│    └── index.html
└── temp-nginx
  └── outsider
    └── index.html
Enter fullscreen mode Exit fullscreen mode

Also, include basic context within the html and md files.

What we're trying to achieve?

Here, we have two separate folders nginx-demo and temp-nginx, each containing static HTML files. We're going to focus on running both these folders on a common port and set rules that we like.

Coming back on track now. For making any changes to the Nginx default configuration, we will make a change in the nginx.conf that is located in the usr/local/etc/nginx path. Also, I have vim in my system so I make changes using vim but you're free to use your editor of choice.

$ cd /usr/local/etc/nginx
$ vim nginx.conf
Enter fullscreen mode Exit fullscreen mode

This will open a file with the default nginx configuration which I really don't want to use. Thus, the way I normally do is make a copy of this configuration file and then make changes to the main file. We'll be doing the same as well.

$ cp nginx.conf copy-nginx.conf
$ rm nginx.conf && vim nginx.conf 
Enter fullscreen mode Exit fullscreen mode

This will now open an empty file and we'll be adding our configuration for it.

  1. Add a basic setup of configuration. It is a must requirement to add the events {} as it is generally used to mention the number of workers for Nginx architecture. We are using http here to tell Nginx that we'll be working at layer 7 of the OSI model.

    In this, we've told nginx to listen on port 5000 and to point to the static file mentioned within the main folder.

      http {
    
         server {
           listen 5000;
           root /path/to/nginx-demo/main/; 
          }
    
      }
    
      events {}
    
  2. We'll add additional rules next for the /content and /outsider URL where outsider will be pointing to a directory outside the root directory mentioned in the 1st step.

    Here location /content signifies that whichever root I define in the leaf directory for this, the content sub URL will be added to the end of the root URL defined. Thus, here when I specify root as root /path/to/nginx-demo/ it simply means that I am telling Nginx at http://localhost:5000/path/to/nginx-demo/content/ show me the content of the static files within the folder.

      http {
    
        server {
            listen 5000;
            root /path/to/nginx-demo/main/; 
    
            location /content {
                root /path/to/nginx-demo/;
            }   
    
            location /outsider {
               root /path/temp-nginx/;
            }
       }
    
      }
    
      events {}
    

    Pretty cool! Now Nginx is not only limited to defining URL roots but also to set rules such that I can block the client from accessing certain files.

  3. We're going to write an additional rule within our main server defined to block any .md files from being accessed. We can use regex in Nginx so we'll define the rule as follows:

       location ~ .md {
            return 403;
       }
    
  4. Let's end this by learning the popular command proxy_pass. Now we've learned what a proxy and reverse proxy is so here we'll begin by defining another backend server running at port 8888. So now we've got 2 backend servers running at port 5000 and 8888.

    What we'll do is that when the client accesses port 8888 through Nginx we'll pass this request to port 5000 & send the response back to the client!

       server {
           listen 8888;
    
           location / {
               proxy_pass http://localhost:5000/;
           }
    
           location /new {
               proxy_pass http://localhost:5000/outsider/;
           }
      }
    

Let's see the final complete code altogether! 😁

   http {

        server {
            listen 5000;
            root /path/to/nginx-demo/main/; 

            location /content {
                root /path/to/nginx-demo/;
            }   

            location /outsider {
               root /path/temp-nginx/;
            }

                    location ~ .md {
              return 403;
            }
       }

         server {
           listen 8888;

           location / {
               proxy_pass http://localhost:5000/;
           }

           location /new {
               proxy_pass http://localhost:5000/outsider/;
           }
      }

   }

   events {}
Enter fullscreen mode Exit fullscreen mode

Run this code using sudo nginx.

Extra Nginx Commands!

  1. To start an Nginx web server for the first time.

      $ nginx 
      #OR 
      $ sudo nginx
    
  2. To reload a running Nginx web server.

      $ nginx -s reload
      #OR 
      $ sudo nginx -s reload
    
  3. To stop a running Nginx web server.

      $ nginx -s stop
      #OR 
      $ sudo nginx -s stop
    
  4. To know which processes of Nginx are running on your system.

      $ ps -ef | grep Nginx
    

The 4th command is important when by any chance the first 3 commands lead to some error, what you can normally do is find all running Nginx processes using the 4th command and kill the processes, and start it again.

To kill a process, you need the PID and then kill it using:

$ kill -9 <PID>
#OR 
$ sudo kill -9 <PID>
Enter fullscreen mode Exit fullscreen mode

Before ending this post, I've used diagrams and visuals from google images and couple of youtube tutorials by Hussein Nasser.

We've come to an end with the basic understanding of Nginx and its configuration. If you're interested in the advanced configuration of Nginx, do let me know through comments. Till then enjoy coding and explore the magic of Nginx! 👋

Comments 54 total

  • Akshay Khot
    Akshay KhotJan 11, 2021

    Good article! Very informative.

  • Ben Halpern
    Ben HalpernJan 11, 2021

    Great post!

  • Ola
    OlaJan 11, 2021

    Thank you so much.. This is very helpful.
    I can't wait for more of this..

  • Taufiq Abdullah
    Taufiq AbdullahJan 12, 2021

    Great !, Very helpful thank u so much :)

  • Md Salehin Khan
    Md Salehin KhanJan 12, 2021

    Great!

  • Boopathi
    BoopathiJan 12, 2021

    Just awesome bro ✌️

  • Ankur Loriya
    Ankur LoriyaJan 12, 2021

    sudo nginix -T

    For test configuration

  • Mick Orbik
    Mick OrbikJan 12, 2021

    Solid post!

  • Hoon Jo
    Hoon JoJan 12, 2021

    So Impressive. !

  • GermaVinsmoke
    GermaVinsmokeJan 12, 2021

    Atleast give the credits to the person whose diagram images you've used 😑

    • Aemie Jariwala
      Aemie JariwalaJan 12, 2021

      Sorry I missed that. I've added all the credits. Thanks a lot for the advice 😀

  • Fazal ur Rehman
    Fazal ur RehmanJan 12, 2021

    Well explained.!

  • pankajrajput1462
    pankajrajput1462Jan 12, 2021

    awesome article

  • Andrei Dascalu
    Andrei DascaluJan 12, 2021

    Well, you are wrong about the definition. A web server doesn't pass a request to a backed server. That's what a proxy does.

    A webserver serves content. That's it. It handles the request and returns it's own response, whereas a reverse proxy proxies the response.

    Even though the most efficient part of Nginx is its web server capability, it's widely used as a proxy/reverse proxy.

    However there are much more capable proxies out there (unless you're using the enterprise version): thinking mainly of Haproxy and Traefik.

    • Aemie Jariwala
      Aemie JariwalaJan 12, 2021

      In the article, I mentioned that the web server passes/directs the requests to the backend server. In the same sense that it's handling the connection between the client and the backend server. However, I agree with your definition as well hence thank you for your opinion! I will certainly look into those proxies as well. 😀

    • Simon Holdorf
      Simon HoldorfJan 12, 2021

      How about you say something like: thank you for the post and all the work you have put into this. I have slightly other opinions about X and want to share my version...

      Yours sounds way too rude!

      • Andrei Dascalu
        Andrei DascaluJan 12, 2021

        You have a point, but I wouldn't want to ruin my reputation as a literal and figurative bastard. And I wouldn't want people to think I discriminate.

    • Ski
      SkiJan 14, 2021

      Bit of hair splitting. Http reverse proxy IS a web server by definition of server as in TCP protocol node that acts as server in client-server connection.

      • Andrei Dascalu
        Andrei DascaluJan 14, 2021

        HTTP reverse proxy is a server (as in general term). Web server serves web content (as in WWW, eg: html/js). Sure, it's hair splitting, but the difference can be important in certain contexts. Eg: HAProxy is a reverse proxy, but NOT a web server as it's unable to actually serve content (it can only proxy it).

        IMHO it's important to know the tools and what they can do to choose what's right.
        A proxy can be, for example, a HTTP proxy or a TCP proxy. Some proxies can do both, some can only do HTTP by design.

  • KMeshU
    KMeshUJan 12, 2021

    Good post!

  • Konstantin Bogomolov
    Konstantin BogomolovJan 12, 2021

    Good tool to learn how nginx match locations: nginx.viraptor.info/

  • mugiwarafx
    mugiwarafxJan 12, 2021

    Great post, thanks for sharing!

  • Kiran RS
    Kiran RSJan 12, 2021

    Please create an article for Apache with nginx (as proxy server) with https.

  • Shwetabh Shekhar
    Shwetabh ShekharJan 12, 2021

    This is great, thanks for sharing!

  • François CHAUSSIN
    François CHAUSSINJan 13, 2021

    Great article, thanks for sharing

  • Aemie Jariwala
    Aemie JariwalaJan 13, 2021

    Thankyou Smith. Glad to know my article could be of help! ☺️

  • Fazal ur Rehman
    Fazal ur RehmanJan 13, 2021

    Hey Aemie!
    Can I use some of your's diagrams in my post?

    I will surely give credits.

    • Aemie Jariwala
      Aemie JariwalaJan 13, 2021

      I have myself used the diagrams from youtube tutorials & google images as mentioned but I have no problem!

  • arv
    arvJan 13, 2021

    Thank you @ameia. Can you please write an article a pie isn’t ngoni minx as websocket reverse proxy!

  • Eugene Vedensky
    Eugene VedenskyJan 15, 2021

    Thank you for the post, I'll use it as a reference whenever I need to work with NGINX.

    Some minor thoughts: although it's probably intuitive to more experienced devs, I think it might be helpful to point out that NGINX will automatically serve static files marked as index.html. Also, in my head it makes more sense to initially show the location block without defining a new root within it to show that NGINX will search your previously defined root path to append the requested URI to before moving on to examples that redefine the root.

    Thanks again for sharing.

  • Diretnan Domnan
    Diretnan DomnanJan 15, 2021

    I finally understand, thanks! You've earned yourself a follower

  • Aemie Jariwala
    Aemie JariwalaJan 15, 2021

    Pleasure is all mine!

  • Yevazn
    YevaznJan 17, 2021

    Great post!

    I'm from HelloGitHub, a nonprofit organization in China. I am reaching out to you to ask if it's OK for us to translate your posts, "Nginx concepts I wish I knew years ago", into Chinese and publish it on our WeChat official account. You own the copyright of course.

    How does that sound to you?

    • Aemie Jariwala
      Aemie JariwalaJan 17, 2021

      First of all, thank you. As long as I own the copyright, I am fine with this. :)

  • Nitin Reddy
    Nitin ReddyFeb 6, 2021

    Good article! I have a question about the format of the nginx.conf configuration file... it certainly isn't JSON. What format is it?

Add comment