Table of Contents
What Nginx Is and When to Use It
Nginx (pronounced “engine-x”) is a high‑performance, event‑driven web server and reverse proxy. In contrast to more process‑heavy servers, it is designed to handle very high numbers of simultaneous connections with low memory usage.
Typical uses:
- Static file web server (HTML, CSS, JS, images)
- Reverse proxy in front of application servers (PHP-FPM, Node.js, Python, Ruby)
- Load balancer (HTTP, TCP/UDP)
- TLS/SSL termination endpoint
In this chapter, we focus on core concepts and basic configuration you need to get a working Nginx setup on a Linux server.
Installing Nginx
Exact commands depend on your distribution’s package manager.
Debian/Ubuntu
sudo apt update
sudo apt install nginxDefault service management:
sudo systemctl enable nginx
sudo systemctl start nginx
sudo systemctl status nginx
Default web root: /var/www/html
Default main config: /etc/nginx/nginx.conf
RHEL/CentOS/Rocky/Alma (DNF/YUM family)
Some distros require enabling EPEL or an nginx module; on current RHEL derivatives it is typically available directly:
sudo dnf install nginx
sudo systemctl enable nginx
sudo systemctl start nginxOften the defaults are the same or very similar:
- Main config:
/etc/nginx/nginx.conf - Web root:
/usr/share/nginx/htmlor/var/www/html(varies by distro)
openSUSE
sudo zypper install nginx
sudo systemctl enable nginx
sudo systemctl start nginxCheck distribution documentation if paths differ; the configuration structure is still the same conceptually.
Nginx Configuration Structure
Nginx uses a hierarchical configuration with:
- Main context (global)
- Events context
- HTTP context (for web/HTTP settings)
- Server blocks (virtual servers)
- Location blocks (per‑path behavior)
Basic skeleton:
# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
# Include individual virtual host configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}Key ideas:
http { ... }contains all HTTP‑related configuration.- Each
server { ... }insidehttprepresents a virtual host (domain). locationblocks inside aserverdefine how certain URLs are handled.
Master and Worker Processes (High-Level)
Nginx uses:
- Master process: reads configuration, manages worker processes, handles reloads.
- Worker processes: do the actual work of handling connections.
Relevant directives (in nginx.conf):
worker_processes auto;— number of worker processes (oftenautois fine).worker_connections 1024;— max concurrent connections per worker.
Rough maximum concurrency:
$$
\text{max\_connections} \approx \text{worker\_processes} \times \text{worker\_connections}
$$
These are tuning topics, but you should recognize where they are defined and that they live in the global / events context, not per‑site.
Basic HTTP Server Block (Virtual Host)
Nginx uses server blocks (often called “virtual hosts”) to host multiple sites on one server.
Minimal HTTP example:
# /etc/nginx/sites-available/example.conf
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example;
index index.html index.htm;
access_log /var/log/nginx/example.access.log;
error_log /var/log/nginx/example.error.log;
location / {
try_files $uri $uri/ =404;
}
}Common directives:
listen— which IP/port to listen on (e.g.,80,443 ssl).server_name— domain names this server block responds to.root— filesystem path for this site’s documents.index— default file when a directory is requested.access_log,error_log— logs for this server.
On Debian/Ubuntu, typical layout:
- Place this file in
/etc/nginx/sites-available/example.conf - Enable it with a symlink:
sudo ln -s /etc/nginx/sites-available/example.conf \
/etc/nginx/sites-enabled/example.conf- Then reload Nginx (see later section).
On other distros, a common convention is simply: /etc/nginx/conf.d/example.conf (included from nginx.conf).
Location Blocks and URL Matching
location blocks control how Nginx handles different request paths.
Basic forms:
location / {
# matches everything (fallback)
}
location /images/ {
# matches /images/... but not /img/...
}
location = /exact-path {
# exact match for /exact-path
}Common prefixes/operators:
location /path/ { ... }— prefix match.location = /path { ... }— exact match.location ~ \.php$ { ... }— regex match (case-sensitive).location ~* \.(jpg|jpeg|png)$ { ... }— case-insensitive regex.
Nginx chooses the best match based on a fixed order (exact > prefix > regex). When starting out, stick to simple prefix and exact matches.
Serving Static Files
A simple static site configuration:
server {
listen 80;
server_name static.example.com;
root /var/www/static.example.com;
index index.html;
location / {
# 'root' from server context is used
try_files $uri $uri/ =404;
}
# Serve files under /assets/ with caching headers
location /assets/ {
expires 7d;
add_header Cache-Control "public";
}
}Key directives:
root— where files live.try_files $uri $uri/ =404;— try the exact file, then directory, else 404.expiresandadd_header— simple caching headers for static assets.
Basic Reverse Proxying
Nginx frequently sits in front of an application server (e.g., Gunicorn, uWSGI, Node.js, PHP-FPM). It accepts client connections and forwards them to the backend.
Minimal HTTP reverse proxy:
upstream app_backend {
server 127.0.0.1:3000;
# you can list multiple servers here for load balancing
}
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://app_backend;
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;
}
}Key pieces:
upstream— group of backend servers.proxy_pass— where to send requests.proxy_set_header— preserve client IP and protocol information for the app.
Without correct headers, your application may see all traffic coming from 127.0.0.1 instead of real client IPs.
Basic TLS/HTTPS Configuration
Nginx can directly terminate TLS; full certificate management is covered elsewhere, so here’s the minimal structure once you have keys.
Assuming:
- Certificate:
/etc/ssl/certs/example.crt - Private key:
/etc/ssl/private/example.key
server {
listen 443 ssl http2;
server_name secure.example.com;
ssl_certificate /etc/ssl/certs/example.crt;
ssl_certificate_key /etc/ssl/private/example.key;
# Basic security/cipher settings will be covered in SSL/HTTPS chapter
# but you need at least the above to bring TLS up.
root /var/www/secure.example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name secure.example.com;
return 301 https://$host$request_uri;
}Important points:
- Use a separate server block for HTTPS with
listen 443 ssl. - Redirect from port 80 to 443 for the same
server_name. - Use appropriate file permissions on key file (
root:root, mode600typically).
Managing Nginx: Test, Reload, Restart
When editing configuration, never restart blindly on production. Use Nginx’s built-in config tester.
Test Configuration
sudo nginx -tIf everything is OK, you see something like:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successfulIf there are errors, output will indicate the file and line; fix and re-test.
Reload Without Dropping Connections
To apply changes gracefully:
sudo systemctl reload nginxNginx will:
- Re-read configuration
- Start new worker processes with new config
- Gracefully shut down old workers once they finish active requests
Restart
Use a restart only if necessary (e.g., crashed process, binary update):
sudo systemctl restart nginxLogging Basics
Nginx provides per-site logging; useful for debugging and analysis.
In a server block:
access_log /var/log/nginx/example.access.log;
error_log /var/log/nginx/example.error.log warn;- Access log — each request, including status code, response size, etc.
- Error log — configuration errors, upstream failures, permission issues.
Common commands:
# View latest access log entries
sudo tail -f /var/log/nginx/example.access.log
# View latest error log entries
sudo tail -f /var/log/nginx/example.error.log
Log formats can be customized globally in http { ... } using log_format but basic defaults are sufficient to start.
Common Beginner Pitfalls
Some frequent issues when starting with Nginx:
- Wrong server block chosen
- Symptom: You hit the server in a browser and get the “Welcome to nginx!” page or the wrong site.
- Check:
server_namematches the requested hostname; order and default server configuration. - Hint: Use
curl -H "Host: example.com" http://IP/to test. - File permission errors
- Symptom: 403 Forbidden for static files.
- Cause: Nginx worker user (e.g.,
www-data,nginx) cannot read files. - Fix: Ensure directory and file permissions allow read (
r) and execute (xon directories) for the Nginx user or group. - Forgetting to reload after config change
nginx -tthensystemctl reload nginxafter every change.- Port already in use
- Symptom: Nginx fails to start; error log mentions
bind() to 0.0.0.0:80 failed. - Cause: Another service is listening on that port (perhaps Apache).
- Fix: Stop/disable the other service or change Nginx port.
- Proxying without proper headers
- Symptom: Application logs show
127.0.0.1as client IP for everything. - Fix: Add
proxy_set_header X-Real-IPandX-Forwarded-Forin proxy location.
Basic Hardening Steps (Overview Only)
Full web hardening is covered elsewhere, but minimal Nginx-specific basics:
- Disable server tokens (hide Nginx version):
# in http { ... }
server_tokens off;- Restrict access to sensitive paths:
location ~ /\. {
deny all;
}- Separate logs and config per site for easier auditing and isolation.
These are starting points; a proper hardening strategy goes much further.
Quick Checklist: Bringing Up a Simple Site
- Install Nginx via your distro package manager.
- Create web root, e.g.:
sudo mkdir -p /var/www/example
sudo chown -R $USER:$USER /var/www/example
echo "Hello from Nginx" > /var/www/example/index.html- Create server block in
/etc/nginx/sites-available/example.conf(orconf.d/). - Enable the config (symlink or ensure it’s included).
- Test configuration:
sudo nginx -t. - Reload Nginx:
sudo systemctl reload nginx. - Test from client:
curl http://example.comor via browser.
Once you’re comfortable with these basics, you can move on to using Nginx for virtual hosts, SSL/TLS, reverse proxying to app servers, and more advanced features.