Skip to main content

Command Palette

Search for a command to run...

Nginx tutorial

Updated
4 min read
Nginx tutorial
A

I post content on backend concepts along with mini projects and implementations for the same.

Nginx can be used as an HTTP web server or a reverse proxy.

In this blog, we’ll go through the basics of nginx and at the end, we’ll create a simple reverse proxy that can route requests to different servers based on path and load balance those requests as well.

  • The way nginx and its modules work is determined in the configuration file. By default, the configuration file is named nginx.conf and placed in the directory /opt/homebrew/etc/nginx in macOS.

  • The nginx.conf file can be used to configure nginx behaviour.

  • When nginx acts as a proxy the requests coming to the backend servers are from nginx not directly from the client so its important to send the host, port and all client information to the backend server.

Directives

Nginx consists of modules that are controlled by directives. Directives are basically key value pairs.

Directives are divided into simple directives and block directives.

  • A simple directive consists of the name and parameters separated by spaces and ends with a semicolon (;).

  • A block directive has the same structure as a simple directive, but instead of the semicolon it ends with a set of additional instructions surrounded by braces ({and }). If a block directive can have other directives inside braces, it is called a context (examples: events, http, server, and location).

Contexts

A group of related directives is called context.

These are a few top level directives that group together some other directives that apply to different traffic types. Eg.- http(http traffic) , events (connections processing) , mail(Mail traffic), stream(tcp and udp traffic).

Common Directives

worker_processes- (can have number or auto value)

  • Controls how many parallel processes nginx spawns to handle client requests.

  • Each worker process runs independently and can handle its own set of connections.

  • Should be set according to expected traffic and server CPU cores (best practice is to set it equal to number of CPU cores).

  • With the auto value, nginx decides based on CPU cores.

worker_connections- (inside events context)

  • Denotes number of simultaneous connections each worker processes can handle.

  • More connections increase memory usage.

http(context) - determines-

  • Which port to listen to.

  • How to Route requests.

    • server block:

      • listen - Specifies the IP address and port to listen for requests.

      • server_name - Indicates which domain or IP address this server block should respond to.

    • upstream block - Defines a group of servers that will handle requests forwarded by Nginx.

Basic commands

Start nginx

nginx

Stop nginx

nginx -s stop

Reloading the config file (Useful if you made any changes)

nginx -s reload

Example configuration

Here is a simple reverse proxy that -

  • Forwards requests with /admins in path to the admin service that has only one server (no load balancing needed).

  • For requests starting with /users it load balances among the 3 user service servers using the round robin algorithm.

  • It also redirects all http traffic to https. (have used a self signed certificate here)

worker_processes 1;
events {
    worker_connections 700;
}
http {
    include mime.types;   # includes file mimetypes while returning response to the client
    upstream nodejs_cluster {    # defining the servers nginx would forward the request to
        #least_conn; # if dont wanna use the default round robin load balancing algorithm
        server 127.0.0.1:3001;
        server 127.0.0.1:3002;
        server 127.0.0.1:3003;
    }
    server {
        server_name localhost;
        listen 443 ssl;
        ssl_certificate /opt/homebrew/etc/nginx/nginx-selfsigned.crt;
        ssl_certificate_key /opt/homebrew/etc/nginx/nginx-selfsigned.key;
        location /users {
            proxy_pass http://nodejs_cluster;
            # when nginx forwards request the request originates from nginx and not client so we need to send some essential client info to the server.
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;

        }
        location ~ /admins {
            proxy_pass http://localhost:3004;
        }
    }
    server {
        server_name localhost;
        listen 80;
        location / {
            return 301 https://$host$request_uri;  # redirecting to https endpoint of same request
        }
    }
}

Nginx location matching priority

If a path fulfils multiple locations, like /users/admins has both /users and /admins, how would nginx route that particular request? Nginx provides an order of priority that it uses to choose how to route a particular request -

  1. Exact match (location = /path) - Matches the exact path highest priority.

  2. Prefix match with priority (location ^~ /users)

  3. Regex matches (location ~ /admins)

  4. Regular path prefix match (location /users)

In the example configuration proxy, http://localhost:8080/admins, http://localhost:8080/center/admins, http://localhost:8080/admins/users,http://localhost:8080/users/admins all get redirected to server 4 whereas http://localhost:8080/users gets redirected to one of the first 3 servers in round robin fashion.