Nginx has emerged as a robust and scalable general-purpose web server in the last decade. It is a choice of many webmasters, startup founders, and site reliability engineers because of its simple yet scalable and expandable architecture, easy configuration, and light memory footprint. Nginx offers a lot of useful features, such as on-the-fly compression and caching out of the box.
Nginx integrates with existing web technologies such as Apache web server and PHP, and helps solving day-to-day problems in an easy way. Nginx is backed by a large, active community as well as a consulting company funded by venture capital. Therefore, it is actively supported.
This book will help you get started with Nginx and learn skills necessary to turn it into a powerful tool, a workhorse that will help you to solve your day-to-day challenges.
Before you can dive into specific features of Nginx, you need to learn how to install Nginx on your system.
It is strongly recommended that you use prebuilt binary packages of Nginx if they are available in your distribution. This ensures best integration of Nginx with your system and reuse of best practices incorporated into the package by the package maintainer. Prebuilt binary packages of Nginx automatically maintain dependencies for you and package maintainers are usually fast to include security patches, so you don't get any complaints from security officers. In addition to that, the package usually provides a distribution-specific startup script, which doesn't come out of the box.
Refer to your distribution package directory to find out if you have a prebuilt package for Nginx. Prebuilt Nginx packages can also be found under the download link on the official Nginx.org site.
In this chapter, we will quickly go through most common distributions that contain prebuilt packages for Nginx.
The Ubuntu Linux distribution contains a prebuilt package for Nginx. To install it, simply run the following command:
$ sudo apt-get install nginx
The preceding command will install all the required files on your system, including the logrotate
script and service autorun scripts. The following table describes the Nginx installation layout that will be created after running this command as well as the purpose of the selected files and folders:
Description |
Path/Folder |
---|---|
Nginx configuration files |
|
Main configuration file |
|
Virtual hosts configuration files (including default one) |
|
Custom configuration files |
|
Log files (both access and error log) |
|
Temporary files |
|
Default virtual host files |
|
Note
Default virtual host files will be placed into /usr/share/nginx/html
. Please keep in mind that this directory is only for the default virtual host. For deploying your web application, use folders recommended by Filesystem Hierarchy Standard (FHS).
Now you can start the Nginx service with the following command:
$ sudo service nginx start
This will start Nginx on your system.
Nginx is not provided out of the box in Red Hat Enterprise Linux or CentOS/Scientific Linux. Instead, we will use the Extra Packages for Enterprise Linux (EPEL) repository. EPEL is a repository that is maintained by Red Hat Enterprise Linux maintainers, but contains packages that are not a part of the main distribution for various reasons. You can read more about EPEL at https://fedoraproject.org/wiki/EPEL.
To enable EPEL, you need to download and install the repository configuration package:
For RHEL or CentOS/SL 7, use the following link:
http://download.fedoraproject.org/pub/epel/7/x86_64/repoview/epel-release.html
For RHEL/CentOS/SL 6 use the following link:
http://download.fedoraproject.org/pub/epel/6/i386/repoview/epel-release.html
If you have a newer/older RHEL version, please take a look at the How can I use these extra packages? section in the original EPEL wiki at the following link:
Now that you are ready to install Nginx, use the following command:
# yum install nginx
The preceding command will install all the required files on your system, including the logrotate
script and service autorun scripts. The following table describes the Nginx installation layout that will be created after running this command and the purpose of the selected files and folders:
Description |
Path/Folder |
---|---|
Nginx configuration files |
/ |
Main configuration file |
|
Virtual hosts configuration files (including default one) |
|
Custom configuration files |
|
Log files (both access and error log) |
|
Temporary files |
|
Default virtual host files |
|
Note
Default virtual host files will be placed into /usr/share/nginx/html
. Please keep in mind that this directory is only for the default virtual host. For deploying your web application, use folders recommended by FHS.
By default, the Nginx service will not autostart on system startup, so let's enable it. Refer to the following table for the commands corresponding to your CentOS version:
Function |
Cent OS 6 |
Cent OS 7 |
---|---|---|
Enable Nginx startup at system startup |
|
|
Manually start Nginx |
|
|
Manually stop Nginx |
|
|
Traditionally, Nginx is distributed in the source code. In order to install Nginx from the source code, you need to download and compile the source files on your system.
Note
It is not recommended that you install Nginx from the source code. Do this only if you have a good reason, such as the following scenarios:
You are a software developer and want to debug or extend Nginx
You feel confident enough to maintain your own package
A package from your distribution is not good enough for you
You want to fine-tune your Nginx binary
In either case, if you are planning to use this way of installing for real use, be prepared to sort out challenges such as dependency maintenance, distribution, and application of security patches.
In this section, we will be referring to the configuration script. Configuration script is a shell script similar to one generated by autoconf, which is required to properly configure the Nginx source code before it can be compiled. This configuration script has nothing to do with the Nginx configuration file that we will be discussing later.
The primary source for Nginx for an English-speaking audience is Nginx.org. Open http://nginx.org/en/download.html in your browser and choose the most recent stable version of Nginx. Download the chosen archive into a directory of your choice (/usr/local
or /usr/src
are common directories to use for compiling software):
$ wget -q http://nginx.org/download/nginx-1.7.9.tar.gz
Extract the files from the downloaded archive and change to the directory corresponding to the chosen version of Nginx:
$ tar xf nginx-1.7.9.tar.gz $ cd nginx-1.7.9
To configure the source code, we need to run the ./configure
script included in the archive:
$ ./configure checking for OS + Linux 3.13.0-36-generic i686 checking for C compiler ... found + using GNU C compiler [...]
This script will produce a lot of output and, if successful, will generate a Makefile
file for the source files.
Notice that we showed the non-privileged user prompt $
instead of the root #
in the previous command lines. You are encouraged to configure and compile software as a regular user and only install as root. This will prevent a lot of problems related to access restriction while working with the source code.
The troubleshooting step, although very simple, has a couple of common pitfalls. The basic installation of Nginx requires the presence of OpenSSL and Perl-compatible Regex (PCRE) developer packages in order to compile. If these packages are not properly installed or not installed in locations where the Nginx configuration script is able to locate them, the configuration step might fail.
Then, you have to choose between disabling the affected Nginx built-in modules (rewrite or SSL, installing required packages properly, or pointing the Nginx configuration script to the actual location of those packages if they are installed.
You can build the source files now using the following command:
$ make
You'll see a lot of output on compilation. If build is successful, you can install the Nginx file on your system. Before doing that, make sure you escalate your privileges to the super user so that the installation script can install the necessary files into the system areas and assign necessary privileges. Once successful, run the make install
command:
# make install
The preceding command will install all the necessary files on your system. The following table lists all locations of the Nginx files that will be created after running this command and their purposes:
Description |
Path/Folder |
---|---|
Nginx configuration files |
|
Main configuration file |
|
Log files (both access and error log) |
|
Temporary files |
|
Default virtual host files |
|
Note
Unlike installations from prebuilt packages, installation from source files does not harness Nginx folders for the custom configuration files or virtual host configuration files. The main configuration file is also very simple in its nature. You have to take care of this yourself.
Nginx must be ready to use now. To start Nginx, change your working directory to the /usr/local/nginx
directory and run the following command:
# sbin/nginx
This will start Nginx on your system with the default configuration.
This stage works flawlessly most of the time. A problem can occur in the following situations:
Switch off third-party modules that break your build or contact the developer for assistance.
Occasionally you might want to amend Nginx binary from a prebuilt packages with your own changes. In order to do that you need to reproduce the build tree that was used to compile Nginx binary for the prebuilt package.
But how would you know what version of Nginx and what configuration script options were used at the build time? Fortunately, Nginx has a solution for that. Just run the existing Nginx binary with the -V
command-line option. Nginx will print the configure-time options. This is shown in the following:
$ /usr/sbin/nginx -V nginx version: nginx/1.4.6 (Ubuntu) built by gcc 4.8.2 (Ubuntu 4.8.2-19ubuntu1) TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro' …
Using the output of the preceding command, reproduce the entire build environment, including the Nginx source tree of the corresponding version and modules that were included into the build.
Note
Here, the output of the Nginx -V
command is trimmed for simplicity. In reality, you will be able to see and copy the entire command line that was passed to the configuration script at the build time.
You might even want to reproduce the version of the compiler used in order to produce a binary-identical Nginx executable file (we will discuss this later when discussing how to troubleshoot crashes).
Once this is done, run the ./configure
script of your Nginx source tree with options from the output of the -V
option (with necessary alterations) and follow the remaining steps of the build procedure. You will get an altered Nginx executable on the objs/
folder of the source tree.
When Nginx is installed, we can quickly study the structure of the installation. This will help you to know your installation better and manage it more confidently.
For each installation method, we have a set of generic locations and default paths. Let's see what these default locations contain.
This folder contains the main configuration file and a set of parameter files. The following table describes the purpose of each of the default parameter files:
The default configuration contains references to this site as root. It is not recommended that you use this directory for real sites, as it is not a good practice for the Nginx folders hierarchy to contain the site hierarchy. Use this directory for testing purposes or for serving auxiliary files.
This is the location of virtual host configuration files. The recommended structure of this folder is to have one file per virtual host in this folder or one folder per virtual host, containing all files related to this virtual host. In this way, you will always know which files were used and which are now being used, and what each of the files contain and which files can be purged.
This is the location for Nginx log files. The default access log file and error log file will be written to this location. For installation from source files, it is not recommended that you use the default location /usr/local/nginx/logs
for real sites. Instead, make sure all your log files are stored in the system log file location, such as /var/log/nginx
, to provide better overview and management of your log files.
Now that you know how to install Nginx and the structure of its installation, we can study how to configure Nginx. Simplicity of configuration is one of the reasons Nginx is popular among webmasters, because this saves them a lot of time.
In a nutshell, Nginx configuration files are simply sequences of directives that can take up to eight space-separated arguments, for example:
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
In the configuration file, the directives are delimited by a semicolon (;
) from one another. Some of the directives may have a block instead of a semicolon. A block is delimited by curly brackets ({}
). A block can contain arbitrary text data, for example:
types { text/html html htm shtml; text/css css; text/xml xml; image/gif gif; image/jpeg jpeg jpg; application/x-javascript js; application/atom+xml atom; application/rss+xml rss; }
A block can also contain a list of other directives. In this case, the block is called a section. A section can enclose other sections, thus establishing a hierarchy of sections.
Most important directives have short names; this reduces the effort required to maintain the configuration file.
In general, a directive can have arbitrary quoted or unquoted strings as arguments. But many directives have arguments that have common value types. To help you quickly get your head around the value types I listed them in the following table:
Value type |
Format |
Example of a value |
---|---|---|
Flag |
[on|off] |
|
Signed integer |
-?[0-9]+ |
|
Size |
[0-9]+([mM]|[kK])? |
|
Offset |
[0-9]+([mM]|[kK]|[gG])? |
|
Milliseconds |
[0-9]+[yMwdhms]? |
|
Variables are named objects that can be assigned a textual value. Variables can only appear inside the http
section. A variable is referred to by its name, prefixed by the dollar ($
) symbol. Alternatively, a variable reference can enclose a variable name in curly brackets to prevent merging with surrounding text.
Variables can be used in any directive that accepts them, as shown here:
proxy_set_header Host $http_host;
This directive sets the HTTP header host in a forwarded request to HTTP host name from the original request. This is equivalent to the following:
proxy_set_header Host ${http_host};
With the following syntax, you can specify the host name:
proxy_set_header Host ${http_host}_squirrel;
The preceding command will append a string _squirrel
to the value of the original host name. Without curly brackets, the string _squirrel
would have been interpreted as a part of the variable name, and the reference would have pointed to a variable "http_host_squirrel" rather than http_host
.
There are also special variable names:
Variables from
$1
to$9
refer to the capture arguments in the regular expressions, as shown here:location ~ /(.+)\.php$ { [...] proxy_set_header X-Script-Name $1; }
The preceding configuration will set the HTTP header
X-Script-Name
in the forwarded request to the name of the PHP script in the request URI. The captures are specified in a regular expression using round brackets.Variables that start with
$arg_
refer to the corresponding query argument in the original HTTP request, as shown here:proxy_set_header X-Version-Name $arg_ver;
The preceding configuration will set the HTTP header
X-Version-Name
in the forwarded request to the value of thever
query argument in the original request.Variables that start with
$http_
refer to the corresponding HTTP header line in the original request.Variables that start with
$sent_http_
refer to the corresponding HTTP header line in the outbound HTTP request.Variables that start with
$upstream_http_
refer to the corresponding HTTP header line in the response received from an upstream.Variables that start with
$cookie_ refer
to the corresponding cookie in the original request.Variables that start with
$upstream_cookie_
refer to the corresponding cookie in the response received from an upstream.
Variables must be declared by Nginx modules before they can be used in the configuration. Built-in Nginx modules provide a set of core variables that allow you to operate with the data from HTTP requests and responses. Refer to the Nginx documentation for the complete list of core variables and their functions.
Third-party modules can provide extra variables. These variables have to be described in the third-party module's documentation.
Any Nginx configuration section can contain inclusions of other files via the include
directive. This directive takes a single argument containing a path to a file to be included, as shown here:
/* * A simple relative inclusion. The target file's path * is relative to the location of the current configuration file. */ include mime.types; /* * A simple inclusion using an absolute path. */ include /etc/nginx/conf/site-defaults.conf;
Once specified, the include
directive instructs Nginx to process the contents of the file or files specified by the argument of this directive as if they were specified in place of the include
directive.
Note
Relative paths are resolved with respect to the path of the configuration file the directive is specified in. This is good to keep in mind when the include
directive is specified in another included file, such as when a virtual host configuration file contains a relative include
directive.
The include
directive can also contain a globbed path with wild cards, either relative or absolute. In this case, the globbed path is expanded and all files matching the specified pattern are included in no particular order. Take a look at the following code:
/* * A simple glob inclusion. This will include all files * ending on ".conf" located in /etc/nginx/sites-enabled */ include /etc/nginx/sites-enabled/*.conf;
The include
directive with wild cards is an obvious solution for including site configurations, as their number can vary greatly. Using the include
directive, you can properly structure the configuration file or reuse certain parts multiple times.
A section is a directive that encloses other directives in its block. Each section's delimiters must be located in the same file, while the content of a section can span multiple files via the include
directive.
It is not possible to describe every possible configuration directive in this chapter. Refer to the Nginx documentation for more information. However, I will quickly go over the Nginx configuration section types so that you can orient in the structure of the Nginx configuration files.
The http
section enables and configures the HTTP service in Nginx. It has the server and upstream declarations. As far as individual directives are concerned, the http
section usually contains those that specify defaults for the entire HTTP service.
The http
section must contain at least one server
section in order to process HTTP requests. Here is a typical layout of the http
section:
http { [...] server { [...] } }
Here and in other examples of this book, we use […]
to refer to omitted irrelevant parts of the configuration.
The server
section configures an HTTP or HTTPS virtual host and specifies listening addresses for them using the listen
directive. At the end of the configuration stage, all listening addresses are grouped together and all listening addresses are activated at startup.
The server
section contains the location
sections, as well as sections that can be enclosed by the location
section (see description of other sections types for details). Directives that are specified in the server
section itself go into the so-called default location. In that regard, the server
section serves the purpose of the location
section itself.
When a request comes in via one of the listening addresses, it is routed to the server
sections that match a virtual host pattern specified by the server_name
directive. The request is then routed further to the location that matches the path of the request URI or processed by the default location if there is no match.
The upstream
section configures a logical server that Nginx can pass requests to for further processing. This logical server can be configured to be backed by one or more physical servers external to Nginx with concrete domain names or IP addresses.
Upstream can be referred to by name from any place in the configuration file where a reference to a physical server can take place. In this way, your configuration can be made independent of the underlying structure of the upstream, while the upstream structure can be changed without changing your configuration.
The location
section is one of the workhorses in Nginx. The location
directive takes parameters that specify a pattern that is matched against the path of the request URI. When a request is routed to a location, Nginx activates configuration that is enclosed by that location
section.
There are three types of location patterns: simple, exact, and regular expression location patterns.
A simple location has a string as the first argument. When this string matches the initial part of the request URI, the request is routed to that location. Here is an example of a simple location:
location /images { root /usr/local/html/images; }
Any request with a URI that starts with /images
, such as /images/powerlogo.png
, /images/calendar.png
, or /images/social/github-icon.png
will be routed to this location. A URI with a path that equals to /images
will be routed to this location as well.
Exact locations are designated with an equals (=
) character as the first argument and have a string as the second argument, just like simple locations do. Essentially, exact locations work just like simple locations, except that the path in the request URI has to match the second argument of the location
directive exactly in order to be routed to that location:
location = /images/empty.gif { emptygif; }
The preceding configuration will return an empty GIF file if and only if the URI /images/empty.gif
is requested.
Regular expression locations are designated with a tilde (~
) character or ~*
(for case-insensitive matches) as the first argument and have a regular expression as the second argument. Regular expression locations are processed after both simple and exact locations. The path in the request URI has to match the regular expression in the second argument of the location
directive in order to be routed to that location. A typical example is as follows:
location ~ \.php$ { [...] }
According to the preceding configuration, requests with URIs that end with .php
will be routed to this location.
The location
sections can be nested. For that, you just need to specify a location
section inside another location
section.
The if
section encloses a configuration that becomes active once a condition specified by the if
directive is satisfied. The if
section can be enclosed by the server
and location
sections, and is only available if the rewrite
module is present.
A condition of an if
directive is specified in round brackets and can take the following forms:
A plain variable, as shown here:
if ($file_present) { limit_rate 256k; }
If the variable evaluates to true value in runtime, the configuration section activates.
A unary expression that consists of an operator and a string with variables, as shown here:
if ( -d "${path}" ) { try_files "${path}/default.png" "${path}/default.jpg"; }
The following unary operators are supported:
A binary expression that consists of a variable name, an operator, and a string with variables. The following binary operators are supported:
Let's discuss some examples of the if
directive.
This one adds a prefix /msie/
to the URL of any request that contains MSIE
in the user-agent field:
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; }
The next example sets the variable $id
to the value of the cookie named id
, if it is present:
if ($http_cookie ~* "id=([^;]+)(?:;|$)") { set $id $1; }
The next one returns HTTP status 405
("Method Not Allowed") for every request with the method POST
:
if ($request_method = POST) { return 405; }
Finally, the configuration in the following example limits the rate to 10 KB whenever the variable $slow
evaluates to true:
if ($slow) { limit_rate 10k; }
The if
directive seems like a powerful instrument, but it must be used with caution. This is because the configuration inside the if
section is not imperative, that is, it does not alter the request processing flow according to the order of the if
directives.
Conditions are not evaluated in the order they are specified in the configuration file. They are merely applied simultaneously and configuration settings from the sections for which conditions were satisfied are merged together and applied at once.
The limit_except
section activates the configuration that it encloses if the request method does not match any from the list of methods specified by this directive. Specifying the GET
method in the list of methods automatically assumes the HEAD
method. This section can only appear inside the location
section, as shown here:
limit_except GET { return 405; }
The preceding configuration will respond with HTTP status 405
("Method Not Allowed") for every request that is not made using the GET
or HEAD
method.
Nginx configuration can contain other section types, such as main
and server
in the main
section, as well as section types provided by third-party modules. In this book, we will not pay close attention to them.
Refer to the documentation of the corresponding modules for information about these types of configuration sections.
Many Nginx configuration settings can be inherited from a section of outer level to a section of inner level. This saves a lot of time when you configure Nginx.
The following figure illustrates how inheritance rules work:

All settings can be attributed to three categories:
Those that make sense only in the entire HTTP service (marked red)
Those that make sense in the virtual host configuration (marked blue)
Those that make sense on all levels of configuration (marked green)
The settings from the first category do not have any inheritance rules, because they cannot inherit values from anywhere. They can be specified in the http
section only and can be applied to the entire HTTP service. These are settings set by directives, such as variables_hash_max_size
, variables_hash_bucket_size
, server_names_hash_max_size
, and server_names_hash_bucket_size
.
The settings from the second category can inherit values only from the http
section. They can be specified both in the http
and server
sections, but the settings applied to a given virtual host are determined by inheritance rules. These are settings set by directives, such as client_header_timeout
, client_header_buffer_size
, and large_client_header_buffers
.
Finally, the settings from the third category can inherit values from any section up to http
. They can be specified in any section inside the HTTP service configuration, and the settings applied to a given context are determined by inheritance rules.
The arrows on the figure illustrate value propagation paths. The colors of the arrows specify the scope of the setting. The propagation rules along a path are as follows:
When you specify a value for a parameter at a certain level of the configuration, it overrides the value of the same parameter at the outer levels if it is set, and automatically propagates to the inner levels of the configuration. Let's take a look at the following example:
location / { # The outer section root /var/www/example.com; gzip on; location ~ \.js$ { # Inner section 1 gzip off; } location ~ \.css$ { # Inner section 2 } [...] }
The value of the root
directive will propagate to the inner sections, so there is no need to specify it again. The value of the gzip
directive in the outer section will propagate to the inner sections, but will be overridden by the value of the gzip
directive inside the first inner section. The overall effect of that will be that gzip
compression will be enabled everywhere in the other section, except for the first inner section.
When a value for some parameter is not specified in a given configuration section, it is inherited from a section that encloses the current configuration section. If the enclosing section does not have this parameter set, the search goes to the outer level and so on. If a value for a certain parameter is not specified at all, a built-in default value is used.
By this point in the chapter, you might have accumulated a lot of knowledge without having an idea of what a complete working configuration looks like. We will study a short but functioning configuration that will give you an idea of what a complete configuration file might look like:
error_log logs/error.log; events { use epoll; worker_connections 1024; } http { include mime.types; default_type application/octet-stream; server { listen 80; server_name example.org www.example.org; location / { proxy_pass http://localhost:8080; include proxy_params; } location ~ ^(/images|/js|/css) { root html; expires 30d; } } }
This configuration first instructs Nginx to write the error log to logs/error.log
. Then, it sets up Nginx to use the epoll event processing method (use epoll
) and allocates memory for 1024 connections per worker (worker_connections 1024
). After that, it enables the HTTP service and configures certain default settings for the HTTP service (include mime.types
, default_type application/octet-stream
). It creates a virtual host and sets its names to example.org
and www.example.org
(server_name example.org www.example.org
). The virtual host is made available at the default listening address 0.0.0.0
and port 80 (listen 80
).
We then configure two locations. The first location passes every request routed to it into a web application server running at http://localhost:8080
(proxy_pass http://localhost:8080
). The second location is a regular expression location. By specifying it we effectively exclude a set of paths from the first location. We use this location to return static data such as images, JavaScript files, and CSS files. We set the base directory for our media files as html
(root html
). For all media files, we set the expiration date as 30 days (expires 30d
).
To try out this configuration, back up your default configuration file and replace the content of the default configuration file with the preceding configuration.
Then, restart Nginx for the settings to take effect. After this is done, you can navigate to the URL http://localhost/
to check out your new configuration.
Now that you know more about the elements and structure of the Nginx configuration file, you might be curious about what best practices exist in this area. Here is a list of recommendations that will help you to maintain your configuration more efficiently and make it more robust and manageable:
Structure your configuration well. Observe which common parts of the configuration are used more often, move them to separate files, and reuse them using the
include
directive. In addition to that, try to make each file in your configuration file hierarchy of a reasonable length, ideally no more than two screens. This will help you to read your files quicker and navigate over them efficiently.Minimize use of the
if
directive. Theif
directive has a nonintuitive behavior. Try to avoid using it whenever possible to make sure configuration settings are applied to the incoming requests as you expect.Use good defaults. Experiment with inheritance rules and try to come up with defaults for your settings so that they result in the least number of directives to be configured. This includes moving common settings from location to the server level and further to the HTTP level.
In this chapter, you learned how to install Nginx from a number of available sources, the structure of Nginx installation and the purpose of various files, the elements and structure of the Nginx configuration file, and how to create a minimal working Nginx configuration file. You also learned about some best practices for Nginx configuration.
In the next chapter, you will learn how to put Nginx into operation and how to manage it in action.