Introduction to NGINX

Fathinah Asma Izzati
6 min readDec 1, 2021

--

How NGINX as a load balancer looks like

When I was asked to create google auth functionality and it worked on my locals, I faced a problem during deployment. The google auth and automated email send don’t work on VM. I have to deal with Nginx to handle this problem. This article is created to teach myself about Nginx.

NGINX is open-source software for web serving, reverse proxying, caching, load balancing, media streaming, and more. It started out as a web server designed for maximum performance and stability. (Nginx docs)

Installation

Nginx is installed on our ubuntu VM, here are commands to initiate:

sudo apt-get update
sudo apt-get install nginx
sudo nginx -v

I experimented with Nginx on my mac, and start installing using homebrew:

brew install nginx
sudo nginx
sudo nginx -s quit
Turn on Nginx, check that it’s running, and turn off

I used sudo nginx -v to check that Nginx is installed. sudo nginx to start, ps -ax|grep nginx to check that Nginx is running, and sudo nginx -s quit to turn off Nginx.

Nginx will be auto served on localhost:8080 ( in my default config file )

Let’s learn by exploring how Nginx looks like in actions.

Basic Configuration

When installing nginx, a default nginx.conf will be created and it will look something like this:

user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 768;
# multi_accept on;
}
http {sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable “msie6”;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

Nginx config files is made up of context. Context is declared like this: context_name {}like http{}. It can be nested and every child context inherit parent’s config. To understand what the above script means, read this article link.

In the last two lines, there is include etc/nginx/sites-enabled/*. Sites-enabled folder coniststs of other config files that is symlinked from /sites-available. So most of code snippets starting in server you will see throughout the post are found in custom conf files located in sites-available. In order for the server to run, we need to symlink from sites-available to sites-enabled.

The server context defines a specific virtual server to handle your clients’ requests. You can have multiple server blocks, and NGINX will choose between them based on the listen and server_name directives.

Inside a server block, we define multiple location contexts that are used to decide how to handle the client requests. Whenever a request comes in, NGINX will try to match its URI to one of those location definitions and handle it accordingly. (Stefanos Vardalos)

Nginx to serve static content

(http://nginx.org/en/docs/beginners_guide.html)

Since I installed Nginx using brew, the default Nginx directory is located in /opt/homebrew/etc/nginx.

Quoting from nginx.org documentation, “By default, the configuration file is named nginx.conf and placed in the directory /usr/local/nginx/conf, /etc/nginx, or /usr/local/etc/nginx.” So it depends on your computer.

I created /opt/homebrew/data which consists of 2 folders: /www for storing html file and /images for storing images. Now, we’re going to replace the default ‘Welcome to nginx!’ page with my index.html.

After creating /opt/homebrew/data/www/index.html, I changed nginx.conf to point out to my new index.html.

Initially, it looked like this:

server {listen 8080;server_name localhost;
location / {
root /html;
index index.html index.htm;
}
}

Then, I changed to the following:

server {
location / {
root /opt/homebrew/data/www;
}
location /images/ {
root /opt/homebrew/data;
}
}

Difference:

  • I deleted listen 8080, so now Nginx will be served on localhost:80
  • The index.html page that is initially served from /opt/homebrew/var/www, now changed to /opt/homebrew/data/www/. Rendering my own index.html 😃
  • If I store image.png in /opt/homebrew/data/images/, I can access that image in localhost:80/images/image.png

Nginx as a Simple Proxy Server — How We Implemented NGINX in Our Project

http://nginx.org/en/docs/beginners_guide.html

One of the frequent uses of Nginx is setting it up as a proxy server, which means a server that receives requests, passes them to the proxied servers, retrieves responses from them, and sends them to the clients.

Proxy Server https://en.wikipedia.org/wiki/Proxy_server
Proxy Server: https://www.youtube.com/watch?v=sWpf9FuMrNo

We will configure a basic proxy server, which (1) serves requests of images with files from the local directory, and (2) sends all other requests to a proxied server. In this example, both servers will be defined on a single nginx instance.

a. Proxied Server

server {
listen 8080;
root /data/up1;
location / {
}
}

This will be a simple server that listens on the port 8080 and map all requests to /data/up1 which has an index.html file.

b. Proxy Server

server {
location / {
proxy_pass http://localhost:8080/;
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}

This proxy server config will serve image requests directly fromroot/data/images, but will pass all requests other than that to our proxied server.

In our project, here is how we set up nginx as a proxy server.

The backend django app will listen to port 80. This conf file will be placed inside our docker. server_name should be followed by domain that nginx will listen for. server_name _ is used as the default name for all domains to be processed by nginx. backend is the name of our backend service in docker. Thus, any request to / will be routed to backend in port 8000.

Another Example

The upstream context defines a pool of servers that NGINX will proxy the requests to, and NGINX can perform a load balancing job to make incoming traffic distributed equally across all servers available. We can refer to the server pool’s name inside location context later.

Example from https://faun.pub/basics-of-configuring-nginx-b38c78eb113

upstream sample.server.com {
server server1_ip:port;
server server2_ip:port;
}
server {
listen 80;
server_name some.server.com;

location / {
proxy_pass http://sample.server.com;
}
location /test {
alias /var/www/html/customapp/;
try_files $uri $uri/ =404;
}
}

Inside the server block, a location block is defined. This parameter sets depending on the request URI. A location will match the prefix/regex given.

proxy_passwill send the request to a specified proxied server. In the above sample, this directive is used to map the location with the upstream.

Important locations:

  • Add configs in -> /usr/local/etc/nginx/servers/
  • Default config -> /usr/local/etc/nginx/nginx.conf
  • Logs will be in -> /usr/local/var/log/nginx/
  • Default webroot is -> /usr/local/var/www/
  • Default listen address -> http://localhost:8080

Starting, Stopping, and Reloading NGINX

sudo service nginx startservice nginx reloadservice nginx status

Sources

--

--