DevOpsClicks
← Home
🌐 Complete Web Server Reference

Nginx Complete Guide

Web server, reverse proxy, and load balancer — from serving static files to production-grade HTTPS configurations and Kubernetes ingress.

10
Chapters
40+
Configs
100%
Free
01🌐

What is Nginx?

The World's Most Popular Web Server

Think of Nginx (pronounced "engine-X") as a traffic cop for the internet. When someone visits your website, Nginx is the first thing that handles their request. It can serve web pages directly, forward requests to your application servers, or split traffic across multiple servers. It powers over 34% of all websites including Netflix, Airbnb, and WordPress.com.
What Can Nginx Do?
📄
Web Server
Serve HTML, CSS, JS, and images directly to browsers. Super fast because it handles thousands of connections at once.
🔀
Reverse Proxy
Sit in front of your app (Node.js, Java, Python) and forward requests to it. Hides your app server from the internet.
⚖️
Load Balancer
Split traffic across multiple app servers. If one server dies, Nginx sends traffic to the healthy ones.
🔒
SSL Termination
Handle HTTPS encryption so your app server doesn't have to. Nginx decrypts the request and forwards plain HTTP internally.
Nginx vs Apache
FeatureNginxApache
ArchitectureEvent-driven (handles thousands of connections with few threads)Process/thread per connection (uses more memory)
Static FilesExtremely fastFast but slower than Nginx
Config StyleCentralized nginx.confDistributed .htaccess files
Best ForReverse proxy, load balancing, microservicesPHP apps, shared hosting, .htaccess needs
Market Share~34% of web~30% of web
💡 Simple Analogy

Apache is like a restaurant where each waiter serves one table at a time. Nginx is like a single super-efficient waiter who takes orders from ALL tables and delivers food as it's ready. That's why Nginx handles more traffic with less resources.

02📥

Installation & Commands

Setup and Daily Operations

Installing Nginx takes one command. After that, you need to know just 5 commands to manage it every day.
Installation
$ sudo apt update && sudo apt install nginxUbuntu/Debian
$ sudo yum install nginxCentOS/RHEL
$ brew install nginxmacOS
$ docker run -d -p 80:80 nginx:alpineDocker (quickest way to try)
5 Commands You'll Use Daily
$ sudo systemctl start nginxStart Nginx
$ sudo systemctl stop nginxStop Nginx
$ sudo systemctl reload nginxReload config WITHOUT dropping connections (use this, not restart)
$ sudo nginx -tTest config for errors BEFORE reloading (always do this first!)
$ sudo systemctl status nginxCheck if Nginx is running and healthy
💡 Always Test First

Before reloading Nginx in production, ALWAYS run nginx -t first. If your config has a typo, reload will fail and Nginx might go down. Test → then reload. Every single time.

03📝

Configuration Basics

Understanding nginx.conf

Nginx configuration lives in /etc/nginx/nginx.conf and the /etc/nginx/sites-available/ directory. The config uses a block structure — think of it like nested boxes. Each box controls a different aspect.
Config File Structure
NGINX.CONF# /etc/nginx/nginx.conf — Main config # GLOBAL: Affects entire Nginx worker_processes auto; # Number of worker threads (auto = match CPU cores) events { worker_connections 1024; # Max connections per worker } http { # HTTP-LEVEL: Affects all websites include /etc/nginx/mime.types; sendfile on; keepalive_timeout 65; # Include site configs include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
Server Block = One Website
SITE CONFIG# /etc/nginx/sites-available/mysite.conf server { listen 80; # Listen on port 80 server_name mysite.com www.mysite.com; # Domain names root /var/www/mysite; # Where your files live index index.html; # Default page location / { try_files $uri $uri/ =404; # Try file, then folder, then 404 } location /images/ { expires 30d; # Cache images for 30 days } }
Key Concepts
📦
server { }
One server block = one website or application. You can have multiple server blocks for different domains.
📍
location { }
Matches URL paths. location /api/ { } handles all URLs starting with /api/. Like a router for your site.
🔄
upstream { }
Defines a group of backend servers for load balancing. Nginx distributes requests across them.
📁
root vs alias
root appends the URL path to the directory. alias replaces it. Most common mistake in Nginx config.
04📄

