NGINX, pronounced as 'engine-x', is an open-source web server that is mainly used for Reverse proxy, Caching, and Load balancing.
If you're into web dev, at some point in your career you might have to work with NGINX. This article will help you get started with NGINX. By the end, you'll be able to setup your own NGINX web server. You'll also understand terms like load balancing and reverse proxy.
Why NGINX?
NGINX is widely used for serving web content. It is known for its high performance, stability, and efficiency, making it a popular choice for various web applications and websites.
Some key features of NGINX are:
- Web Server 🤖: It can serve static content(such as HTML, CSS and images) directly to clients, making it efficient for delivering web pages.
- Reverse Proxy ⏩: It can act a reverse proxy by forwarding client's requests to other servers. It is a commonly used practice for security and scalability.
- Load Balancer ⚖️: It can route incoming traffic to different server instances ensuring optimal resource utilization.
- SSL/TLS Termination 🔐: It can handle SSL/TLS termination, encrypting and decrypting data between clients and servers.
- Performance Optimization ⚡️: It is designed to be lightweight and efficient, capable of handling a large number of concurrent connections with low resource usage.
Installation
Ubuntu/Debian
sudo apt update
sudo apt install nginx
After installation, NGINX will automatically start in the background. To check the status, run:
sudo systemctl status nginx
MacOS
We can install it using brew
brew install nginx
After installation, you can run it using:
brew services start nginx
Windows
- Download the latest stable version of NGINX from the official website: NGINX Download.
- Extract the downloaded zip file to a location of your choice.
- Navigate to the NGINX directory and run
nginx.exe
. NGINX should start.
Configuration
To find the configuration file, run:
nginx -t
nginx: the configuration file /opt/homebrew/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /opt/homebrew/etc/nginx/nginx.conf test is successful
This command tests the configuration file for syntax errors and typos, without applying it. It will also reveal the path to the main configuration file.
You can either edit this file directly or create a new one to follow along.
Serving HTML
If you check the nginx.conf
file, you'll see a lot of blocks wrapped in {}
and a lot of key-value pairs inside these blocks.
These blocks are known as contexts and the key-value pairs are known as directives for that context.
We'll clear the file and start from scratch. Your nginx.conf
should look like this:
events {}
http {
server {
listen 8080;
root /Users/syfe/Desktop/tutorials/nginx-test/html;
}
}
You only need events
and http
contexts to successfully load a configuration. Inside http
, we have the server
context that has the configuration for our web server.
It tells the server to listen
on port 8080
and set root
for serving files as /Users/syfe/Desktop/tutorials/nginx-test/html
.
Inside the html
directory, we'll create an index.html
file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Hello, world!</h1>
</body>
</html>
This is how directory structure looks currently.
If you created a new conf file, you can load it by running:
nginx -c path_to_your_file
And after making changes to any conf file, you can apply it using:
nginx -s reload
If you go on http://localhost:8080
, you'll see the html being served. 🎉
Serving other static content
If you try to add styles to your HTML content using a CSS file and serve it using the current configuration it will not work.
To make this work, you have to set the correct mime types in the configuration.
...
http {
types {
text/css css;
text/html html;
}
server {
...
}
}
...
But manually adding these mime types for all different kinds of assets is cumbersome. Therefore, NGINX comes with a default mime.types
file that can be used here.
After adding the default mime types file, our configuration looks like this:
events {}
http {
# include mime.types; (if you did not create a custom file)
include /opt/homebrew/etc/nginx/mime.types;
server {
listen 8080;
root /Users/syfe/Desktop/tutorials/nginx-test/html;
}
}
After reloading the conf, our HTML and CSS should be working as expected but now we have support for a lot of types.
The location
block
Let's assume you've the following directory structure:
Going to /animals
, will serve the index.html
file inside the animals
directory. What if you want to have another endpoint /forest
that serves the same file?
We can use the location
block to specify the full path and then using alias
we can set the directory that will serve the files.
events {}
http {
include /opt/homebrew/etc/nginx/mime.types;
server {
listen 8080;
root /Users/syfe/Desktop/tutorials/nginx-test/html;
location /forest {
alias /Users/syfe/Desktop/tutorials/nginx-test/html/animals;
}
}
}
With the above configuration, requests to /forest
will be served from animals
directory.
What if someone deletes the animals
directory or the file we're trying to serve is not available? We can provide fallback files using try_files
directive.
Let's create a fallback file.
Now, let's update the configuration.
events {}
http {
include /opt/homebrew/etc/nginx/mime.types;
server {
listen 8080;
root /Users/syfe/Desktop/tutorials/nginx-test/html;
location /animals {
root /Users/syfe/Desktop/tutorials/nginx-test/html;
try_files /animals/fallback.html /index.html =404;
}
}
}
Now, when a user visits /animals
:
- First the server will look for
/animals/index.html
. - If it doesn't exist, it'll look for
/animals/fallback.html
. - If our fallback file is missing it'll try to serve the
index.html
at root. - If it cannot find any file listed by us, it'll throw a 404 error.
Redirects
It is quite easy to set up redirections using NGINX. Let's update the configuration to redirect all incoming traffic from /birds
to /animals
.
events {}
http {
include /opt/homebrew/etc/nginx/mime.types;
server {
listen 8080;
root /Users/syfe/Desktop/tutorials/nginx-test/html;
location /animals {
root /Users/syfe/Desktop/tutorials/nginx-test/html;
}
location /birds {
return 307 /animals;
}
}
}
Returning with 307
does the trick.
Reverse Proxy
To forward requests to another server we can use the proxy_pass
directive.
events {}
http {
include /opt/homebrew/etc/nginx/mime.types;
server {
listen 8080;
location / {
proxy_pass http://192.168.10.5:8080;
}
}
}
Now, all the requests to localhost:8080
will be forwarded to http://192.168.10.5:8080
. This is helpful when you don't want to reveal the actual server or want to relay requests to different servers based on different paths.
Load Balancing
Sometimes, in high traffic situations, we might spin up multiple instances to handle the load. NGINX can act as a load balancer and evenly distribute requests among all the instances.
This ensures a seamless experience for our users without any downtime.
Let's update the configuration to achieve this:
events {}
http {
include /opt/homebrew/etc/nginx/mime.types;
upstream instances {
server 192.168.10.2:8080;
server 192.168.10.3:8080;
server 192.168.10.4:8080;
}
server {
listen 8080;
location / {
proxy_pass http://instances;
}
}
}
The upstream
block is used to specify a group of servers that can be referenced by proxy_pass
. NGINX will automatically take care of distributing the requests evenly.
Logging
With all that you've learnt so far, you'll be able to do a lot of cool things. One final(and important) thing that will help you in your journey is - Logging.
Let's update the configuration to add access logs on our server:
events {}
http {
include /opt/homebrew/etc/nginx/mime.types;
log_format main '$remote_addr - $remote_user [$time_local] "$request" ';
access_log /Users/syfe/Desktop/tutorials/nginx-test/access.log main;
server {
listen 8080;
root /Users/syfe/Desktop/tutorials/nginx-test/html;
}
}
We provide the format using log_format
directive. The access_log
directive takes the path to store the logs and the format we specified earlier.
That's it for this post! I hope this will get you started or at least now you understand what NGINX is. The official documentation for NGINX is well written if you wish to explore further.
🤝 I'd love to connect on LinkedIn or X.
Syfe is hiring devs. 👨💻🌏
Top comments (4)
Nice post!
Very informative post 👍
Thanks for the awesome write up!
This was very informative! 👍