NGINX : Starter

Durgesh Verma
6 min readApr 3, 2022

Here in this Story we will be covering basically three things for NGINX:

  1. Basic Concept
  2. Performance Managment
  3. SSL/TLS Setup

Hearing this term NGINX first time?

So here is the answer for you

Nginx (pronounced as “Engine X”) is a high performance web server and also works as a reverse proxy server. It was originally developed to tackle the C10K Problem which means serving 10.000 concurrent connections.

NGINX is much more than just being a web server . We can use NGINX as a reverse proxy server as well, making for easy integration with slow upstream servers like . We can distribute your traffic properly (load balancing), stream media, resize your images on the fly, cache content, and much more.

When serving as a reverse proxy, Nginx is acting as a front web server which passes the incoming requests on to web servers on the back, on different ports etc.

Nginx can then handle aspects like SSL / HTTPS, GZip, cache headers, load balancing and a lot of other stuff. The web servers on the back then do not need to know how to handle all this stuff. And we only have one web server for which we need to learn how to configure SSL / TLS , GZip etc. — and that is Nginx. I use Nginx in front of Jetty / Netty. Nginx handles all the SSL / HTTPS stuff, and Jetty just serves ordinary HTTP requests on the back.

The baseline nginx architecture consists of a master process and its workers. The master is supposed to read the conf file and maintain workers processes, while workers do the actual processing of requests.

NGINX can be downloaded and installed from nginx

Basic Commands:

To start nginx server

[sudo] nginx

While our nginx server is running, we can manage it by sending signals:

[sudo] nginx -s signal

Available signals:

  • stop: fast shutdown
  • quit: graceful shutdown (wait for workers to finish their processes)
  • reload: reload the configuration file
  • reopen: reopen the log files.

Configuration files / Directives / Contexts:

By default, the nginx configuration file can be found in:

  • /etc/nginx/nginx.conf,
  • /usr/local/etc/nginx/nginx.conf, and
  • /usr/local/nginx/conf/nginx.conf

This files consists of directives and contexts.

Directives are the options that consists of name and parameters and it ends with an semi-colon ;

gzip on; 

Contexts are the section where we can declare the directives.

worker_processes 2; # directive in global context

http { # http context
gzip on; # directive in http context

server { # server context
listen 80; # directive in server context
}
}

Types of Directives:

a) Normal:

It has one value per context. Also, it can be defined only once in the context. Sub contexts can override the parent directive, but this override will be valid only in a given sub context.

gzip on;
gzip off; # illegal to have 2 normal directives in same context

server {
location /downloads {
gzip off;
}

location /assets {
# gzip is in here
}
}

b) Array

It adds multiple directives in the same context will add to the values instead of overwriting them altogether. Defining a directive in a subcontext will override ALL parent values in the given subcontext.

error_log /var/log/nginx/error.log;
error_log /var/log/nginx/error_notive.log notice;
error_log /var/log/nginx/error_debug.log debug;

server {
location /downloads {
# this will override all the parent directives
error_log /var/log/nginx/error_downloads.log;
}
}

c) Action Directive

Actions are directives that change things. Their inheritance behaviour will depend on the module.

server {
rewrite ^ /foobar;

location /foobar {
rewrite ^ /foo;
rewrite ^ /bar;
}
}

d) Processing Requests

Inside nginx, you can specify multiple virtual servers, each described by a server { } context.

server {
listen *:80 default_server;
server_name durgesh.co;

return 200 "Hello from durgesh.co";
}

server {
listen *:80;
server_name foo.co;

return 200 "Hello from foo.co";
}

server {
listen *:81;
server_name bar.co;

return 200 "Hello from bar.co";
}

It gives NGINX some insights to handle incoming requests . Nginx will first check the listen directive to test which virtual server is listening on the given IP:port combination. Then, the value from server_name directive is tested against the Host header, which stores the domain name of the server.

Nginx will choose the virtual server in the following order:

  1. Server listing on IP:port, with a matching server_name directive;
  2. Server listing on IP:port, with the default_server flag;
  3. Server listing on IP:port, first one defined;
  4. If there are no matches, refuse the connection.

e) server_name Directive

The server_name directive accepts multiple values. It also handles wildcard matching and regular expressions.

