Comprehending the Structure and Contexts of Nginx Configuration File

Nginx is a powerful web server known for its ability to handle heavy traffic from major websites. It particularly shines in managing numerous simultaneous connections and efficiently distributing or delivering static content. This guide will mainly cover the organization of an Nginx configuration file and provide suggestions on structuring your files effectively.

Comprehending Nginx’s Configuration Contexts.

This guide will explain the format of the primary Nginx configuration file. The specific location of this file will vary based on the installation method used for Nginx. In numerous Linux distributions, the file can be found at /etc/nginx/nginx.conf. If it cannot be found there, it might be placed at /usr/local/nginx/conf/nginx.conf or /usr/local/etc/nginx/nginx.conf.

When examining the main configuration file, it is important to observe its tree-like structure, which is indicated by sets of brackets ({ and }). In Nginx documentation, these bracket-defined sections are referred to as “contexts” as they encompass configuration details that are segregated based on their respective areas of focus. These divisions serve to both organize the structure and implement conditional logic for determining the application of the configurations contained within.

Nginx supports the inheritance of configurations due to the ability to have layered contexts. In simpler terms, if a directive is applicable to multiple levels of scopes, a declaration in a higher-level context will be automatically applied to all the lower-level contexts as a default value. However, these default values can be overridden by the lower-level contexts. It’s essential to keep in mind that when overriding directives that deal with arrays, the previous value will be replaced entirely rather than added to.

You can only use directives in the specific situations they were intended for. If a configuration file includes directives in the incorrect context, Nginx will generate an error. The Nginx documentation provides valuable reference information about the contexts in which each directive can be properly used.

In the following discussion, we will explore the most prevalent situations one is likely to encounter when working with Nginx.

The fundamental situations

The initial set of contexts we will talk about are the fundamental contexts utilized by Nginx to establish a hierarchical tree and divide the distinct configuration blocks. These contexts constitute the primary framework of an Nginx configuration.

The primary context

The “main” or “global” context is the broadest context that is not confined to the standard context blocks like the one shown.

One possible paraphrase could be:

“The configuration file for Nginx, located at /etc/nginx/nginx.conf.”

# The main context is here, outside any other contexts

. . .

context {

    . . .

}

“All directives outside of these blocks are considered part of the “main” context. Remember that if your Nginx configuration is modular, with options spread across multiple files, some instructions may seem to be outside of a bracketed context but will still be included within a context when the configuration is loaded as a whole.”

The primary context encompasses the widest scope for Nginx configuration. It is utilized to configure aspects that impact the overall application. While the directives within this segment influence the subordinate contexts, a majority of them cannot be overridden at lower levels.

In the main context, you can specify various configurations such as the system’s user and group for worker processes, the quantity of workers, and the destination to store the ID of the main Nginx process. Additionally, you have the option to set a default error file for the entire application at this level, which can be overridden in more specific contexts if needed.

The Context of Events

The “events” context is nested within the “main” context. It is employed to define global settings that impact Nginx’s handling of connections at a broad level. Only one events context is permitted in the Nginx configuration.

The configuration file will have this context appearing outside of any other bracketed contexts in the following manner.

nginx configuration file located in the directory /etc/nginx/nginx.conf.
# main context

events {

    # events context
    . . .

}

The event-based connection processing model employed by Nginx relies on directives within this context to guide the behavior of worker processes when dealing with connections. These directives primarily allow for the selection of connection processing techniques and alteration of their implementation.

Typically, the platform automatically selects the most efficient connection processing method available, with epoll being the preferable choice for Linux systems.

Additional configurations include the maximum number of connections that each worker can manage, the choice for a worker to handle only one connection at a time or handle all pending connections after receiving a notification, and the decision for workers to alternate in responding to events.

The context of the HTTP.

When it comes to configuring Nginx as a web server or reverse proxy, the “http” context is commonly utilized for defining an HTTP context. This context encompasses the majority of the configuration and includes directives and other contexts required to determine how the program will handle connections via HTTP or HTTPS.

