Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

A NGINX server block maps one or more hostnames to a site or application. Create a block with the correct listen, server_name and content handler, make sure the running nginx.conf includes it, validate the complete configuration with nginx -t, reload NGINX, and test using the intended hostname. When NGINX serves the wrong site, inspect the address and port selected by listen, the Host header, default-server rules and the full parsed configuration from nginx -T.

What an NGINX server block does

A server block is NGINX’s virtual-server unit inside the http context. It normally combines a listen directive, which selects a local address and port, with server_name, which identifies the hostnames handled by that block. The block then defines how matching requests are served, either from files with root and index or by forwarding them to an application with proxy_pass.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

NGINX chooses a block in two stages. It first compares the request’s local IP address and port with the listen directives. Among the blocks on that socket, it compares the HTTP Host header with server_name. If no name matches, NGINX uses the default server for that address and port. The default server is a property of the listen port, not of a server name.

Server-name matching priority

When several names could match, NGINX stops at the first match in this order:

  1. Exact server name, such as app.example.com.
  2. The longest wildcard beginning with an asterisk, such as *.example.com.
  3. The longest wildcard ending with an asterisk, such as mail.*.
  4. The first matching regular expression.

Exact names are easiest to audit. Wildcards can reduce repeated configuration, while regular expressions are evaluated later and are more difficult to reason about when multiple blocks overlap.

Prepare the configuration before adding a block

Find the active file and include graph

NGINX reads text configuration, normally beginning with nginx.conf. Server blocks must be loaded in a traffic-handling context, usually through an include directive inside http. Operating-system packages often provide directories such as conf.d or a sites-enabled layout, but directory names are not authoritative: the running configuration’s include directives are.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Locate the nginx.conf used by the running NGINX service.
  2. Read its http section and every referenced include pattern.
  3. Place the new file in a path that the active include pattern actually reads, or add an include for that path.
  4. Keep a backup of the last known-good configuration before editing.

If you are unsure which files are active, run nginx -T with the same privileges and configuration path used by the service. The command prints the complete parsed configuration, including included files, and is the fastest way to find a block that was never included or was overridden by another file.

Create a server block for a static site

For a site made of files, use root to identify the document directory and index to define the default file:

server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/example;
    index index.html;
}

Adapt the values safely

  • Replace example.com and www.example.com with the names that DNS will send to this server.
  • Set root to the directory containing the site. Confirm that the expected index file exists there.
  • Use one block for names that intentionally serve the same content. Give a different site its own block and its own server_name.
  • Ensure the NGINX worker can read the directory and files. A correct block still returns an error if the operating-system permissions prevent access.

The listen 80 line handles HTTP on port 80. If the machine has separate IPv4 and IPv6 listeners, configure both deliberately when clients can reach either address; otherwise, behavior can differ by network.

Configure a reverse proxy server block

For an application server, NGINX accepts the public request and forwards it to an upstream process. The relevant configuration surface includes location, proxy_pass and proxy headers:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Change the upstream address and port to the endpoint on which the application is listening. The application must be running and reachable from the NGINX host; a syntactically valid block cannot make an unavailable upstream respond.

Choose between files and proxying

Requirement Direct file serving Reverse proxy
Primary directives root, index location, proxy_pass, proxy headers
Request destination Files below the configured document root An application endpoint such as 127.0.0.1:3000
Main failure to investigate Missing file, wrong root or unreadable permissions Stopped or unreachable upstream process

Enable, validate and reload the block

Make sure NGINX can see the file

Creating a file is not enough. The file must be matched by an include directive in the configuration used by the running service. Use nginx -T to confirm that the block appears exactly once and that its directives are in the expected context.

Test the complete configuration

  1. Run nginx -t with appropriate privileges.
  2. Read every line of the result. Correct syntax, directive-context, path, duplicate-listener and certificate errors before proceeding.
  3. Run nginx -t again after each correction. A successful test applies to the complete included configuration, not just the file you edited.

Do not reload after a failed test. NGINX’s configuration test is the guard that prevents a bad edit from replacing a working configuration.

Reload without stopping active connections

After nginx -t succeeds, reload NGINX through the host’s service manager. On a systemd installation, that is commonly sudo systemctl reload nginx; use the equivalent command for the service manager on your platform. Then make a request using the real hostname, not merely the server’s IP address.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -I http://example.com

For a pre-DNS test, send the intended Host header while addressing the server directly:

curl -I -H 'Host: example.com' http://SERVER_IP/

This distinguishes an NGINX routing problem from a DNS record that points somewhere else.

Set up HTTPS for one or more domains

