Lesson 4 / 25

Server Blocks and Request Routing by Host

Configure virtual hosts with listen, server_name and default_server.

Choosing which server handles a request

One NGINX instance can host many sites with server blocks (virtual hosts). For each request, NGINX first picks servers whose listen matches the address and port the connection arrived on, then compares the request's Host header with each server_name. Matching order: exact names first (example.com), then the longest wildcard starting with an asterisk (*.example.com), then the longest wildcard ending with one (mail.*), then the first matching regular expression (~^(?<tenant>.+)\.app\.example\.com$) in configuration order. If nothing matches, the default server for that listen socket handles the request: the one marked default_server, or else the first one defined. It is good practice to define an explicit default server that rejects unknown hosts (for example with return 444;, which closes the connection), so requests for random hostnames or bare IP addresses do not land on a real site.

Picking a server block

The listen socket narrows the candidates; the Host header picks one; otherwise the default server answers.

An incoming arrow reaching a sorting funnel, splitting into three site boxes with name tags and one grey box marked with a shield as the catch-all.
Figure 2.1 — Request routing by listen address and server_name.

Several sites plus a catch-all

Unknown hosts never reach a real application.

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 444;                         # close connection for unknown hosts
}

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example;
}

server {
    listen 80;
    server_name ~^(?<tenant>[a-z0-9-]+)\.app\.example\.com$;
    root /var/www/tenants/$tenant;      # named capture used as a variable
}

server_name _ is not magic

_ is just an invalid hostname that never matches; what makes a block the catch-all is default_server on its listen directive (or being defined first). Be explicit.

Quick check: No server_name matches a request's Host header. Which server block handles it?

  • NGINX returns 500
  • The last server block in the file
  • The default server for that listen address and port
  • A random server
Answer

The default server for that listen address and port — The default_server (or the first defined) for the matching listen socket handles unmatched hosts.