Nginx Introduction

What Nginx is, installing it, and how its configuration file structure is organized.

What Nginx is

Nginx (pronounced "engine-x") is a piece of software that can act as three different things depending on how it's configured:

  • A web server — it can serve static files (HTML, CSS, JS, images) directly off disk, extremely fast, with a small memory footprint per connection.
  • A reverse proxy — it can sit in front of an application server (PHP-FPM, Node.js, a Java app) and forward requests to it, adding TLS termination, compression, and buffering along the way.
  • A load balancer — it can distribute incoming requests across a pool of backend servers.

Most real deployments use Nginx for more than one of these roles at once: it terminates HTTPS, serves static assets directly, and proxies everything else to an application server behind it — all from the same config file. This tutorial focuses on the practical config syntax for all three roles; if you want the underlying architectural concepts (why reverse proxies and load balancers exist, load balancing algorithms, caching strategies), see the System Design track's page on load balancing and caching.

Installing Nginx

On Debian/Ubuntu:

Bash
sudo apt update
sudo apt install nginx
sudo systemctl enable --now nginx

On RHEL/CentOS/Amazon Linux:

Bash
sudo yum install nginx
sudo systemctl enable --now nginx

Once installed, Nginx starts serving a default welcome page on port 80 immediately. Useful commands for managing the running service:

Bash
sudo systemctl status nginx     # check it's running
sudo systemctl restart nginx    # full restart (drops connections briefly)
sudo systemctl reload nginx     # reload config with zero downtime
sudo nginx -t                   # test config syntax before reloading — always run this first

nginx -t is worth calling out on its own: it validates your configuration file syntax without applying it, so you catch a typo before reloading breaks the live server.

Config file structure

The main configuration file is /etc/nginx/nginx.conf. It defines a small number of nested contexts (blocks), each scoping directives that apply within it:

Nginx
# /etc/nginx/nginx.conf (simplified)
user www-data;
worker_processes auto;

events {
    worker_connections 1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    sendfile on;
    keepalive_timeout 65;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
  • events {} — controls how Nginx handles connections at a low level (e.g. worker_connections, the max simultaneous connections per worker process).
  • http {} — the context for everything HTTP/HTTPS-related. Almost all the configuration you'll actually write lives inside http, directly or through an included file.
  • server {} — nested inside http, one server block represents one virtual host — typically one domain (or one domain + port combination).
  • location {} — nested inside server, a location block matches a URL path and defines how requests to that path are handled.

In practice, you rarely edit nginx.conf itself. Distro packages split real site configuration into separate files:

  • Debian/Ubuntu: individual site configs go in /etc/nginx/sites-available/, and are activated by symlinking into /etc/nginx/sites-enabled/.
  • RHEL/CentOS/Amazon Linux: site configs go directly in /etc/nginx/conf.d/*.conf.
Bash
# Debian/Ubuntu: enable a site
sudo ln -s /etc/nginx/sites-available/mysite.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Common mistakes

  • Editing nginx.conf directly for site-specific config instead of adding a file under sites-available/conf.d — this makes config sprawl and multi-site management much harder to reason about.
  • Running systemctl restart after every config change instead of nginx -t followed by reload — restart drops active connections, reload doesn't.
  • Forgetting to symlink a new config into sites-enabled (Debian/Ubuntu) and wondering why the site "doesn't exist."
  • Not running nginx -t before reloading — a syntax error in reload can leave the old config running, or in some failure modes stop Nginx from serving at all.