This blog post summarizes basic use-cases of NGINX, namely static hosting, reverse proxy, and load balancer.
It provides fully-reproducible configuration setup using Docker for each use-case.
What is NGINX?
NGINX is a popular web services middleware that can be used as static hosting, reverse proxy, load balancer, and HTTP cache.
It is an open-source software with FreeBSD license.
Why is NGINX so popular?
ChatGPT answers the following (emphasis by me):
NGINX is popular for several reasons:
High Performance and Scalability: NGINX is known for its high performance and scalability, capable of handling thousands of concurrent connections with low resource consumption. This makes it ideal for high-traffic websites and web applications.
Easy to Configure and Customize: NGINX has a simple and intuitive configuration system, making it easy to customize and optimize for specific use cases. It also has a large ecosystem of modules and plugins that can extend its functionality.
Reliability and Stability: NGINX is highly reliable and stable, with a low rate of crashes and failures. It uses an event-driven, asynchronous architecture to handle multiple connections efficiently, and can be configured to automatically recover from failures.
Security: NGINX has several built-in security features, including SSL and TLS encryption, access control, and anti-DDoS measures. It also supports integration with third-party security tools and services.
Open-Source and Community Support: NGINX is open-source software, which means that it is freely available and can be modified and distributed by anyone. It has a large and active community of developers and users, who contribute to its development, documentation, and support.
As a side note, not all the open-source software can be modified and distributed without any restrictions. However, NGINX's licence (FreeBSD) is one of the very permissive licenses and that's why.
Setup using Docker
Before diving into use cases, we need to install Docker and clone the demo repository.
Installation
This section uses Docker, so if you have not installed it yet, please do so now.
I recommend that if your operating system is Mac or Windows, download Docker Desktop (free for individuals and small-scale enterprises) or Rancher Desktop (free for anyone). Those softwares come with a virtual machine to instantiate a Linux VM on which docker runs.
If you are using Linux, you can install docker command using the package manager.
Verify installation
- Open the terminal and run 
docker run --rm -p 8080:80 nginxto start an NGINX container from the official image - Then, open your browser and visit http://localhost:8080/
 - If you see "Welcome to nginx!" page, then installation and setup are successful
 
You can stop the running container with Ctrl-C.
--rm: removes the container after it is stopped-p 8080:80: sets up a port mapping between8080local and80container
Downloading the demo code
In the terminal, run git clone https://github.com/ryojp/nginx-intro to clone the repo.
Use Cases
NGINX as a Static Hosting solution
Let's not dive deep into static hosting. Here, I'll just provide some basics.
Demo
- Navigate into 
static_hostingdirectory of the cloned repo and rundocker compose up --build - Visit http://localhost:8080
 
Config
server {
    listen       80;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    error_page  404              /404.html;
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
Details
Explanation
This is a basic NGINX configuration that sets up a web server listening on port80 and serving content from the /usr/share/nginx/html directory.The listen directive specifies the IP address and port number that NGINX will listen on. In this case, it is listening on port 80 for HTTP traffic.
The server_name directive specifies the hostname of the server. In this case, it is set to localhost.
The location directive is used to define how NGINX should handle requests that match a specific URL pattern. In this case, any request that matches the root / URL will be served files from the /usr/share/nginx/html directory with index.html or index.htm being the default file served.
The error_page directive specifies which HTML file to serve in the event of a specific error. In this case, it is set to serve /404.html for a 404 Not Found error, and /50x.html for any 500, 502, 503, or 504 error. The second location block specifies the location of the /50x.html file.
Overall, this configuration sets up a simple web server that serves static files from a specified directory and handles common HTTP errors.
NGINX as a Reverse Proxy
It is also very simple and easy to configure NGINX as a reverse proxy.
Please see the following config file.
server {
    listen       80;
    #listen  [::]:80;
    server_name  localhost;
    #access_log  /var/log/nginx/host.access.log  main;
    location /hello {
        proxy_pass http://hello:8000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
By using proxy_pass directive, the above config instructs NGINX to pass the requests at /hello endpoint to port 8000 of the hello host.
By default, Host header changes with this reverse-proxying, so it is a common practice to explicitly overwrite the Host field with the original (client host) using proxy_set_header directive.
Lastly, X-Forwarded-For header is set to contain all the proxied hosts.
Demo
- Navigate into 
reverse_proxydirectory of the cloned repo and rundocker compose up --build - Run 
curl http://localhost:8080/helloorcurl http://localhost:8080/byeto recieve requests from the proxied backends 
NGINX as a Load Balancer
By defining upstream NGINX can act as a load balancer.
Algorithms
NGINX supports major algorithms such as  round-robin, least connections, least time, IP Hash, etc.
Most of the above can have configurable weights, useful when the upstream servers have varying machine specs.
With NGINX Plus, it is possible to identify user sessions and pin traffic to the appropriate upstream regardless of the load-balancing algorithms.
Timeout
NGINX provides various timeouts, both between client and NGINX, and between NGINX and upstream servers.
For example, proxy_connect_timeout is the timeout for establishing a connection with the upstream server.
proxy_send_timeout is the timeout over which sending request to an upstream server.
Those timeouts should be set appropriately in production environment to reduce overheads.
Example
upstream greetings {
    least_conn;
    server hello:8000 weight=2;
    server bye:8000 weight=1;
}
server {
    listen       80;
    server_name  localhost;
    location / {
        proxy_pass http://greetings/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
The above NGINX config declares greetings upstream servers comprising hello:8000 and bye:8000 with varying weights.
This upstream uses the weighted least-connection algorithm to balance requests.
The defined greetings upstream is used as the target proxy for requests to / by using proxy_pass directive.
Summary
In this post, we saw basic usage of NGINX, including static hosting, reverse proxy, and load balancer.
I will write another blog on how to configure HTTP cache in NGINX later.
