The server {} block is nginx's virtual host. The server_name directive declares which hostnames the block responds to and supports exact names, leading wildcards (\*.example.com), trailing wildcards (www.example.\*), and regex names prefixed with ~. When a request arrives, nginx first picks the listen socket and then chooses the server with the best matching server_name. If no name matches, the block marked listen 80 default_server; (or listen 443 default_server; on TLS) handles the request — this is the conventional home for a catch-all redirect or a default site.
Inside a server, the location directive matches against the normalised request URI (after percent-decoding and stripping .. segments). Four kinds of match are available, in strict priority order: = exact match, ^~ preferential prefix, ~ and ~* regex (case-sensitive and case-insensitive, with the first defined winning), and finally the longest matching plain prefix. Understanding this order is essential: a location = /login always wins over a regex or prefix, which is exactly what you want for a high-traffic endpoint.
Once a location is selected, two directives determine where files come from. root appends the request URI to the configured path, so root /var/www; with a request for /img/x.png serves /var/www/img/x.png. alias replaces the matched location prefix with the alias path and requires the alias to end with a slash matching the location; with alias /var/www/; the same request is served as /var/www/img/x.png. The index directive defines the file nginx serves when a directory is requested (the default is index index.html;), and you can extend the list to index index.html index.htm index.php;. For paths that might not exist as files, try_files walks a list in order — try_files $uri $uri/ /index.php?$query_string; — and falls back to a final URI or named location when nothing matches. The special named location syntax (location @fallback { ... }) is reachable only through internal redirects, which makes it perfect for error handlers and SPA fallbacks.
For outright redirects or rejections, return sends an immediate HTTP response without contacting any upstream: return 301 https://example.com$request_uri; performs a permanent redirect, while return 302 ...; is the temporary variant. Use 301 only when the move is truly permanent, because browsers cache 301s aggressively and rollbacks become difficult. For more flexible URI manipulation, rewrite matches a regex against the URI and can capture groups, ending with a flag such as last, break, redirect, or permanent. The difference between last and break is subtle but important: last stops processing the current server or location and restarts matching against the rewritten URI, while break stops only the rewrite phase and continues serving the rewritten URI inside the same location. Used with try_files and return, these primitives cover almost every routing pattern you will encounter.