title: "Nginx Complete Learning Roadmap"
These explain how Nginx works internally.
| Concept | Purpose |
|---|---|
| Nginx | High-performance web server, reverse proxy, load balancer |
| Master Process | Reads config, starts and manages workers |
| Worker Process | Handles client requests |
| Event-Driven Architecture | Efficiently handles many connections |
| Non-Blocking I/O | Doesn't wait for one request before serving another |
| Worker Connections | Maximum simultaneous connections per worker |
| Worker Processes | Number of worker processes (usually one per CPU core) |
| Keepalive | Reuses TCP connections to reduce overhead |
These define how nginx.conf is organized.
nginx.conf
│
├── main
│
├── events
│
└── http
│
├── upstream
│
└── server
│
└── location
| Block | Purpose |
|---|---|
| main | Global settings |
| events | Worker and connection settings |
| http | HTTP configuration |
| upstream | Backend server group |
| server | Virtual host (website/app) |
| location | URL routing |
These are configuration instructions.
| Directive | Example | Purpose |
|---|---|---|
| listen | listen 80; |
Port to listen on |
| server_name | server_name example.com; |
Domain name |
| root | /var/www/html |
Static file directory |
| alias | /data/images |
Maps URL to another directory |
| index | index index.html; |
Default page |
| proxy_pass | http://localhost:3000 |
Forward request to backend |
| return | return 301 ... |
Redirect |
| rewrite | Rewrite URLs | URL rewriting |
| try_files | SPA routing | Check files before fallback |
These determine where requests go.
| Term | Purpose |
|---|---|
| location | Matches URL paths |
| Prefix Match | /api |
| Exact Match | = |
| Regex Match | ~ |
| Named Location | @backend |
Example:
location /api {
proxy_pass http://localhost:3000;
}
location /images {
root /var/www/html;
}| Term | Purpose |
|---|---|
| Reverse Proxy | Client talks only to Nginx |
| proxy_pass | Send request to backend |
| Proxy Headers | Pass client information |
| WebSocket Proxy | Support real-time connections |
Example:
location /api {
proxy_pass http://localhost:5000;
}| Term | Purpose |
|---|---|
| Upstream | Group backend servers |
| Round Robin | Default balancing |
| Least Connections | Send to least busy server |
| IP Hash | Same client → same server |
| Health Checks | Detect failed servers |
Example:
upstream backend {
server localhost:3000;
server localhost:3001;
}| Feature | Purpose |
|---|---|
| root | Website directory |
| alias | Different filesystem path |
| MIME Types | Correct content type |
| index | Default file |
| Autoindex | Directory listing |
| Feature | Purpose |
|---|---|
| SSL/TLS | HTTPS |
| HTTP → HTTPS Redirect | Force secure traffic |
| HSTS | Enforce HTTPS |
| Rate Limiting | Prevent abuse |
| Basic Authentication | Password protection |
| Hide Server Version | Improve security |
| Feature | Purpose |
|---|---|
| Gzip Compression | Smaller responses |
| Brotli Compression | Better compression (optional module) |
| Keepalive | Reuse connections |
| Caching | Faster responses |
| Buffering | Smooth data transfer |
| Sendfile | Faster file delivery |
| Feature | Purpose |
|---|---|
| Access Log | Record all requests |
| Error Log | Record errors |
| Log Format | Customize logs |
| Debug Logging | Troubleshooting |
Browser
│
▼
Nginx
│
HTML/CSS/JS
Example:
- Portfolio
- Landing page
- React production build
Browser
│
▼
Nginx
│
Node.js
Example:
- Express API
- NestJS
- Django
- Spring Boot
Nginx
/ | \
App1 App2 App3
Distributes traffic across multiple servers.
HTTPS
│
Nginx
│
HTTP
│
Backend
Nginx handles encryption so your backend can run on plain HTTP internally.
Browser
│
▼
Nginx
├──────────────┐
│ │
React Build Node API
A very common MERN deployment pattern.
example.com
shop.com
blog.com
│
Nginx
One Nginx instance serves multiple domains.
Serve:
- Images
- Videos
- CSS
- JavaScript
- PDFs
without involving the backend.
Examples:
- HTTP → HTTPS
- old-page → new-page
- Trailing slash normalization
Protect APIs from excessive requests.
Example:
- 100 requests/minute per IP
Supports real-time applications:
- Chat apps
- Notifications
- Live dashboards
- Multiplayer games
| File/Folder | Purpose |
|---|---|
| /etc/nginx/nginx.conf | Main configuration |
| /etc/nginx/conf.d/ | Additional configs |
| /etc/nginx/sites-available/ | Available virtual hosts (Debian/Ubuntu) |
| /etc/nginx/sites-enabled/ | Enabled virtual hosts |
| /var/log/nginx/access.log | Access logs |
| /var/log/nginx/error.log | Error logs |
| /run/nginx.pid | Master process ID |
- Nginx
- Master Process
- Worker Process
- Event-Driven Architecture
- Non-Blocking I/O
- Worker Processes
- Worker Connections
- Keepalive
- nginx.conf
- Main Block
- Events Block
- HTTP Block
- Server Block
- Location Block
- Upstream Block
- Directive
- Context
- Include
- listen
- server_name
- location
- root
- alias
- index
- proxy_pass
- try_files
- rewrite
- return
- Reverse Proxy
- Forward Proxy
- Load Balancer
- Virtual Host
- Gzip Compression
- Caching
- SSL/TLS
- Access Log
- Error Log
- Rate Limiting
- WebSocket Proxy
- HTTP → HTTPS Redirect
The simplest setup — Nginx just serves files directly from disk, no backend involved at all.
Flow: Browser asks for a page → Nginx matches the request to a location block → the root directive tells it which folder to look in → it reads the matching file straight off disk and returns it. No app server ever gets involved. Used for portfolios, landing pages, or a React/Vue production build.
Now Nginx sits in front of an application server instead of serving files itself.