The HTTP context and the events context are siblings and should be presented adjacent to each other rather than being nested. Both of them are offspring of the main context.

nginx.conf file located in the /etc/nginx directory.
# main context

events {
    # events context

    . . .

}

http {
    # http context

    . . .

}

While lower levels of contexts provide detailed instructions for managing requests, directives at this level govern the defaults for all virtual servers defined within. Many directives can be customized at this hierarchy and beyond, based on desired inheritance behavior.

You may come across various directives that control the default locations for access and error logs (access_log and error_log), configure asynchronous I/O for file operations (aio, sendfile, and directio), and determine the server’s response to errors (error_page). Other directives enable compression (gzip and gzip_disable), fine-tune TCP keep alive settings (keepalive_disable, keepalive_requests, and keepalive_timeout), and define rules to optimize packets and system calls (sendfile, tcp_nodelay, and tcp_nopush). Additional directives set the document root and index files for an application-level (root and index), and configure hash tables for storing different types of data (*_hash_bucket_size and *_hash_max_size for server_names, types, and variables). To gather more information, please consult the Nginx documentation.

The server’s environment

The “server” context is defined within the “http” context. This is our initial instance of nested contexts enclosed in brackets. Additionally, it is the first context that permits multiple declarations.

The typical format for the server context might appear similar to this. Keep in mind that these are situated within the http context:

The nginx configuration file can be found at /etc/nginx/nginx.conf.
# main context

http {

    # http context

    server {

        # first server context

    }

    server {

        # second server context

    }

}

Because each instance defines a specific virtual server to handle client requests, it is possible to declare multiple server contexts. You can create as many server blocks as required, each capable of managing a specific subset of connections.

This is the initial context type that Nginx needs to employ for selecting an algorithm. Every client request will be processed as per the defined configuration in a single server context. Thus, Nginx must determine the most suitable server context, considering the request’s specifics. There are two standard choices, distinguished by their utilization of domain names.

  • listen: The IP address / port combination that this server block is designed to respond to. If a request is made by a client that matches these values, this block will potentially be selected to handle the connection.
  • server_name: This directive is the other component used to select a server block for processing. If there are multiple server blocks with listen directives of the same specificity that can handle the request, Nginx will parse the “Host” header of the request and match it against this directive.

In this particular setting, the directives have the power to supersede various directives from the http context such as logging, compression, and the document root. Apart from the directives borrowed from the http context, we have the ability to configure files to handle requests (try_files), perform redirects and rewrites (return and rewrite), and define custom variables (set).

The context of the location.

The next type of context that you will frequently encounter is the location context. Location contexts have several similarities with server contexts. For instance, you can define multiple location contexts, assign each location to handle specific client requests, and select the appropriate location by matching the definition to the client request using a selection algorithm.

Although the server block’s directives specify whether to choose a server block, the decision regarding a location’s capability to process a request is made within the location definition (the line that begins the location block).

Here is one possible paraphrase:
The overall structure appears in this way.

The configuration file for Nginx is located at /etc/nginx/nginx.conf.
location match_modifier location_match {

    . . .

}

Location blocks are contained within server contexts and can be nested within each other unlike server blocks. This nesting capability is beneficial as it allows for the creation of a broader location context to capture a specific portion of traffic, and then refine the processing based on more specific criteria using additional nested contexts.

The configuration file for Nginx, located at /etc/nginx/nginx.conf.
# main context

server {
    
    # server context

    location /match/criteria {

        # first location context

    }

    location /other/criteria {

        # second location context

        location nested_match {

            # first nested location

        }

        location other_nested {

            # second nested location

        }

    }

}

The choice of server contexts depends on the IP address/port combination and the host name mentioned in the “Host” header, while location blocks further divide the handling of requests within a server block by analyzing the request URI. The request URI refers to the part of the request that comes after the domain name or IP address/port combination.