Use one HTTP block for port 80 and a separate HTTPS block for port 443. An HTTPS block needs the TLS listener, the names it serves, and paths to a valid certificate and private key:

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /path/to/certificate.pem;
    ssl_certificate_key /path/to/private-key.pem;

    root /var/www/example;
    index index.html;
}

You can use the port-80 block to redirect HTTP or to handle it separately, depending on the site’s requirements. Each certificate and key path must exist and be readable by NGINX; test the configuration before reloading.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Redirect HTTP to HTTPS

When every request should use TLS, keep the port-80 block deliberately small and redirect it to the same URI on HTTPS:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

The redirect block does not need a document root because it never serves the page itself. Keep the 443 block separate so certificate directives are only applied to the TLS listener. If some HTTP paths must remain available, handle those requirements explicitly instead of adding a blanket redirect.

How multiple HTTPS names share one IP

Server Name Indication (SNI) lets several HTTPS names share one IP address. Configure each name in the appropriate server_name list or block, provide the matching certificate, and ensure the request reaches the intended 443 listener. If SNI or name matching is wrong, a browser can receive the certificate belonging to the default server instead of the requested domain.

Long or numerous names

Large name sets can exceed NGINX’s server-name hash limits. If NGINX reports that it could not build the server_names_hash, adjust these directives in the http context:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • server_names_hash_bucket_size addresses names that are too long for a bucket.
  • server_names_hash_max_size addresses a hash that contains many names.

Change the relevant value, run nginx -t, and reload only after the test succeeds.

Why NGINX serves the wrong site

1. The hostname does not match

Check the exact spelling of the requested hostname and the Host header. A request for www.example.com does not match a block that lists only example.com. Confirm DNS resolves the name to the intended server, then reproduce the request with curl -H 'Host: ...' so the header is unambiguous.

2. The request landed on the default server

If no server_name matches, NGINX selects the default for that address and port. If no block explicitly uses default_server, the first block for that socket becomes the default. The name _ by itself does not make a block the default.

For a deliberate catch-all, mark the listener explicitly:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
server {
    listen 80 default_server;
    server_name _;
    return 444;
}

Use a catch-all only when dropping or separately handling unmatched hosts is intentional. Inspect nginx -T to see which block is first and which one declares default_server.

3. IPv4 and IPv6 use different listeners

A hostname can resolve to both address families while only one has the new block. Compare the IPv4 and IPv6 listen lines in the effective configuration and test each path if results differ between networks.

4. Duplicate names or files are being loaded

Search the output of nginx -T for repeated server_name values and unexpected included files. Duplicate names on the same listen socket can trigger a conflicting server name ... ignored warning. Remove the duplicate or make one block authoritative; do not rely on file order to express a routing policy that should be explicit.

Understand listen sockets and default selection

The same hostname can legitimately have separate behavior on different sockets. For example, a block listening on 192.0.2.10:80 is not interchangeable with one listening on 192.0.2.11:80, and a port-443 block is never considered for an HTTP request on port 80. Check the address portion of every listen line, not just the port number.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If several blocks listen on the same address and port, designate one as default_server when unmatched traffic needs predictable handling. Otherwise, the first block NGINX loads for that socket is the default. A filename that sorts first is not a reliable policy: adding or removing an included file can change that order. An explicit catch-all makes the decision visible in the effective configuration.

Requests made directly to an IP address also frequently select the default because the Host header is the IP rather than one of your domain names. Test each domain with its real host header, and test IPv6 separately when an AAAA record is published.

Fix common NGINX errors

Message or symptom Likely cause Fix
nginx: [emerg] syntax error Missing brace or semicolon, invalid directive context, or an error in an included file Read the file and line reported, check braces and semicolons, verify that the directive is allowed in that context, then rerun nginx -t.
conflicting server name ... ignored Two blocks claim the same name on the same listen socket Remove the duplicate, consolidate the names, or make the intended block the only authoritative match. Confirm the result with nginx -T.
could not build the server_names_hash A name is too long or the configuration contains many names Increase server_names_hash_bucket_size for long names or server_names_hash_max_size for many names in http, then test.
Browser shows the wrong HTTPS certificate The request matched a different 443 block, SNI/name configuration is incorrect, or the intended certificate path is wrong Check the 443 listen, exact server_name, certificate paths and default-server selection in nginx -T.
502 Bad Gateway The reverse-proxy upstream is stopped or unreachable Check that the process is running and listening at the proxy_pass address, then inspect NGINX’s error log and the application’s own logs.
Static file returns 404 The root points to the wrong directory, the file is absent, or a location rule changes the expected handling Verify the full filesystem path, file existence and readable permissions; inspect more-specific location rules in the effective configuration.