Flow: The browser never talks to the app server directly — it only knows about Nginx. Nginx receives the request, and proxy_pass forwards it to whatever's running behind it (Express, NestJS, Django, Spring Boot). Nginx also adds headers so the backend still knows the real client IP. This is the backbone pattern almost every other scenario builds on.
Same idea as a reverse proxy, but now there's more than one backend to choose from.
Flow: Every incoming request hits Nginx first. Nginx picks one server from the upstream group using a strategy — round robin (default, just cycles through), least connections (send to whichever server is least busy), or IP hash (same client always lands on the same server, useful for session stickiness). If a server stops responding, health checks pull it out of rotation automatically.
Nginx handles all the encryption overhead so your backend doesn't have to.
Flow: The client connects to Nginx over HTTPS, so all the TLS handshake and certificate work happens right there. Nginx decrypts the traffic and passes it on to the backend as plain HTTP over the internal network — the backend never needs its own certificate. Add HSTS and an HTTP → HTTPS redirect on top and you've covered the full security-features section too.
Nginx splits traffic: static frontend files go one way, API calls go another.
Flow: One server block, two location blocks. Requests to / (or any frontend route) hit try_files, which serves the static React build — falling back to index.html for client-side routing. Requests to /api get matched first and proxy_passed straight to the Node backend. This is the standard way to deploy a MERN app behind one domain.
One Nginx instance, many completely separate sites.
Flow: All three domains point at the same server IP. When a request arrives, Nginx reads the Host header and matches it against server_name in each server block. Each block has its own root or proxy_pass, so example.com, shop.com, and blog.com end up served completely independently — even though it's one Nginx process handling all of them.
Keep heavy files off the application server entirely.
Flow: A location block matches file extensions or a path prefix like /assets/, and Nginx serves those bytes straight from disk using sendfile — no PHP, Node, or Python process ever wakes up for it. Add gzip/brotli compression and cache headers here and images, videos, PDFs, and JS bundles load fast without costing backend CPU.
Nginx can quietly change the URL before anything else sees it.
Flow: The browser asks for /old-page. Nginx matches it in a location or rewrite rule and sends back a 301 (permanent) response pointing at /new-page — the browser then makes a second request to the new URL. The same mechanism forces HTTP → HTTPS and normalizes trailing slashes.
Nginx can reject excess requests before they ever reach your app.

The last scenario — keeping a persistent, real-time connection alive through Nginx.
Flow: A normal HTTP request comes in with an Upgrade: websocket header. Nginx has to explicitly forward Upgrade and Connection headers (this doesn't happen by default with plain proxy_pass) and hold the connection open instead of treating it as a one-shot request/response. Once upgraded, both sides keep that single TCP connection alive for as long as needed — this is what powers chat apps, live notifications, dashboards, and multiplayer games.
.png)