Let’s say a client wants to access http://www.example.com/blog on port 80. Each component (http, www.example.com, and port 80) is important in deciding which server block to use. Once a server is chosen, the /blog part of the request URL will be checked against the defined locations to determine the appropriate context for responding to the request.

There are several directives that you will probably come across in a specific location context. It is worth noting that many of these directives are also applicable at higher levels. At this level, you can utilize new directives to access locations beyond the document root (alias), designate the location as internally accessible only (internal), and redirect requests to other servers or locations through proxying methods such as http, fastcgi, scgi, and uwsgi.

Different Situations

Other contexts are available in addition to the ones mentioned above when working with Nginx. These specific contexts are either used in specific situations or for functionality that is not commonly needed.

  • split_clients: This context is configured to split the clients that the server receives into categories by labeling them with variables based on a percentage. These can then be used to do A/B testing by providing different content to different hosts.
  • perl / perl_set: These contexts configure Perl handlers for the location they appear in. This will only be used for processing with Perl.
  • map: This context is used to set the value of a variable depending on the value of another variable. It provides a mapping of one variable’s values to determine what the second variable should be set to.
  • geo: Like the above context, this context is used to specify a mapping. However, this mapping is specifically used to categorize client IP addresses. It sets the value of a variable depending on the connecting IP address.
  • types: This context is again used for mapping. This context is used to map MIME types to the file extensions that should be associated with them. This is usually provided with Nginx through a file that is sourced into the main nginx.conf config file.
  • charset_map: This is another example of a mapping context. This context is used to map a conversion table from one character set to another. In the context header, both sets are listed and in the body, the mapping takes place.

The background information leading up to the current situation.

The upstream context is utilized to specify and set up servers referred to as “upstream” servers. This context establishes a pool of servers with a given name that Nginx can subsequently direct requests to. This context will commonly be employed when configuring various types of proxies.

To include the upstream context, it should be located in the http context and not within any particular server contexts. The structure appears as follows:

nginx.conf file which is located in the /etc/nginx directory.
# main context

http {

    # http context

    upstream upstream_name {

        # upstream context

        server proxy_server1;
        server proxy_server2;

        . . .

    }

    server {

        # server context

    }

}

Server or location blocks can make use of the named upstream context to direct requests of a specific type towards a defined set of servers. By default, an algorithm (usually round-robin) is employed by the upstream to select the appropriate server for handling each request. This functionality enables Nginx to perform load balancing while acting as a proxy for requests.

If we consider the context

The “if” context allows for conditional execution of instructions based on a given test, similar to an if statement in traditional programming. In Nginx, if the test returns “true”, the if directive will execute the enclosed instructions.

The rewrite module in Nginx provides the if context, which is primarily intended for conditional execution. However, it is advised against using the if context for most forms of conditional execution because Nginx has other purpose-made directives for testing conditions. The Nginx community emphasizes the significance of this point by creating a page titled “if is evil.”

One issue is that the Nginx processing order frequently produces unforeseen outcomes. The only directives that can be deemed consistently secure to utilize within these contexts are the return and rewrite directives (which were designed for this purpose). Additionally, it is important to note that using an if context renders a try_files directive in the same context pointless.

In most cases, an “if” statement is utilized to ascertain if a rewrite or return is required. Frequently, these statements reside within location blocks, thus the typical format will resemble the following:

nginx.conf file located in the /etc/nginx directory.
# main context

http {

    # http context

    server {

        # server context

        location location_match {

            # location context

            if (test_condition) {

                # if context

            }

        }

    }

}

The Context of the Limit Except directive

The limit_except context is utilized to confine the utilization of specific HTTP methods within a particular location context. For instance, if only certain clients should have the privilege to access POST content, while allowing everyone to have the capacity to read content, this requirement can be defined using a limit_except block.

The example mentioned above would appear similar to this.

nginx.conf is located in the /etc/nginx directory.
. . .

# server or location context