Serving Static Content

HTML, React, Angular & File Downloads

Nginx is incredibly fast at serving static files — HTML pages, CSS, JavaScript bundles, images, and downloads. This is the simplest and most common use case.
Serve a React/Angular Build
NGINXserver { listen 80; server_name app.mycompany.com; root /var/www/frontend/build; # React build output index index.html; # Handle React Router (SPA) — all routes serve index.html location / { try_files $uri $uri/ /index.html; } # Cache static assets aggressively location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } # Gzip compression — reduces file sizes by 70% gzip on; gzip_types text/css application/javascript application/json image/svg+xml; gzip_min_length 1000; }
💡 try_files for SPA

React, Angular, and Vue use client-side routing. Without try_files $uri $uri/ /index.html, refreshing the page on /dashboard gives a 404 because there's no physical file at that path. This directive catches all routes and serves index.html, letting React handle routing.

05🔀

Reverse Proxy

Forward Traffic to Your App

A reverse proxy sits between the internet and your application. Users talk to Nginx (port 80/443), and Nginx forwards requests to your app (port 3000, 8080, etc.). This hides your app, adds SSL, enables caching, and improves security.
Proxy to Node.js / Spring Boot
NGINXserver { listen 80; server_name api.mycompany.com; location / { proxy_pass http://localhost:3000; # Your Node.js app proxy_http_version 1.1; # Pass real client info to your app proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # WebSocket support proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }
Multiple Apps on One Server
NGINXserver { listen 80; server_name mycompany.com; # Frontend React app location / { proxy_pass http://localhost:3000; } # Backend API location /api/ { proxy_pass http://localhost:8080/; } # Grafana dashboard location /grafana/ { proxy_pass http://localhost:3001/; } }
💡 Trailing Slash Matters

proxy_pass http://localhost:8080/ (with slash) strips the matched location prefix. proxy_pass http://localhost:8080 (without) passes the full URL. This is the most common Nginx debugging issue.

06⚖️

Load Balancing

Split Traffic Across Servers

When one server can't handle all the traffic, you run multiple copies and let Nginx split the load. If one server crashes, Nginx automatically stops sending traffic to it.
Basic Load Balancing
NGINX# Define backend server group upstream api_servers { server 10.0.1.10:8080; # Server 1 server 10.0.1.11:8080; # Server 2 server 10.0.1.12:8080; # Server 3 } server { listen 80; server_name api.mycompany.com; location / { proxy_pass http://api_servers; # Nginx picks a server } }
Load Balancing Methods
MethodHow It WorksBest For
Round Robin (default)Sends requests to servers in order: 1, 2, 3, 1, 2, 3...Equal servers
Least ConnectionsSends to the server with fewest active connectionsVarying request times
IP HashSame client IP always goes to same serverSession stickiness
WeightedStronger servers get more traffic (weight=3 gets 3x)Mixed server sizes
NGINXupstream api_servers { least_conn; # Use least connections server 10.0.1.10:8080 weight=3; # This server gets 3x traffic server 10.0.1.11:8080 weight=1; server 10.0.1.12:8080 backup; # Only used if others are down }
07🔒

SSL/TLS & HTTPS

Encrypt Everything

HTTPS encrypts traffic between the browser and your server. Without it, passwords and data are sent in plain text. Let's Encrypt provides free SSL certificates that auto-renew.
Free SSL with Let's Encrypt
$ sudo apt install certbot python3-certbot-nginxInstall Certbot
$ sudo certbot --nginx -d mysite.com -d www.mysite.comGet certificate and auto-configure Nginx
$ sudo certbot renew --dry-runTest auto-renewal
HTTPS Configuration (What Certbot Generates)
NGINXserver { listen 443 ssl http2; server_name mysite.com; ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem; # Strong SSL settings ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; # HSTS — tell browsers to always use HTTPS add_header Strict-Transport-Security "max-age=31536000" always; location / { proxy_pass http://localhost:3000; } } # Redirect HTTP to HTTPS server { listen 80; server_name mysite.com; return 301 https://$host$request_uri; }
⚠️ Never Expose HTTP in Production

Always redirect port 80 (HTTP) to port 443 (HTTPS). Browsers show \"Not Secure\" warnings for HTTP sites, and Google ranks HTTPS sites higher.

08🛡️

Security Hardening

Headers, Rate Limiting & Protection

Nginx is your first line of defense. Add security headers, rate limiting, and access controls to protect your application from attacks.
Security Headers
NGINXserver { # Prevent clickjacking add_header X-Frame-Options "SAMEORIGIN" always; # Prevent MIME sniffing add_header X-Content-Type-Options "nosniff" always; # XSS protection add_header X-XSS-Protection "1; mode=block" always; # Control referrer info add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Hide Nginx version server_tokens off; }
Rate Limiting — Stop Brute Force Attacks
NGINX# Define rate limit zone: 10 requests per second per IP http { limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; } server { location /api/login { limit_req zone=api_limit burst=20 nodelay; proxy_pass http://localhost:8080; } }
💡 Simple Explanation

Rate limiting is like a bouncer at a club. You allow 10 people per second (rate=10r/s). If 30 people arrive at once, 20 can enter immediately (burst=20) and the rest wait or get rejected.

09🐳

Nginx in Docker & Kubernetes

Containerized Deployments

In modern DevOps, Nginx runs inside Docker containers or as a Kubernetes Ingress Controller — the entry point for all traffic into your cluster.
Nginx Docker Container
DOCKERFILE# Dockerfile for React app served by Nginx FROM node:20-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM nginx:alpine COPY --from=build /app/build /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80
Kubernetes Ingress Controller
K8S YAML# Nginx Ingress routes external traffic to K8s services apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx tls: - hosts: [app.company.com] secretName: app-tls rules: - host: app.company.com http: paths: - path: / pathType: Prefix backend: service: name: frontend-svc port: {number: 80} - path: /api pathType: Prefix backend: service: name: backend-svc port: {number: 8080}
10💼

Interview Questions

Nginx Q&A for DevOps Interviews

What is a reverse proxy?
It sits between clients and backend servers. Clients talk to Nginx, Nginx forwards to your app. Benefits: SSL termination, load balancing, caching, security. Your app server is never directly exposed.
Nginx vs Apache?
Nginx: event-driven, handles more concurrent connections with less memory, better for reverse proxy/load balancing. Apache: process-per-connection, supports .htaccess, better for shared hosting.
What is upstream?
A block that defines a group of backend servers. Nginx distributes requests across them. Used for load balancing with methods like round-robin, least_conn, or ip_hash.
How does SSL termination work?
Nginx handles HTTPS encryption/decryption. Internal traffic between Nginx and your app uses plain HTTP. This offloads CPU-intensive crypto from your app server.
What does proxy_pass do?
Forwards the client request to a backend server. proxy_pass http://localhost:3000 sends all matched requests to your Node.js app on port 3000.
try_files explained?
try_files $uri $uri/ /index.html means: try the exact file → try as directory → fall back to index.html. Essential for single-page apps (React/Angular).
What is Nginx Ingress?
A Kubernetes component that uses Nginx to route external HTTP/HTTPS traffic to the correct services inside the cluster. It replaces individual LoadBalancer services.
How to do zero-downtime reload?
sudo nginx -t (test config) → sudo systemctl reload nginx. Reload gracefully finishes existing connections before applying new config. Never use restart in production.