πŸ”₯ DevOps with Nginx – Phase 1: Getting Started with Nginx as a Web Server



This content originally appeared on DEV Community and was authored by Krisha Arya

Hey Devs!
Welcome to Part 1 of my DevOps + Nginx series, where I’m documenting everything I’m learning hands-on β€” just like how companies expect in real-world DevOps roles.

In this phase, I’ll cover:

🔹 What is Nginx? All about Nginx.
🔹Static Hosting, Reverse Proxy, and FastCGI in Simple Words. ( Code Understanding)
🔹 How to install Nginx on Ubuntu
🔹 Understanding directory structure
🔹 Hosting a static website
🔹 Configure Basic Access Logs and Error Logs in Nginx
🔹Enable Custom 404 Pages

What is Nginx?
Nginx is a high-performance web server that can also function as a reverse proxy, load balancer, and HTTP cache.It serves static files like HTML, CSS, JS, and images directly to the browser as web server.

It’s widely used to forward client requests to backend services (like Node.js or Django apps) using reverse proxying, so the client doesn’t communicate directly with the backend server.

We can host static websites or forward requests to other servers by configuring Nginx in its nginx.conf file or site configuration files under /etc/nginx/sites-available.

What is a Proxy?
A proxy is a server that acts as an intermediary between a client (like a browser) and another server (like a backend or internet server).

_Forward Proxy _
A forward proxy sits in front of the client and hides the client’s identity by forwarding its requests to the internet.

“Client β†’ Forward Proxy β†’ Internet”

Use Cases:
Hiding the client’s IP
Accessing blocked websites
Monitoring and filtering outgoing traffic
Corporate network restrictions

Reverse Proxy
A reverse proxy sits in front of the server, intercepting client requests and forwarding them to one or more backend servers.

“Client β†’ Reverse Proxy β†’ Backend Server(s)”

Use Cases:
Load balancing across multiple backend servers
SSL termination (managing HTTPS)
Caching and performance optimization
Security (hide internal server details)
Rate limiting or request throttling

Real-Life Analogy
Forward Proxy is like you sending a letter via a friend so the recipient doesn’t know it’s from you.

Reverse Proxy is like a receptionist at an office who receives your request and forwards it to the correct department inside (department is hidden from you).

How Nginx Handles Requests
Nginx is event-based and non-blocking, which means it can handle many simultaneous requests very efficiently, even with low memory and CPU usage.Unlike traditional servers, Nginx doesn’t create a new thread or process for every request.Instead, it uses an event loop to efficiently serve thousands of requests per worker.

If we take other server like Apache,it creates thread or process for every request which takes lots of memory and becomes slow.
Nginx handles several requests without creating that number of threads, because it uses a master process to control smart, multitasking worker processes.These workers handle requests using an efficient event loop, not blocking or waiting (When a worker is reading a file, sending data, or waiting on I/O, it doesn’t get stuck.It simply moves on to handle another ready request.This is called non-blocking I/O) which is why Nginx is faster and more memory-efficient than Apache, especially under high traffic.

Nginx Configuration Basics
Nginx config file = set of directives (instructions)
Simple directive: Ends with a ;
Example: listen 80;
Block directive: Wrapped in {} and can contain more directives
Example:

http {
    server {
        location / {
            root /data;
        }
    }
}

Context Hierarchy:
main β†’ http β†’ server β†’ location
Comments start with #.

Serving Static Files Using Nginx
Serve files (like HTML or images) directly from disk.

  • Create folders.
sudo mkdir -p /data/www
sudo mkdir -p /data/images

Put your files in /data/www/index.html and /data/images/sample.png

server {
    location / {
        root /data/www;
    }

    location /images/ {
        root /data;
    }
}

Example:
http://localhost/index.html β†’ serves /data/www/index.html

http://localhost/images/sample.png β†’ serves /data/images/sample.png

Note: Way of forming final path url and map.
Final File Path = root_path + URL_path_after_location
Example:

  1. Request: http://localhost/index.html
    It matches: location /
    Root is: /data/www
    Remaining path after / is: index.html
    Final path = /data/www/index.html

  2. Request: http://localhost/images/pic1.png
    It matches: location /images/
    Root is: /data
    Remaining path after /images/ is: pic1.png
    Final path = /data/images/pic1.png

Setting Up Nginx as a Reverse Proxy
You have a Node.js app on port 8080, but want users to access it via default port 80.

