Guides

What is nginx? The web server and reverse proxy explained

What is nginx? A free web server, reverse proxy, load balancer and cache. What nginx is used for, nginx vs Apache, its config layout and how to install it.

Published ~8 min read
On this page

Short answer: nginx (pronounced “engine-x”) is free, open source software that serves websites and sits in front of applications. One program works as a web server, reverse proxy, load balancer and HTTP cache. Igor Sysoev released it publicly in 2004 to handle many thousands of simultaneous connections with little memory, which its event-driven design still does.

The project’s home page at nginx.org (read on 21 October 2026) calls it “an HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, and mail proxy server”. In practice that means it is the first program a request meets on a large share of the web’s servers: it answers static files itself and passes everything else on to the application behind it. This guide covers what nginx is used for, how its architecture differs from Apache, the open source and commercial editions, how its configuration is laid out on Debian and Ubuntu, and how to install it.

What does nginx mean, and how do you say it?

The name is a play on “engine x”, and that is how it is pronounced: “engine-ex”, not “n-jinx”. The open source project writes it in lower case, nginx; F5, the company that has owned the commercial side since 2019, writes NGINX in its product names. Both refer to the same core software.

What is nginx used for?

  • Web server. Serving HTML, CSS, JavaScript, images and downloads straight from disk, fast and with little memory per connection.
  • Reverse proxy. Accepting requests from the internet and passing them to an application server (Node.js, Python, PHP-FPM, Java) that listens only locally. What is a reverse proxy explains the pattern, and web server vs application server shows where each half of the work belongs.
  • TLS termination. Holding the HTTPS certificate and decrypting traffic, so the application behind it speaks plain HTTP on localhost.
  • Load balancer. Spreading requests over several backends with an upstream block: round robin by default, or least_conn, ip_hash, hash and random.
  • HTTP cache. Storing backend responses on disk with proxy_cache and answering repeat requests without asking the application.
  • Rate limiting and access control. Capping requests per client IP with limit_req, or restricting paths by address or password.
  • TCP and UDP proxy. The stream module forwards non-HTTP traffic, such as a database port or a game server, with load balancing.

A reverse proxy with load balancing, for example, takes a dozen lines:

nginx config
upstream app {
    least_conn;
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://app;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

How does nginx work? The event-driven design

nginx runs as one master process and a few worker processes. The master reads the configuration, opens the listening ports and starts the workers; it handles no traffic itself. Each worker runs a single event loop: it asks the kernel (through epoll on Linux, kqueue on the BSDs) which of its thousands of open connections have data ready, does a little work on each, and moves on without ever waiting on one client. The usual setting, worker_processes auto, starts one worker per available CPU, which on a machine with SMT means one per logical CPU.

Example output of ps on a 2 vCPU server
$ ps -o pid,user,cmd -C nginx
    PID USER     CMD
    812 root     nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
    813 www-data nginx: worker process
    814 www-data nginx: worker process

That design is why nginx keeps memory flat when many slow clients hold keep-alive connections open: an idle connection costs a small structure in a worker, not a whole process or thread. It also explains how a reload works without dropping traffic. The master starts new workers with the new configuration and tells the old ones to finish their current requests and exit; restarting or reloading nginx walks through that and when a full restart is needed instead.

The trade-off: a worker must never block. Slow disk reads can stall it, which nginx mitigates with thread pools for file I/O, and anything that runs application code (PHP, Python) has to live in a separate process that nginx talks to over FastCGI or HTTP.

nginx vs Apache

Apache httpd is the older web server (first released in 1995) and handles concurrency through interchangeable multi-processing modules (MPMs): prefork runs one process per connection, worker one thread per connection, and event hands idle keep-alive connections to a listener thread so workers stay free. Modern Apache with the event MPM narrows the gap, but the two still differ in ways that matter day to day:

nginxApache httpd
Concurrency modelA few event-driven workers, each holding thousands of connectionsMPM of your choice: prefork (process per connection), worker (threads) or event
Per-directory configNone: no .htaccess, every change goes into the main config and needs a reload.htaccess files, read on every request where AllowOverride permits
Running PHPThrough PHP-FPM over FastCGI onlymod_php inside Apache, or PHP-FPM
Static files under loadVery efficient, low memory per connectionGood with the event MPM; heavier with prefork
ModulesCompiled in or loaded as dynamic modules (since 1.9.11)Large module ecosystem, loaded at runtime
Licence2-clause BSDApache License 2.0
Typical role todayFront door: web server, reverse proxy, TLS, cacheApplication-heavy shared hosting and setups that rely on .htaccess

One Debian detail shows the difference in practice: installing libapache2-mod-php switches Apache from the event MPM to prefork, because mod_php is not thread-safe. Many hosts therefore run both servers together: nginx in front for TLS, static files and caching, Apache behind it for the PHP sites whose .htaccess rules nobody wants to translate.

Open source nginx vs NGINX Plus

The open source nginx from nginx.org is free under a 2-clause BSD licence and comes in two branches: mainline (odd minor version numbers, new features first) and stable (even minor numbers, bug fixes only). Distribution packages usually ship a stable release and backport security fixes, so Debian 12 still reports 1.22.1 years after release. Run nginx -v to see what you have, and check the nginx.org download page for the current branches rather than trusting a version number in any article.

NGINX Plus is F5’s paid subscription built on the same core. It adds features aimed at large deployments, such as active health checks, a live monitoring dashboard and API, extra session-persistence and load-balancing methods, JWT authentication and commercial support. For a website, an API or a handful of applications on one server, the open source edition is what nearly everyone runs.

How is nginx configured?

Everything lives in plain-text files made of directives (listen 80;) grouped into contexts (blocks in braces). The main file is /etc/nginx/nginx.conf; inside its http context, each server block is one site (what Apache calls a virtual host), and location blocks inside it decide how individual paths are handled.

PathWhat it holds
/etc/nginx/nginx.confGlobal settings: user, worker processes, the events and http contexts, and the include lines for everything below
/etc/nginx/sites-available/One file per site. The package ships a file named default
/etc/nginx/sites-enabled/Symlinks to the sites that are switched on; only these are loaded
/etc/nginx/conf.d/Extra *.conf files included into the http context
/etc/nginx/snippets/Reusable fragments, such as fastcgi-php.conf for PHP-FPM
/etc/nginx/modules-enabled/Dynamic modules loaded at start
/var/log/nginx/access.log and error.log
/var/www/htmlThe default site's document root

The default site in Debian 12’s package (1.22.1, read from the packaged file with comments removed) is a complete minimal server block:

/etc/nginx/sites-available/default (comments removed)
server {
	listen 80 default_server;
	listen [::]:80 default_server;
	root /var/www/html;
	index index.html index.htm index.nginx-debian.html;
	server_name _;
	location / {
		try_files $uri $uri/ =404;
	}
}

How to install nginx on Ubuntu or Debian

  1. 1Install the package
    Ubuntu · Debian
    sudo apt update
    sudo apt install -y nginx

    The service starts and is enabled at boot straight away. Check it with systemctl status nginx.

  2. 2Open the firewall
    Ubuntu · Debian with ufw
    sudo ufw allow 'Nginx Full'    # ports 80 and 443
    sudo ufw status

    The package ships ufw profiles named Nginx HTTP, Nginx HTTPS and Nginx Full. Make sure SSH is allowed before you enable ufw for the first time; setting up ufw has the order.

  3. 3Check that it answers
    any Linux
    curl -I http://localhost

    A HTTP/1.1 200 OK with a Server header that starts with nginx (by default it carries the version, such as nginx/1.22.1 on Debian 12, unless server_tokens off; is set) means the default site is up. Opening the server’s IP address in a browser shows the “Welcome to nginx” page.

  4. 4Add your own site
    Ubuntu · Debian
    sudo mkdir -p /var/www/example.com
    sudo nano /etc/nginx/sites-available/example.com     # a server block like the one above
    sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
    sudo nginx -t && sudo systemctl reload nginx

    Set server_name to your domain and root to the new directory, and point the domain’s DNS at the server. For HTTPS and proxying an app, nginx reverse proxy with SSL continues from here with certbot.

Basic nginx commands

TaskCommand
Test the configurationsudo nginx -t
Test and print the full merged configurationsudo nginx -T
Apply config changes without dropping connectionssudo systemctl reload nginx
Full restartsudo systemctl restart nginx
Show the versionnginx -v
Version plus build options and modulesnginx -V
Service logjournalctl -u nginx
Watch the error logsudo tail -f /var/log/nginx/error.log

Make nginx -t a habit before every reload: it catches a missing semicolon before it can take a site down. The systemd unit on Debian and Ubuntu runs the same test before it starts nginx, so a broken file shows up as a failed start rather than a half-running server.

Errors you will meet first

Running nginx on your own server

Installing and configuring nginx yourself needs root access, both for the package and to bind ports 80 and 443, so it is a job for a VPS or dedicated server; on shared hosting the provider decides which web server runs. nginx is light enough for the smallest plan: a static site or a reverse proxy in front of one app uses a few megabytes of RAM. Any Linux VPS with Ubuntu or Debian takes the steps above as they are.

Frequently asked

What is nginx used for?

Serving websites and sitting in front of applications: as a web server for static files, a reverse proxy that passes requests to Node.js, Python or PHP-FPM, a load balancer across several backends, a TLS terminator and an HTTP cache. Its stream module also proxies plain TCP and UDP traffic.

How do you pronounce nginx?

Engine-ex. The name comes from 'engine x'. The open source project writes it in lower case as nginx, and F5 writes NGINX in its commercial product names.

Is nginx better than Apache?

For static files and as a reverse proxy in front of applications, nginx usually needs less memory when there are many connections, because of its event-driven workers. Apache is more convenient where sites rely on .htaccess files or mod_php. Many servers run both: nginx in front, Apache behind it.

Is nginx free?

Yes. The open source nginx from nginx.org is free under a 2-clause BSD licence, and it is the version Debian, Ubuntu and most other distributions package. NGINX Plus is F5's paid subscription on the same core, with extra features for large deployments and commercial support.

Related articles

All guides