Read errors in the right order

  1. Start with the first error from nginx -t; later messages can be consequences of the first failure.
  2. Check the referenced file, line and directive context.
  3. For runtime routing problems, print the merged configuration with nginx -T before changing files again.
  4. After a successful test and reload, reproduce the request and then read the NGINX error log if the response is still wrong.

A practical troubleshooting sequence

Use a fixed sequence instead of changing several directives at once. First verify that DNS resolves the hostname to the server’s intended IPv4 or IPv6 address. Next verify that the relevant socket is listening and that the block appears in nginx -T. Then send a request with an explicit Host header. This isolates name selection from DNS and browser caching.

Once the correct block is selected, inspect its handler. For a static site, combine the configured root with the requested URI and check that the resulting file exists and is readable. For a proxy, check the exact address in proxy_pass from the NGINX machine; an application that works from another host may still be unreachable locally. Only after these checks should you investigate application responses, redirects or page-level errors.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When a change appears to have no effect, compare the edited file with the block printed by nginx -T. Common explanations are an unexpanded include pattern, editing a configuration tree that the service does not use, or a second block with the same name taking precedence. Always test and reload the configuration that the running service actually reads.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Use a predictable layout for multiple sites

One exact-name block per site

For unrelated domains, separate blocks with exact names make ownership and troubleshooting clear. Keep each site’s static root or upstream definition in its own block, and avoid placing a name in more than one block on the same socket.

Wildcards for intentionally shared subdomains

A wildcard is useful when many subdomains genuinely share behavior. Remember that the longest matching wildcard wins, so a more specific exact name or wildcard can override the general one. Document the intended exception in the configuration so a later edit does not appear to be accidental.

Regular expressions only when necessary

Regular-expression server names are evaluated after exact and wildcard forms, and the first matching expression wins. Their order therefore matters more than it does for exact names. Prefer explicit names when the set is known and stable.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Operational checklist

  • DNS for every hostname points to the intended address, including any IPv6 address that clients can use.
  • The block is inside the active http include graph.
  • listen covers the address and port clients actually reach.
  • server_name contains every required hostname with no unintended duplicates.
  • Static roots contain the expected files and are readable by NGINX, or the proxy upstream is running and reachable.
  • HTTPS blocks have listen 443 ssl, matching names, and valid certificate and private-key paths.
  • nginx -t succeeds before every reload.
  • nginx -T confirms the effective configuration when a block appears missing, overridden or ambiguous.
  • A request tested with the real hostname returns the intended site, not merely a response obtained by IP address.

Following that sequence turns most server-block failures into a bounded check: first the socket, then the name, then the selected block’s content handler, and finally the files, certificate or upstream that block references.

Frequently Asked Questions

Why does NGINX show the default page instead of my site?

The request usually did not match the intended server_name, or it reached a different address or port. Confirm DNS, test with curl -H 'Host: your-domain', and inspect nginx -T for the selected listener, duplicate names and the explicit default_server.

Does server_name _; make a block the default?

No. The default is attached to a listen socket. Declare listen 80 default_server; (and the equivalent IPv6 listener when needed) to make the catch-all explicit.

What is the difference between nginx -t and nginx -T?

nginx -t checks whether the complete included configuration is valid. nginx -T performs that inspection while also printing the merged configuration, making it useful for finding missing includes, duplicates and unexpected overrides.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does nginx -t report a server-names hash error?

A hostname may be too long for the current bucket size, or the configuration may contain many names. Increase server_names_hash_bucket_size for long names or server_names_hash_max_size for many names inside the http context, then test again.

How do I host several HTTPS domains on one IP address?

Create the required 443 server blocks with matching server_name values, certificates and private keys. SNI lets NGINX choose the certificate and block by hostname. A wrong certificate usually indicates a 443 listener, SNI, name or default-server mismatch.

Why does a reverse proxy return 502 Bad Gateway?

The upstream named in proxy_pass is commonly stopped, listening on another address or blocked from NGINX. Check connectivity from the NGINX host, then read the NGINX error log and the application’s logs.

Why does a static file return 404 when the file exists?

The effective root may point elsewhere, the URI may be handled by a more-specific location, or NGINX may lack permission to read the path. Confirm the full path, permissions and merged configuration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I put every domain in one server block?

Only names that intentionally serve the same content and behavior belong together. Separate unrelated sites into exact-name blocks; use wildcards only for deliberately shared subdomains and avoid duplicate names on one socket.

The Bottom Line

Set the listener first, match the hostname second, and then verify the selected block’s files, certificate or upstream. Confirm the active include graph with nginx -T, require a clean nginx -t before every reload, and test with the real hostname or an explicit Host header.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.