DEV Community

Cover image for Introduction to NGINX
Sanjeev Sharma
Sanjeev Sharma

Posted on

Introduction to NGINX

NGINX, pronounced as 'engine-x', is an open-source web server that is mainly used for Reverse proxy, Caching, and Load balancing.

If you're into web dev, at some point in your career you might have to work with NGINX. This article will help you get started with NGINX. By the end, you'll be able to setup your own NGINX web server. You'll also understand terms like load balancing and reverse proxy.


Why NGINX?

NGINX is widely used for serving web content. It is known for its high performance, stability, and efficiency, making it a popular choice for various web applications and websites.

Some key features of NGINX are:

  1. Web Server 🤖: It can serve static content(such as HTML, CSS and images) directly to clients, making it efficient for delivering web pages.
  2. Reverse Proxy ⏩: It can act a reverse proxy by forwarding client's requests to other servers. It is a commonly used practice for security and scalability.
  3. Load Balancer ⚖️: It can route incoming traffic to different server instances ensuring optimal resource utilization.
  4. SSL/TLS Termination 🔐: It can handle SSL/TLS termination, encrypting and decrypting data between clients and servers.
  5. Performance Optimization ⚡️: It is designed to be lightweight and efficient, capable of handling a large number of concurrent connections with low resource usage.

Installation

Ubuntu/Debian
sudo apt update
sudo apt install nginx
Enter fullscreen mode Exit fullscreen mode

After installation, NGINX will automatically start in the background. To check the status, run:

sudo systemctl status nginx
Enter fullscreen mode Exit fullscreen mode
MacOS

We can install it using brew

brew install nginx
Enter fullscreen mode Exit fullscreen mode

After installation, you can run it using:

brew services start nginx
Enter fullscreen mode Exit fullscreen mode
Windows
  1. Download the latest stable version of NGINX from the official website: NGINX Download.
  2. Extract the downloaded zip file to a location of your choice.
  3. Navigate to the NGINX directory and run nginx.exe. NGINX should start.

Configuration

To find the configuration file, run:

nginx -t

nginx: the configuration file /opt/homebrew/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /opt/homebrew/etc/nginx/nginx.conf test is successful
Enter fullscreen mode Exit fullscreen mode

This command tests the configuration file for syntax errors and typos, without applying it. It will also reveal the path to the main configuration file.

You can either edit this file directly or create a new one to follow along.

Serving HTML

If you check the nginx.conf file, you'll see a lot of blocks wrapped in {} and a lot of key-value pairs inside these blocks.

These blocks are known as contexts and the key-value pairs are known as directives for that context.

We'll clear the file and start from scratch. Your nginx.conf should look like this:

events {}

http {
    server {
        listen 8080;
        root /Users/syfe/Desktop/tutorials/nginx-test/html;
    }
}
Enter fullscreen mode Exit fullscreen mode

You only need events and http contexts to successfully load a configuration. Inside http, we have the server context that has the configuration for our web server.

It tells the server to listen on port 8080 and set root for serving files as /Users/syfe/Desktop/tutorials/nginx-test/html.

Inside the html directory, we'll create an index.html file.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1>Hello, world!</h1>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode

This is how directory structure looks currently.

Directory structure

If you created a new conf file, you can load it by running:

nginx -c path_to_your_file
Enter fullscreen mode Exit fullscreen mode

And after making changes to any conf file, you can apply it using:

nginx -s reload
Enter fullscreen mode Exit fullscreen mode

If you go on http://localhost:8080, you'll see the html being served. 🎉

Serving other static content

If you try to add styles to your HTML content using a CSS file and serve it using the current configuration it will not work.

To make this work, you have to set the correct mime types in the configuration.

...
http {
  types {
    text/css   css;
    text/html  html;
  }

  server {
    ...
  }
}
...
Enter fullscreen mode Exit fullscreen mode

But manually adding these mime types for all different kinds of assets is cumbersome. Therefore, NGINX comes with a default mime.types file that can be used here.

After adding the default mime types file, our configuration looks like this:

events {}

http {
    # include mime.types; (if you did not create a custom file)
    include /opt/homebrew/etc/nginx/mime.types;

    server {
        listen  8080;
        root    /Users/syfe/Desktop/tutorials/nginx-test/html;
    }
}
Enter fullscreen mode Exit fullscreen mode