location /restricted-write {

    # location context

    limit_except GET HEAD {

        # limit_except context

        allow 192.168.1.1/24;
        deny all;
    }
}

When the context header is encountered, the directives within it will be enforced to restrict access, excluding the listed HTTP methods. In this scenario, clients are permitted to use the GET and HEAD verbs, while only those originating from the 192.168.1.1/24 subnet can utilize other methods.

Here is one option for paraphrasing the given phrase natively:
“Guidelines to Observe When Considering Contexts.”

Having gained insight into the typical situations you may come across while exploring Nginx configurations, we can now explore some recommended approaches for handling Nginx contexts.

Utilize Directives within the Most Comprehensive Setting Offered.

Several directives can be applied in multiple contexts. For example, numerous directives can be placed within the http, server, or location context, allowing for versatility in configuring these directives.

In general, it is advisable to declare directives at the highest applicable context and override them in lower contexts when needed, which is made possible by Nginx’s implementation of an inheritance model. There are multiple benefits to employing this approach.

To start off, declaring at a higher level helps in avoiding redundant repetition among sibling contexts. For instance, in the given example, all the locations are declaring the identical document root.

The configuration file for Nginx is located at /etc/nginx/nginx.conf.
http {
    server {
        location / {
            root /var/www/html;

            . . .

        }

        location /another {
            root /var/www/html;

            . . .

        }

    }
}

It is possible to relocate the root to either the server block or the http block, as shown:

http {
    root /var/www/html;
    server {
        location / {

            . . .

        }

        location /another {

            . . .

        }
    }
}

In most cases, using the server level is usually the best choice. However, there are advantages to declaring at a higher level. This not only lets you set the directive in fewer locations, but it also ensures that the default value is applied to all child elements. This helps prevent errors that can occur when a directive is accidentally left out at a lower level, which can be particularly problematic in complex configurations. By declaring at higher levels, you establish a reliable default setting.

Instead of using If logic for processing, opt for utilizing multiple sibling contexts.

When you need to handle requests differently based on information in the client’s request, users often resort to using the “if” statement to conditionally process it. However, this approach has a few problems that we mentioned earlier in brief.

One reason is that the “if” statement frequently produces outcomes that do not match what the administrator expects. Even though the execution will always yield the same outcome given identical input, Nginx’s interpretation of the environment may differ from what is assumed unless extensively tested.

Another reason is that there are existing streamlined directives specifically designed for various purposes. Nginx already employs a well-documented algorithm to facilitate the selection of server blocks and location blocks. Whenever feasible, it is advisable to segregate your distinct configurations into separate blocks, enabling this algorithm to efficiently handle the selection process mechanism.

One option for paraphrasing the given sentence natively could be:

For example, instead of depending on rewrites to convert a user’s request into the format you prefer to work with, you should attempt to establish two sections for the request. One section should indicate the intended method, while the other should handle unclear requests by redirecting them (and potentially rewriting them) to the appropriate section.

Typically, the outcome is enhanced readability and improved performance. Accurate requests require no extra processing, while incorrect requests can often be handled with a redirect instead of a rewrite, resulting in reduced overhead.

In conclusion, we can summarize that…

By now, you should have a solid understanding of Nginx’s frequently used contexts and the directives that establish the blocks that define them.

To ensure optimal placement, it is important to refer to Nginx’s documentation for details on contexts where a directive can be used. By carefully crafting your configurations, you can enhance maintainability and frequently enhance performance.

Afterward, you will be able to grasp the process of setting up Nginx for password authentication.

 

 

More tutorials

JSON fundamentals(Opens in a new browser tab)

Common errors that occur when using Nginx for connections.(Opens in a new browser tab)

Spring Component annotation(Opens in a new browser tab)

Dependency Injection in Spring(Opens in a new browser tab)

Python HTTP requests such as GET and POST methods.(Opens in a new browser tab)

 

Leave a Reply 0

Your email address will not be published. Required fields are marked *