Getting Started with Nginx on Linux
๐ Section 1: Introduction to NGINX
โ What is NGINX?
NGINX is an open-source, high-performance web server that also functions as:
- A reverse proxy
- Load balancer
- HTTP cache
- Mail proxy
It is designed for high concurrency, performance, and low memory usage โ making it ideal for modern DevOps and cloud environments.
Reverse Proxy
๐ NGINX vs Apache (Why DevOps Prefer NGINX)
| Feature | NGINX | Apache |
|---|---|---|
| Architecture | Event-driven (asynchronous) | Process/thread-based |
| Performance | High concurrency, fast | Slower with many connections |
| Memory usage | Low | High |
| Static content | Extremely fast | Good |
| Config format | Simple, declarative | More flexible but complex |
| Use cases | Web server, reverse proxy, LB | Traditional web server |
๐ก DevOps Engineers often choose NGINX for its:
- Lightweight footprint
- Ease of automation
- Docker/Kubernetes friendliness
๐งฐ Common DevOps Use Cases for NGINX
| Use Case | Example |
|---|---|
| Web server | Serving static React/Angular apps |
| Reverse proxy | Forwarding requests to backend apps (Node.js, Python, Java) |
| Load balancer | Distributing load between multiple backend servers |
| SSL termination | Handling HTTPS at the edge |
| Caching | Reducing load on upstream services |
| Ingress controller (Kubernetes) | Managing traffic inside Kubernetes clusters |
| Rate limiting & security enforcement | Protecting APIs from abuse or bots |
๐ ๏ธ Installing NGINX
๐ง On Ubuntu/Debian
sudo apt update
sudo apt install nginx -y
๐ฆ On RHEL/CentOS
sudo yum install epel-release -y
sudo yum install nginx -y
๐ณ Using Docker (Recommended for DevOps)
docker run --name nginx -p 8080:80 -d nginx
Visit: http://localhost:8080
๐ NGINX File Structure (Linux)
| File/Directory | Purpose |
|---|---|
/etc/nginx/nginx.conf | Main configuration file |
/etc/nginx/sites-available/ | Stores virtual host (server block) configs |
/etc/nginx/sites-enabled/ | Symlinks to active site configs |
/var/www/html | Default web root directory |
/var/log/nginx/ | Contains access and error logs |
๐งช Demo: Run NGINX Using Docker
Step 1: Run container
docker run --name nginx-demo -p 8080:80 -d nginx
Step 2: Test in browser
Visit: http://localhost:8080
You should see the Welcome to NGINX page.
Step 3: View Logs
docker logs nginx-demo
Step 4: Clean up
docker stop nginx-demo
docker rm nginx-demo
๐ Section 2: NGINX as a Web Server
๐ Goal
Learn how to use NGINX to serve static content such as HTML, CSS, JavaScript, and images โ a foundational skill for DevOps & Cloud Engineers.
๐ง What is a Web Server?
A web server is software that serves static files (like .html, .css, .js, .png) over HTTP.
When users visit your website, the web server responds with these files.
NGINX is one of the fastest and most popular web servers used for this purpose.
๐ Default Web Root in Linux
| Directory | Purpose |
|---|---|
/var/www/html | Default directory for static files |
/etc/nginx/sites-available/default | Default config file pointing to the web root |
๐ Anatomy of a Basic server Block
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Breakdown:
listen 80;โ Listens on HTTP port 80server_name localhost;โ Domain or IP to respond torootโ Path where NGINX looks for filesindexโ Default file to serve (usually index.html)location /โ URL path handling
๐งช Demo: Serve a Static Website Using NGINX
๐ง Option 1: Using Native Linux NGINX
- Create an HTML file:
echo "<h1>Hello from NGINX Web Server</h1>" | sudo tee /var/www/html/index.html
- Reload NGINX:
sudo systemctl reload nginx
- Test:
Visit:
http://localhostor your serverโs IP in browser.
๐ณ Option 2: Serve HTML from Docker
- Create a project folder:
mkdir nginx-static && cd nginx-static
- Add
index.html:
<!-- index.html -->
<h1>Hello from NGINX in Docker!</h1>
- Run NGINX Docker container:
docker run --name web-nginx -v $PWD:/usr/share/nginx/html:ro -p 8080:80 -d nginx
- Open in browser:
http://localhost:8080
๐ Root vs Alias
These two directives behave differently inside location blocks.
root example:
location /static/ {
root /data/www;
}
# /static/img.png โ /data/www/static/img.png
alias example:
location /static/ {
alias /data/www/;
}
# /static/img.png โ /data/www/img.png
๐ Use alias when you want to replace the URI path.
๐งฏ Common Errors & Fixes
| Error | Solution |
|---|---|
| 403 Forbidden | Check file permissions (use chmod/chown) |
| 404 Not Found | Ensure correct root or alias |
| NGINX not reloading changes | Use sudo nginx -s reload or restart NGINX |
| Port already in use | Use sudo lsof -i :80 to identify process |
๐ Section 3: NGINX as a Reverse Proxy (Ubuntu/Linux)
๐ง What is a Reverse Proxy?
A reverse proxy is a server that receives client requests and forwards them to backend servers, then sends the response back to the client.
NGINX is one of the most popular tools used as a reverse proxy in production.
๐ Reverse Proxy vs Forward Proxy
| Feature | Forward Proxy | Reverse Proxy |
|---|---|---|
| Who configures it | Client | Server-side |
| Forwards requests to | External servers (internet) | Internal backend servers (apps/services) |
| Use case | Browsing anonymously, caching | Load balancing, SSL termination, API gateway |
| Example | Proxy server for office users | NGINX between frontend and backend apps |
๐ Why Use NGINX as a Reverse Proxy?
- Protect backend services from direct access
- Centralized SSL termination
- Load balancing backend apps
- Path-based routing (
/apiโ backend1,/appโ backend2) - Easy caching and compression
๐ Reverse Proxy Configuration (Ubuntu/Linux)
๐ง File: /etc/nginx/sites-available/default
Update the existing server block or create a new one:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Breakdown:
proxy_passโ forwards requests to your backend appproxy_set_headerโ preserves original request metadata (like IP and host)
๐งช Demo: Reverse Proxy to a Node.js App
Step 1: Install Node.js (optional if using your own backend)
sudo apt update
sudo apt install nodejs npm -y
Step 2: Create a simple backend app
mkdir ~/node-backend && cd ~/node-backend
nano server.js
Paste this:
const http = require('http');
http.createServer((req, res) => {
res.end('Hello from Node.js backend!');
}).listen(3000);
Run it:
node server.js
Your app is now running at
http://localhost:3000
Step 3: Configure NGINX as reverse proxy
Edit the NGINX default site:
sudo nano /etc/nginx/sites-available/default
Replace the location / {} block with:
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Step 4: Test and reload NGINX
Check config for syntax errors:
sudo nginx -t
Reload NGINX:
sudo systemctl reload nginx
Step 5: Test in browser
Visit:
http://localhost
โ
You should see: Hello from Node.js backend!
๐ File Structure Recap (Ubuntu)
| Path | Purpose |
|---|---|
/etc/nginx/nginx.conf | Global NGINX settings |
/etc/nginx/sites-available/default | Active site config for reverse proxy |
/var/www/html | Not used in reverse proxy |
/var/log/nginx/access.log | Logs all requests |
โ๏ธ Section 4: Load Balancing with NGINX (Ubuntu/Linux)
๐ฏ Goal
Use NGINX to distribute traffic across multiple backend servers โ improving availability, reliability, and scalability of your applications.
๐ง What is Load Balancing?
Load balancing is the process of distributing incoming network traffic across multiple backend servers.
Benefits:
- Prevents server overload
- Increases availability and fault tolerance
- Enables horizontal scaling
NGINX supports multiple load balancing algorithms out of the box.
๐งฎ Load Balancing Algorithms in NGINX
| Algorithm | Behavior |
|---|---|
round-robin | Default โ rotates through all backends equally |
least_conn | Sends traffic to the backend with the fewest active connections |
ip_hash | Uses client IP to consistently route requests to the same backend |
๐ Basic Load Balancer Configuration
Edit:
sudo nano /etc/nginx/sites-available/default
Replace contents with:
upstream backend_app {
server 127.0.0.1:3001;
server 127.0.0.1:3002;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://backend_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
๐งช Demo: Load Balance Two Local Backend Servers
Step 1: Create Backend Servers
Weโll run two simple HTTP servers using Node.js.
Create script:
mkdir ~/load-test && cd ~/load-test
server1.js
require('http').createServer((req, res) => {
res.end('Response from Server 1');
}).listen(3001);
server2.js
require('http').createServer((req, res) => {
res.end('Response from Server 2');
}).listen(3002);
Step 2: Run both servers
node server1.js &
node server2.js &
Step 3: Reload NGINX
sudo nginx -t
sudo systemctl reload nginx
Step 4: Test the Load Balancer
Open a browser or use curl:
curl http://localhost
Run it multiple times โ you should see the response alternate between:
Response from Server 1
Response from Server 2
โ Youโve just created a working load balancer using NGINX!
๐ Switching Load Balancing Methods
Use Least Connections
upstream backend_app {
least_conn;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
}
Use IP Hash
upstream backend_app {
ip_hash;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
}
๐ Section 5: SSL/TLS Setup in NGINX Using a Self-Signed Certificate (Ubuntu/Linux)
๐ฏ Goal
Secure your application with HTTPS using a self-signed SSL certificate.
This is ideal for local development, internal tools, and non-public test environments.
๐ง Why Use HTTPS (Even in Dev)?
- Encrypts traffic between client and server
- Simulates production-like environment for testing
- Helps catch mixed-content issues early
- Required by modern frontend frameworks and APIs
๐ ๏ธ Step-by-Step: Create a Self-Signed Certificate
Step 1: Generate SSL Certificate and Key
sudo openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /etc/ssl/private/nginx-selfsigned.key \
-out /etc/ssl/certs/nginx-selfsigned.crt
When prompted:
- Common Name (CN): use
localhostor your serverโs IP
Step 2: Update NGINX Configuration
Edit the default site config:
sudo nano /etc/nginx/sites-available/default
Replace with the following:
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
# Optional: Redirect HTTP to HTTPS
server {
listen 80;
server_name localhost;
return 301 https://$host$request_uri;
}
Step 3: Reload NGINX
Check and reload configuration:
sudo nginx -t
sudo systemctl reload nginx
Step 4: Test HTTPS Locally
Open your browser and visit:
https://localhost
โ ๏ธ You will see a warning:
โYour connection is not privateโ
โ Thatโs expected with self-signed certs. Proceed anyway to view your site securely.
๐ SSL File Paths Recap
| Path | Purpose |
|---|---|
/etc/ssl/certs/nginx-selfsigned.crt | SSL certificate |
/etc/ssl/private/nginx-selfsigned.key | Private key |
/etc/nginx/sites-available/default | HTTPS proxy config |
๐งช Bonus: Test Without Browser (curl)
curl -k https://localhost
-kallows insecure (self-signed) HTTPS connections.
โ Summary
- Self-signed SSL is perfect for secure local development.
- Requires only OpenSSL and a few lines in NGINX.
- Always test your HTTPS setup with curl and browser.
- In production, switch to Letโs Encrypt or trusted CAs.
๐ฏ Summary
- NGINX is a lightweight, high-performance web server and reverse proxy.
- Widely used in DevOps for load balancing, SSL termination, and as a reverse proxy.
- Easy to install via Linux package managers or Docker.
- Supports modular configuration โ great for automation and CI/CD.
- NGINX can serve static files efficiently.
- The
rootandindexdirectives define where and what to serve. - Use Docker volumes to serve files without touching the host filesystem.
- Always reload NGINX after making config changes.
- NGINX can proxy traffic to backend apps using
proxy_pass. - Config changes go in
/etc/nginx/sites-available/default(on Ubuntu). - Always test config and reload NGINX after changes.
- Ideal for API gateways, internal routing, and SSL termination.
- Self-signed SSL is perfect for secure local development.
- Requires only OpenSSL and a few lines in NGINX.
- Always test your HTTPS setup with curl and browser.
- In production, switch to Letโs Encrypt or trusted CAs.