After reloading the conf, our HTML and CSS should be working as expected but now we have support for a lot of types.

The location block

Let's assume you've the following directory structure:

Directory structure

Going to /animals, will serve the index.html file inside the animals directory. What if you want to have another endpoint /forest that serves the same file?

We can use the location block to specify the full path and then using alias we can set the directory that will serve the files.

events {}

http {
    include /opt/homebrew/etc/nginx/mime.types;

    server {
        listen  8080;
        root    /Users/syfe/Desktop/tutorials/nginx-test/html;

        location /forest {
            alias /Users/syfe/Desktop/tutorials/nginx-test/html/animals;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

With the above configuration, requests to /forest will be served from animals directory.

What if someone deletes the animals directory or the file we're trying to serve is not available? We can provide fallback files using try_files directive.

Let's create a fallback file.

Directory structure

Now, let's update the configuration.

events {}

http {
    include /opt/homebrew/etc/nginx/mime.types;

    server {
        listen  8080;
        root    /Users/syfe/Desktop/tutorials/nginx-test/html;

        location /animals {
            root /Users/syfe/Desktop/tutorials/nginx-test/html;
            try_files /animals/fallback.html /index.html =404;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, when a user visits /animals:

  1. First the server will look for /animals/index.html.
  2. If it doesn't exist, it'll look for /animals/fallback.html.
  3. If our fallback file is missing it'll try to serve the index.html at root.
  4. If it cannot find any file listed by us, it'll throw a 404 error.

Redirects

It is quite easy to set up redirections using NGINX. Let's update the configuration to redirect all incoming traffic from /birds to /animals.

events {}

http {
    include /opt/homebrew/etc/nginx/mime.types;

    server {
        listen  8080;
        root    /Users/syfe/Desktop/tutorials/nginx-test/html;

        location /animals {
            root /Users/syfe/Desktop/tutorials/nginx-test/html;
        }

        location /birds {
            return 307 /animals;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Returning with 307 does the trick.

Reverse Proxy

To forward requests to another server we can use the proxy_pass directive.

events {}

http {
    include /opt/homebrew/etc/nginx/mime.types;

    server {
        listen 8080;

        location / {
            proxy_pass http://192.168.10.5:8080;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, all the requests to localhost:8080 will be forwarded to http://192.168.10.5:8080. This is helpful when you don't want to reveal the actual server or want to relay requests to different servers based on different paths.

Load Balancing

Sometimes, in high traffic situations, we might spin up multiple instances to handle the load. NGINX can act as a load balancer and evenly distribute requests among all the instances.

Load balancing

This ensures a seamless experience for our users without any downtime.

Let's update the configuration to achieve this:

events {}

http {
    include /opt/homebrew/etc/nginx/mime.types;

    upstream instances {
        server 192.168.10.2:8080;
        server 192.168.10.3:8080;
        server 192.168.10.4:8080;
    }

    server {
        listen 8080;

        location / {
            proxy_pass http://instances;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

The upstream block is used to specify a group of servers that can be referenced by proxy_pass. NGINX will automatically take care of distributing the requests evenly.

Logging

With all that you've learnt so far, you'll be able to do a lot of cool things. One final(and important) thing that will help you in your journey is - Logging.

Let's update the configuration to add access logs on our server:

events {}

http {
    include /opt/homebrew/etc/nginx/mime.types;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" ';
    access_log /Users/syfe/Desktop/tutorials/nginx-test/access.log main;

    server {
        listen 8080;
        root /Users/syfe/Desktop/tutorials/nginx-test/html;
    }
}
Enter fullscreen mode Exit fullscreen mode

We provide the format using log_format directive. The access_log directive takes the path to store the logs and the format we specified earlier.


That's it for this post! I hope this will get you started or at least now you understand what NGINX is. The official documentation for NGINX is well written if you wish to explore further.

🤝 I'd love to connect on LinkedIn or X.

Syfe is hiring devs. 👨‍💻🌏

Top comments (4)

Collapse
 
bevilaquabruno profile image
Bruno Fernando Bevilaqua

Nice post!

Collapse
 
adityasid profile image
Aditya Santra

Very informative post 👍

Collapse
 
dsaga profile image
Dusan Petkovic

Thanks for the awesome write up!

Collapse
 
vishakhaawasthi01 profile image
VishakhaAwasthi01

This was very informative! 👍