ZNHOO Whatever you are, be a good one!

Nginx

  1. Nginx Installation
  2. Nginx Overview
  3. Have a Try
  4. Nginx Context
  5. Rule of thumb
  6. Request Processing
  7. Location Match
  8. Multiple if Conditions
  9. Number of Connections
  10. Catch-all Virtual Server

Nginx Installation

~ # dnf install nginx
~ # systemctl enable nginx
~ # systemctl status nginx

Nginx Overview

  1. Starter
  2. Nginx has one master process and several worker processes.
    1. The main purpose of master process is to read and evaluate configurations, maintain worker processes, manage TCP connections etc.
    2. Worker process respond to client requests. The number of worker processes is subject to the number of CPU cores, the storage size of HDDs, load pattern etc.
  3. Nginx employs event-based model and OS-dependent mechanisms to efficiently distribute requests among worker processes.
  4. By default, the configuration file is located within /etc/nginx/nginx.conf.

Have a Try

Firstly, edit, test and reload the configuration:

~ # nginx -t

~ # nginx -s reload
# -or-
~ # systemctl reload nginx

Then start Nginx:

~ # systemctl start nginx
~ # pe -eF | fgrep -i nginx

To terminate Nginx:

~ # nginx -s quit/stop
# -or-
~ # systemctl quit/stop nginx

The quit signal is a graceful method to shutdown the service, waiting for worker processes to finish ongoing requests before stopping all nginx processes.

Nginx Context

A Simple Directive consists of a name and parameters separated by spaces and ends with a semicolon (;).

name arg1 arg2 … argN ;

A Block Directive has the same structure as a simple directive. But the ending semicolon is substituted with a set of additional _instruction_s surrounded by braces ('{' and '}'), like map.

name arg1 arg2 … argN { instructions }

If a Block Directive can have other directives inside braces, it is called a Context, like events, http, server, and location. The location context is what we encounter daily.

name arg1 arg2 … argN { directives; }

Contexts can be nested. For example, the event and http directives reside in the main context, server in http and location in server. The main context is the outmost context. Nginx does not name the main.

Directives outside of any contexts are considered to be in the main context.

# main context

directive1;

event {
    directive2;
    directive3;
}

http {
    directive4;

    map $http_upgrade $connection_header {
        default upgrade;
        '' close;
    }

    server {
        directive5;

        location [ = | ~ | ~* | ^~ ] uri {
            directive6;
            directive7;
        }
        
        directive8;
    }

    directive9;
}

Rule of thumb

Do not Repeat Yourself.

  1. Set directives at their broadest applicable context.
  2. Modular configuration. Different configuration files or directories can be integrated into nginx.conf by the include directive.
    1. sites-available;
    2. sites-enabled;
    3. default.d
    4. modules.d
    5. conf.d

Request Processing

Firstly, nginx determines which server context should serve a request.

  1. It tests the IP and port of the listen directive.

    If the the request is received at the specified IP and/or port, the server context is selected as a candidate.

  2. For each selected candidate, Nginx tests the '$host' variable against the server_name directive and select the matched server context.
  3. If none of the candidates match, then choose the default server context.

    There is a special directive called default_server that is a property of the port part of listen directive, NOT that of server_name directive. Therefore, different default_server can be configured for different ports. Check whatever!

Location Match

Once a server context is determined, a location should be chosen as well. Nginx tests the request line without query arguments, namely the uri part.

A general location context is as location optional_modifier uri { }. The optional_modifier can be one of = | ~ | ~* | ^~. If none of the modifiers are provided, it is called prefix match.

  1. = means exact match.
  2. ~ (case-sensitive) and ~* (case-insensitive) do regex match.
  3. ^~ is a special prefix match. If the relevant uri has the longest prefix, regex match is omited. Hence, we call it not regex match.

The match order is as the following:

  1. Firstly, do = match. If matched, terminate the search.
  2. Secondly, do prefix match that searches the longest prefix, irrespective of location order.
    1. If the longest match has modifier ^~, then terminate the search.
    2. Otherwise, the longest match is kept as a candidate.
  3. Thirdly, do regex in the order of their appearance in the configuration file.
    1. The first matched regex terminates the search.
    2. If none of the regexn is matched, then the longest prefix match in 2.2 is selected.

Multiple if Conditions

Nginx if does not support the and or or operator. To achieve or, use separate if directive. For and operator, we can set a variable and then concatenate multiple values together as below.

if ($request_uri = /) {
  set $con root;
}

if ($host ~* example.com) {
  set $con "${con}+example.com";
}

if ($http_cookie !~* "auth_token") {
  set $con "${con}+no_auth_token";
}

if ($con = "root+example.com+no_auth_token") {
  return 403;
}

Number of Connections

By default, a single worker process allows 1024 connections simutaneously. We can litmit the number by:

events {
    worker_connections 50;
}

Catch-all Virtual Server

# catch-all 'default_server' vhosts

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;
    root /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
	    # Use "$host" instead of "$server_name" unless you have special needs.
        #return 301 https://$server_name$request_uri;
        return 301 https://$host$request_uri;
    }

    error_page 404 /40x.html;
    location = /40x.html {
        internal;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        internal;
    }
}

# Settings for a TLS enabled server.

server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;

    server_name _;
    root /usr/share/nginx/html;

    # Let's Encrypt will start offer wildcard certs beginning 2018
    ssl_certificate "/etc/letsencrypt/live/example.com/fullchain.pem";
    ssl_certificate_key "/etc/letsencrypt/live/example.com/privkey.pem";
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
        return 404;
    }

    error_page 404 /40x.html;
    location = /40x.html {
        internal;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        internal;
    }

}
  1. All HTTP requests are redirected (301) to HTTPS.
  2. Trigger 404 code, telling end users that the request is not expected.
  3. Attention to server_name: _;