server_name durgesh_host.co www.durgesh.co; # exact match
server_name *.durgesh.co; # wildcard matching
server_name durgesh.*; # wildcard matching
server_name ~^[0-9]*\.durgesh\.co$; # regexp matching

When there is ambiguity, nginx uses the following order:

  1. Exact name;
  2. Longest wildcard name starting with an asterisk, e.g. “*.example.org”;
  3. Longest wildcard name ending with an asterisk, e.g. “mail.*”;
  4. First matching regular expression (in the order of appearance in the configuration file).

Nginx will store 3 hash tables: exact names, wildcards starting with an asterisk, and wildcards ending with an asterisk. If the result is not in any of the tables, the regular expressions will be tested sequentially.

f) listen Directive

In most cases, you’ll find that the listen directive accepts IP:port values.

listen 127.0.0.1:80;
listen 127.0.0.1; # by default port :80 is used
listen *:81;
listen 81; # by default all ips are used
listen [::]:80; # IPv6 addresses
listen [::1]; # IPv6 addresses

However, it is also possible to specify UNIX-domain sockets:

listen unix:/var/run/nginx.sock;

You can even use hostnames:

listen localhost:80;
listen netguru.co:80;

This should be used with caution, as the hostname may not be resolved upon nginx’s launch, causing nginx to be unable to bind on a given TCP socket.

Finally, if the directive is not present, *:80, is used.

other Imp Directives:

root , location and try_files directive .

The root directive sets the root directory for requests, allowing nginx to map the incoming request onto the file system.

server {
listen 80;
server_name durgesh.co;
root /var/www/durgesh.co;
}

Which allows nginx to return server content according to the request:

netguru.co:80/index.html     # returns /var/www/durgesh.com/index.html
netguru.co:80/foo/index.html # returns /var/www/durgesh.com/foo/index.html

The location directive sets the configuration depending on the requested URI.

location /foo {
# ...
}

When no modifier is specified, the path is treated as prefix, after which anything can follow. The above example will match:

/foo
/fooo
/foo123
/foo/bar/index.html
...

Also, multiple location directives can be used in a given context:

server {
listen 80;
server_name durgesh.co;
root /var/www/durgesh.co;
location / {
return 200 "root";
}
location /foo {
return 200 "foo";
}
}
durgesh.co:80 / # => "root"
durgesh.co:80 /foo # => "foo"
durgesh.co:80 /foo123 # => "foo"
durgesh.co:80 /bar # => "root"

Nginx also provides a few modifiers which can be used in conjunction with location. These modifiers impact which location block will be used, as each modifier has assigned precedence.

=           - Exact match
^~ - Preferential match
~ && ~* - Regex match
no modifier - Prefix match

Nginx will first check for any exact matches. If it doesn’t find any, it’ll look for preferential ones. If this match also fails, regex matches will be tested in the order of their appearance. If everything else fails, the last prefix match will be used.

location /match {
return 200 'Prefix match: matches everything that starting with /match';
}
location ~* /match[0-9] {
return 200 'Case insensitive regex match';
}
location ~ /MATCH[0-9] {
return 200 'Case sensitive regex match';
}
location ^~ /match0 {
return 200 'Preferential match';
}
location = /match {
return 200 'Exact match';
}
/match # => 'Exact match'
/match0 # => 'Preferential match'
/match1 # => 'Case insensitive regex match'
/MATCH1 # => 'Case sensitive regex match'
/match-abc # => 'Prefix match: matches everything that starting with /match'

try_files directive

This directive will try different paths, returning whichever is found.

try_files $uri index.html =404;

So for /foo.html , it will try to return files in the following order:

  1. $uri ( /foo.html );
  2. index.html;
  3. If none is found: 404.

What’s interesting, if we define try_files in a server context, and then define a location that matches all requests, our try_files will not be executed. This will happen because try_files in a server context defines its own pseudo-location, which is the least specific location possible. Therefore, defining location / will be more specific than our pseudo-location.

server {
try_files $uri /index.html =404;
location / {
}
}

Thus, you should avoid try_files in a server context:

server {
location / {
try_files $uri /index.html =404;
}
}

That’s all for NGINX Starter!

If you want to explore more on the NGINX please refer below links:

Please leave your feedback and comments .

--

--