server {
    location / {
        proxy_pass http://localhost:8080;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

Note: proxy_pass is an Nginx directive used to forward (proxy) incoming client requests to another server or application (called an upstream server).It’s a core part of setting up a Reverse Proxy using Nginx.When user visits main website, nginx forward to path mentioned in proxy_pass without informing the user.We do this when we don’t want Nginx to serve content directly from files like index.html but pass request to backend app like node.js,python flask etc. Also for maintaining traffic.

FastCGI Proxying (e.g., for PHP)
FastCGI lets Nginx talk to languages like PHP using the FastCGI protocol.

server {
    location / {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param QUERY_STRING    $query_string;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

Now, let’s do practical now.
First, we need to set up nginx.
Ran a container:

docker run -it -p 8000:80 ubuntu

Checked /etc directory:

cd /etc
ls

No /etc/nginx directory was present. Why?

Explanation:
The default Ubuntu image doesn’t come with Nginx pre-installed. So I manually installed it inside the container:

apt update
apt install nginx -y

To check if it’s running:

sudo systemct1 status nginx

We can also check version of nginx.

nginx -v

Now let’s deep dive into creating and serving own static files on nginx server.So, we configure this in nginx.conf.

touch /etc/nginx/nginx.conf
nano /etc/nginx/nginx.conf

Here you will see predefined configuration. So, before doing your own configuration, move it to another backup file otherwise you will end up with messing up.
Get back to /etc/nginx.

mv nginx.conf nginx_backup.conf
touch nginx.conf
cd nginx.conf

Now, in this nginx.conf, you will see nothing and now we can write our own configuration.
I am showing my own sample code, here I have defined types and servers only inside http. types helps nginx to know that file is of which type and then if you check via inspecting or from postman, nginx shows type of that file.In server section, we define port of nginx, server name (_ means no server name),location of website which we going to run on this nginx server.

Then reloaded, we do this whenever we do some changes in config file, we need to reload nginx server:

nginx -s reload

Note: -s is used for invoking executable files . Common syntax is
“nginx -s signal”.And signal can be:

  • stop β€” Forceful shutdown.Immediately kills the Nginx master and worker processes.
  • quit β€” Tells Nginx to finish processing current requests, then shut down.It stops accepting new connections but waits for in-progress ones to finish.
  • reload β€” reloading the configuration file without stopping the server.
  • reopen β€” You’re rotating logs (logrotate), and want Nginx to start writing into the new log files without restarting.Like changing notebooks without stopping the work.

Before above command, you should also run below command to start nginx manually first if its first time running nginx or after stopping it.

nginx

Note: As by default nginx run on port 80. You can see on And port 80 shows by default browser.Now we can also run it by giving specific port such as port 8000,8080 and so on.

Configure Basic Access Logs and Error Logs in Nginx

  1. Access Logs – This records every request made to your Nginx server.

It helps you answer:
Who is visiting your site?
What pages are they visiting?
What browser/IP/location are they using?
How fast was the response?
Did it return 200 (success), 404 (not found), 500 (server error)?

  1. Error Logs – This records problems or warnings that occur on the server.

It logs:
Missing files (404 errors)
Misconfigured directives
Permission issues
Backend failures (like failed upstreams)

http {
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log warn;

    server {
        listen 80;
        location / {
            root /data/www;
            index index.html;
        }
    }
}

Note: Access logs and Error logs files are inbuilt and automatically save logs.By default, inside http , path are mentioned of these two but if not then create and mention(but it happens very rarly).

Enable Custom 404 Pages

What is a 404 Page?
When a requested file doesn’t exist, you can show a custom HTML page instead of default error.

  • Create 404 file:
echo "<h1>Oops! Page not found (404)</h1>" | sudo tee /data/www/custom_404.html
  • Update config with error_page:
server {
    listen 80;
    server_name localhost;

    location / {
        root /data/www;
        index index.html;
    }

    error_page 404 /custom_404.html;

    location = /custom_404.html {
        root /data/www;
        internal;
    }

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
}

Note: If a 404 occurs β†’ redirect to /custom_404.html.The internal; means it won’t be directly accessible β€” only via errors.

  • Reload Nginx:
nginx -s reload
  • Go to a missing URL: You would see custom error page.

So, that’s it for today! In next part, we will more deep dive into it. Bye!


This content originally appeared on DEV Community and was authored by Krisha Arya