The traffic director,Nginx.
A high-performance web server, reverse proxy, and load balancer that serves static content, terminates TLS, and routes traffic to upstream applications. This guide walks through a minimal server block, a wildcard virtual host, the KBVE reverse-proxy pattern, and the tuning that keeps it all fast and secure.
One instance, many hosts
A single Nginx instance can front dozens of virtual hosts, each defined by a server block that matches on server_name and port — serving static assets from disk while proxying dynamic requests upstream.
- Reverse proxy — terminate TLS and forward with proxy_pass.
- Load balancer — round-robin, least_conn, and ip_hash.
- Safe reloads — nginx -t then a graceful reload.
On this page
What this guide covers
Nginx configuration
Three configs in rising complexity — a minimal static block, a wildcard virtual host, and the KBVE reverse proxy with TLS.
Load balancing
Upstream pools with weight, backup, least_conn, and ip_hash for distribution, failover, and sticky sessions.
Gzip and caching
Compression and immutable cache headers — the highest-impact, lowest-effort wins for Core Web Vitals.
Security headers
Baseline hardening against clickjacking, MIME sniffing, and mixed content, plus a careful approach to HSTS.
Start here
Overview
Nginx is a high-performance web server and reverse proxy. It serves static assets directly from disk, terminates TLS, and forwards dynamic requests to upstream application servers over HTTP or a Unix socket. A single Nginx instance can front dozens of virtual hosts, each defined by a server block that matches on server_name and port.
This guide walks through three configurations in order of complexity: a minimal single-site block, a wildcard virtual host that serves many subdomains, and the KBVE reverse-proxy pattern that terminates TLS and load-balances upstream containers.
Four steps
Configuration Flow
-
Write a server block — Define
listen,server_name, and either aroot(static) orproxy_pass(reverse proxy). -
Validate the syntax — Run
nginx -t. Nginx checks every included file and reports the exact line on error. -
Reload gracefully — Run
nginx -s reloadorsystemctl reload nginx. Workers restart without dropping active connections. -
Verify —
curl -I https://your-hostconfirms the status code, TLS, and upstream headers.
Server blocks
Nginx Configuration
This is a default example of an Nginx configuration file. Each server block is self-contained; drop it in conf.d/ and reload.
Minimal Static Server Block
Section titled “Minimal Static Server Block”The simplest useful config: serve static files from a document root over port 80.
server { listen 80; server_name example.com;
root /var/www/example; index index.html;
location / { try_files $uri $uri/ =404; }}try_files attempts the exact URI, then the URI as a directory, then returns 404 — this is the correct pattern for a static site and avoids exposing the filesystem.
Example WildCard Nginx Configuration
Section titled “Example WildCard Nginx Configuration”A wildcard server_name matches every subdomain, letting one block serve *.example.com. The captured subdomain maps to a per-tenant document root.
server { listen 80; server_name ~^(?<sub>.+)\.example\.com$;
root /var/www/tenants/$sub; index index.html;
location / { try_files $uri $uri/ =404; }}The named capture (?<sub>.+) is reused in root, so a request to alice.example.com serves /var/www/tenants/alice. Pair this with a wildcard TLS certificate (*.example.com) to terminate HTTPS for every tenant from one block.
Example KBVE Nginx Configuration
Section titled “Example KBVE Nginx Configuration”The KBVE pattern terminates TLS and reverse-proxies to an upstream application (for example a container listening on 127.0.0.1:8000). It forwards the original host and client IP so the backend sees real request metadata.
upstream kbve_app { server 127.0.0.1:8000; keepalive 32;}
server { listen 443 ssl http2; server_name kbve.com;
ssl_certificate /etc/nginx/ssl/kbve.crt; ssl_certificate_key /etc/nginx/ssl/kbve.key;
location / { proxy_pass http://kbve_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; }}
server { listen 80; server_name kbve.com; return 301 https://$host$request_uri;}The second server block issues a 301 redirect from HTTP to HTTPS so no plaintext traffic reaches the app. The upstream block with keepalive reuses backend connections, cutting latency under load.
Spread the load
Load Balancing
An upstream block can list multiple backends, turning Nginx into a load balancer. The default method is round-robin; Nginx also supports least_conn (send to the backend with the fewest active connections) and ip_hash (pin a client to one backend for session stickiness).
upstream kbve_pool { least_conn; server 10.0.0.11:8000 weight=3; server 10.0.0.12:8000; server 10.0.0.13:8000 backup; keepalive 32;}
server { listen 443 ssl http2; server_name kbve.com;
location / { proxy_pass http://kbve_pool; proxy_set_header Host $host; }}| Directive | Behavior |
|---|---|
weight=N | Send proportionally more traffic to this backend |
backup | Only used when all primary backends are down |
max_fails / fail_timeout | Mark a backend unhealthy after N failures |
least_conn | Route to the least-busy backend |
ip_hash | Sticky sessions by client IP |
Fast by default
Performance: Gzip and Caching
Compression and static-asset caching are two of the highest-impact, lowest-effort SEO wins — smaller, faster responses improve Core Web Vitals, which Google uses as a ranking signal.
gzip on;gzip_comp_level 5;gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;gzip_min_length 256;
location ~* \.(?:css|js|jpg|jpeg|png|gif|ico|woff2)$ { expires 30d; add_header Cache-Control "public, immutable";}gzip_types must list every MIME type to compress (text/html is always compressed and cannot be listed). The immutable cache directive tells browsers never to revalidate fingerprinted assets, eliminating conditional requests.
Harden the edge
Security Headers
Add baseline security headers in the server block. These harden the site against clickjacking, MIME sniffing, and mixed content, and are checked by security scanners that can influence trust signals.
add_header X-Frame-Options "SAMEORIGIN" always;add_header X-Content-Type-Options "nosniff" always;add_header Referrer-Policy "strict-origin-when-cross-origin" always;add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;When it breaks
Troubleshooting
-
nginx -tfails — Read the printed file and line number. The most common cause is a missing semicolon or an unclosed block. -
502 Bad Gateway — Nginx reached the
proxy_passtarget but got no valid response. The upstream is down or bound to a different port/socket. Check withcurl 127.0.0.1:8000on the host. -
504 Gateway Timeout — The upstream is too slow. Raise
proxy_read_timeout, or fix the backend. -
403 Forbidden on static files — The Nginx worker user (
www-dataornginx) lacks read permission onroot, or SELinux is blocking it. Checkls -land the error log. -
Changes not taking effect — You edited the config but did not reload. Run
nginx -s reload, and confirm you edited the file actually included bynginx.conf.
Logs live at /var/log/nginx/access.log and /var/log/nginx/error.log by default — the error log is where upstream and permission failures surface.
Questions
Frequently asked
What is Nginx used for?
Nginx is a web server that also works as a reverse proxy, load balancer, and TLS terminator. It serves static files directly and forwards dynamic requests to upstream application servers.
Where is the main Nginx configuration file?
The primary file is /etc/nginx/nginx.conf. Site-specific server blocks usually live in /etc/nginx/conf.d/ or /etc/nginx/sites-available/ and are enabled by symlinking into sites-enabled.
How do I reload Nginx without dropping connections?
Run nginx -t to validate the configuration, then nginx -s reload (or systemctl reload nginx). A reload applies new config with a graceful worker restart and no dropped connections, unlike a full restart.
What is a reverse proxy in Nginx?
A reverse proxy accepts client requests and forwards them to one or more backend servers using proxy_pass. Nginx handles TLS, caching, and load balancing in front of the application, which never faces the client directly.
How do I load balance across multiple servers with Nginx?
Define an upstream block listing each backend server, then point proxy_pass at that upstream. Nginx defaults to round-robin and also supports least_conn and ip_hash. Use weight, backup, and max_fails to tune distribution and failover.
What causes a 502 Bad Gateway error in Nginx?
A 502 means Nginx reached the proxy_pass target but received no valid response — usually the upstream application is down or listening on a different port or socket. Verify the backend with curl on the host and check the Nginx error log.
How do I enable Gzip compression in Nginx?
Set gzip on and list the MIME types to compress with gzip_types (text/html is always compressed). Combine it with expires and Cache-Control headers on static assets to reduce payload size and improve Core Web Vitals.
