Picking the wrong server block is the classic reason a site shows another site's content.
A server block is a virtual server. NGINX chooses one for each request in two steps:
- First by address and port: only servers whose
listenmatches the connection are candidates. - Then by the Host header compared with
server_name.
server_name accepts several forms, checked in this priority order:
- exact names:
example.com www.example.com - the longest wildcard starting with
*:*.example.com - the longest wildcard ending with
*:mail.* - the first matching regular expression, in file order:
~^(?<sub>.+)\.example\.com$
If no name matches, the request goes to the default server for that address and port: the one marked listen 80 default_server, or otherwise simply the first server block defined for it. That's why requests for unknown hosts, or for a bare IP address, sometimes land on a random site.
A good practice is an explicit catch-all that rejects unknown hosts. return 444 is an NGINX-specific code that closes the connection without a response.
The special name .example.com matches both example.com and all its subdomains.
Example
server {
listen 80 default_server; # catch-all for unknown Host headers
server_name _;
return 444; # close the connection, send nothing
}
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example;
}
server {
listen 80;
server_name *.shop.example.com; # any subdomain of shop.example.com
root /var/www/shop;
}
# curl -H 'Host: www.example.com' http://127.0.0.1/ -> /var/www/example
# curl -H 'Host: other.org' http://127.0.0.1/ -> connection closedRemember
- Servers are matched by listen address/port, then by server_name
- Exact names beat wildcards, which beat regexes
- No match goes to default_server, or the first server for that port
Watch out for
- Relying on file order for the default server; mark it explicitly with default_server.