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.

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

When a second NGINX site returns 404 Not Found while the first site works, the request is usually reaching the wrong server block or the correct block is mapping the URL to a file that does not exist. Prove which server block received the request first; then check its root, alias, location, and try_files rules. A correct configuration must also be enabled, reachable through DNS, and separately configured for HTTP and HTTPS.

Why the second virtual host returns 404

NGINX chooses a server block before it looks for a file. It groups server blocks by listening address and port, then compares the request’s Host header with each block’s server_name. If no name matches, NGINX uses the default server for that address and port. The default block may belong to your first website, a catch-all, or an intentionally restrictive configuration.

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

Even when the intended block is selected, a 404 can still be generated during filesystem lookup. The URI is combined with the active root or interpreted through an alias. If the resulting file or directory is absent, or if try_files ends with =404, NGINX returns 404.

What is wrong What happens Where to investigate
Host does not match server_name Another server block, often the default, handles the request listen, server_name, DNS, and the actual Host header
Correct block is selected but path is wrong NGINX looks in the wrong directory or cannot find the requested file root, alias, location, file names, and permissions
try_files deliberately fails The final fallback returns an explicit 404 Arguments and location precedence in try_files
Only HTTPS fails Port 443 uses a different server-selection and location configuration 443 listener, certificate block, root, and HTTPS locations

How NGINX selects a server block

listen creates separate selection groups

Server selection is performed independently for each address-and-port combination. Two sites sharing one IP normally both use listen 80; for HTTP and are distinguished by their names. HTTPS sites normally share listen 443 ssl;, but still need matching names and their own TLS configuration.

#1 Best Overall
Recipe Book to Write in Your Own Recipes, Spiral Blank Cookbook 150 Recipes
  • B5 Recipe Book: This hardcover blank recipe book measures 10''×7.3'', containing 150 blank pages, comes with 1 sheet of DIY category stickers, perfect for writing down your own recipes and organizing them in one place.
  • Practical Layout - 5 pages of conversion charts show you everything you'll ever need to know in the kitchen. The table of contents will help organize your personal favorite recipes. A back pocket is designed for loose items.
  • Easy to Use - This blank cookbook is made of high-quality paper with a beautiful hardcover for long-term use. The sturdy gold double-wire spiral binding makes writing easier and page turning smoother.
  • Make Your Own Recipes - This blank cookbook has up to 150 blank pages for you to write in your own recipes, with plenty of space to record ingredients and instructions. You can write down all the special tips for your family members.
  • Thoughtful Gift - A personalized recipe book makes a thoughtful gift for your children or newlyweds, and a great gift for housewarming, weddings, bridal showers, anniversaries, or any other occasion.

default_server belongs to the listen directive, not to server_name. Therefore, a default on port 80 does not automatically become the default on port 443, and a default for one IP does not govern another IP.

server_name must match the literal Host

Include every name users actually request. If the site is reachable as both second.example and www.second.example, list both names. A request for the apex domain does not match a block that only contains www, and vice versa. The port is part of the HTTP request context, so an HTTP block does not select an HTTPS block merely because the names are identical.

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

Testing by IP can select a different site

When you browse to an IP address, the Host value is the IP unless you configure that IP as a server name. NGINX can consequently select the default block instead of the domain’s block. Always test with the actual hostname, or explicitly supply the Host header.

Reliable troubleshooting sequence

1. Validate syntax and print the effective configuration

Start with a syntax check:

sudo nginx -t

Then print the complete configuration NGINX is using:

sudo nginx -T

Search that output for every relevant directive:

sudo nginx -T 2>/dev/null | grep -nE 'listen|server_name|root|alias|index|location|try_files|return|proxy_pass'

This catches duplicate blocks, unexpected includes, an inherited location, or a second configuration file that you did not realize was loaded. If you need to confirm compiled paths and build options, inspect:

nginx -V

Use the output of nginx -T, rather than an unenabled file on disk, as the source of truth.

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

2. Confirm that the second site is enabled

On Debian and Ubuntu, a file in /etc/nginx/sites-available/ is not active until it is linked into /etc/nginx/sites-enabled/. Check the link and its target:

ls -l /etc/nginx/sites-enabled/

On systems that do not use those directories, inspect the include directives shown by nginx -T. If the intended file is not included, editing it cannot change live traffic.

3. Compare the listening contexts

Check that both blocks listen where you expect:

sudo nginx -T 2>/dev/null | grep -nE 'listen[[:space:]]'

For two domains sharing one address, both HTTP blocks generally listen on port 80. If you deliberately use different ports, users must request those ports and any firewall or load balancer must pass them through. Look for an accidental default_server on the wrong listener or two blocks competing for an address and port.

4. Test the exact Host value

From a client, bypass DNS and test HTTP against the server’s IP:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -i -H 'Host: second.example' http://SERVER_IP/

Test the alternate name separately:

curl -i -H 'Host: www.second.example' http://SERVER_IP/

For HTTPS, use --resolve so the TLS connection and Host name both identify the intended site while traffic goes to the chosen IP:

curl -ik --resolve second.example:443:SERVER_IP https://second.example/

A response that changes when you change the Host header proves that server selection, rather than the file itself, is the issue. The -k option allows this diagnostic to proceed with an untrusted or locally issued certificate; do not use it as a production security setting.

5. Check DNS independently

Resolve the domain from the client or a suitable DNS system:

dig +short second.example

The result must point to an address that actually receives the request. A perfect NGINX configuration cannot answer if public DNS still points to an old server, a different load balancer, or an address that has no route to this machine. Check the apex and www records separately because they can point to different destinations.

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

6. Verify the root, file, and directory traversal

Suppose the active block contains:

root /var/www/second;

For a request to /, verify the expected index file:

sudo ls -la /var/www/second/index.html

Also verify every parent directory. The NGINX worker must be able to traverse /var, /var/www, and /var/www/second, then read the file. A missing file normally produces 404 for static content; a permission problem can instead appear as 403 or an open() failure in the error log.

Remember that the URI, not an arbitrary local path, is translated through the active root or alias. For example, /images/logo.svg under root /var/www/second; maps to /var/www/second/images/logo.svg.

7. Read access and error logs while reproducing the request

Find the log paths in the selected server block or in inherited configuration, then watch them while running the explicit-Host curl command:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo tail -f /var/log/nginx/access.log /var/log/nginx/error.log

The access log can show the request’s Host, URI, status, and selected server if those variables are included in its log format. The error log commonly reveals the exact path NGINX attempted to open, a permission failure, a rewrite loop, or an upstream problem. If separate per-site logs are configured, watch the second site’s files; no new entry there is a strong indication that another block handled the request.

8. Inspect location precedence and try_files

A location can override the root you expected. Nested prefixes and regular-expression locations may win over a general location /, so inspect the complete active configuration rather than only the server-level directives.

This common static pattern intentionally returns 404 when neither a file nor a directory exists:

Rank #2
Pipilo Press Blank Family Cookbook Recipe Binder - 6.5 x 8.2 in Hardcover Spiral Bound - 90 Ruled Pages with Memo Pocket - Write In Your Own Recipes & Meal Planning Notebook
  • Create a Culinary Legacy: The Pipilo Press Blank Family Cookbook Recipe Binder offers a timeless platform for chronicling beloved recipes. With its hardcover and spiral binding, this recipe book to write in your own recipes ensures durability and ease of use for generations
  • Thoughtful Gifting Choice: This book for writing recipes is an ideal present for various occasions, adding a personal touch to celebrations. Its elegant design makes it perfect for moms cookbook DIY projects or anyone passionate about preserving family traditions
  • Durable Design Features: Constructed with a 300gsm cardstock cover and matte lamination, this cookbook you can write in ensures longevity. Its spiral-bound format provides convenient access to pages, making it a practical tool for everyday use
  • Organized Recipe Storage: The included memo pocket offers a space to store handwritten notes or recipe cards, enhancing its functionality. This feature transforms the recipe book for moms into a sentimental family memento
  • Ample Writing Space: Measuring 6.5 x 8.2 inches, this blank spiral family recipe cookbook offers plenty of room for detailed notes. It is perfect for jotting down ingredients, preparation methods, and serving suggestions for a complete culinary record
location / {
    try_files $uri $uri/ =404;
}

That is appropriate for a static site. For an application, the final argument may need to be a named location or an upstream fallback documented by that application. Do not remove try_files blindly: first determine whether the requested path should be a real file, a routed application URL, or a proxy request.

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

9. Diagnose HTTP and HTTPS separately

Port 80 and port 443 have separate server-selection contexts. A working HTTP block does not configure the HTTPS certificate, root, locations, or redirect target. Test both explicitly:

curl -i -H 'Host: second.example' http://SERVER_IP/
curl -ik --resolve second.example:443:SERVER_IP https://second.example/

If HTTP works and HTTPS returns 404, inspect the 443 block selected by nginx -T. Confirm its server_name, root, location, and any try_files or proxy directives. Also check that the certificate block is not a generic default that lacks the second site’s content configuration.

10. Reload only after validation

Apply a change only after the configuration passes validation:

sudo nginx -t && sudo systemctl reload nginx

A reload applies the new configuration without stopping existing connections. Repeat the explicit HTTP and HTTPS tests after the reload and watch the logs again, so you verify the running process rather than only the file you edited.

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.

Minimal configuration for a second static site

Use a simple block while isolating the problem:

server {
    listen 80;
    server_name second.example www.second.example;
    root /var/www/second;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

The two server_name values must match the Host header exactly, and /var/www/second must contain the requested files. Create or verify a test file before troubleshooting application rewrites:

sudo mkdir -p /var/www/second
printf '%sn' 'second site' | sudo tee /var/www/second/index.html

After enabling the block, run nginx -t, reload, and test with the domain Host header. If this minimal block works, add application-specific locations one at a time and retest after each change.

When the second site is an application

Application URLs often do not correspond to physical files. A static-style try_files $uri $uri/ =404; will therefore reject a route such as /dashboard unless a matching file or directory exists. Use the application’s documented front-controller or upstream pattern, and ensure the fallback is inside the intended server block.

For proxied services, inspect proxy_pass and the location that contains it. A request can appear to be a virtual-host 404 when the upstream application itself returns 404. The access log status, upstream-status fields if configured, and error log distinguish an NGINX file lookup from an upstream response.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Catch-all configuration that exposes mistakes

A deliberate catch-all prevents an unmatched Host from displaying another customer’s site:

server {
    listen 80 default_server;
    server_name _;
    return 404;
}

The underscore has no special catch-all behavior by itself. The catch-all status comes from default_server on the listen directive. With this policy, an incorrect Host or DNS record produces a clear 404 instead of silently serving the first site’s content. Configure an equivalent policy for 443 if HTTPS traffic needs the same isolation.

Choosing the right fix

Observed result Most likely cause Fix to make Applies to
Changing the Host header changes the site or status Server-name selection mismatch Add the exact apex or www name, correct the listener, or fix DNS The affected address and port
No log entry in the second site’s log Another block handled the request Inspect nginx -T, enabled includes, and default-server behavior HTTP, HTTPS, or both depending on the listener
Error log shows an unexpected open() path Incorrect root, alias, or location precedence Correct the mapping and verify the file exists The selected server/location
Only missing application routes return 404 try_files ends in =404 Use the application’s named-location or upstream fallback The affected application location
HTTP succeeds but HTTPS fails Port 443 has a different or generic server block Configure the 443 block’s names, certificate, root, and locations independently HTTPS only
Both explicit-Host tests fail DNS, routing, wrong IP, disabled configuration, or missing files Work through DNS, enabled includes, paths, permissions, and logs in order Potentially all traffic

Common mistakes to avoid

  • Editing only sites-available: an unlinked file is not active on Debian or Ubuntu.
  • Testing only by IP: the IP becomes the Host value and commonly selects the default block.
  • Adding server_name _; without default_server: the underscore is not a magic wildcard.
  • Copying the port-80 block to port 443 without checking it: HTTPS has independent selection and content directives.
  • Deleting try_files to hide a 404: this can expose directory behavior or break application routing instead of fixing the mapping.
  • Reloading without nginx -t: a syntax error prevents the intended configuration from loading.
  • Assuming a valid file proves valid delivery: DNS, Host matching, directory traversal, and location precedence must all be correct.

Frequently Asked Questions

Why does the first NGINX domain work but the second returns 404?

The request may not match the second block’s server_name, so NGINX sends it to the default server for that address and port. It can also match correctly but point through root, alias, or try_files to a missing path. Test with an explicit Host header and inspect nginx -T to distinguish the two cases.

How can I prove which server block handled a request?

Run curl -i -H 'Host: second.example' http://SERVER_IP/, then repeat with the other hostname and watch the access and error logs. A per-site access log with Host or server fields is especially useful; if the second site’s log receives no entry, another block likely handled the request.

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

Why does testing the server by IP show the wrong website?

The IP address becomes the Host value, which usually does not match the domain’s server_name. NGINX then uses the default block. Supply the intended Host header for HTTP or use curl --resolve for HTTPS.

Why does HTTP work while HTTPS still returns 404?

Port 80 and port 443 have independent server-selection contexts. The 443 block may have a generic certificate server, different names, a different root, or different locations and try_files rules. Inspect and test the 443 configuration separately.

Does server_name _; create a catch-all server?

No. The underscore has no special wildcard behavior. Unmatched requests go to the server marked default_server on the relevant listen directive. A deliberate catch-all commonly uses both listen 80 default_server; and server_name _;.

What does a 404 from try_files $uri $uri/ =404; mean?

It means NGINX checked the candidate URI as a file and directory, found neither, and then followed the explicit =404 fallback. That is correct for a static site. Application routes usually need the framework’s documented named-location or upstream fallback instead.

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

Is a file in sites-available automatically active?

Not on Debian or Ubuntu. The file must be linked into /etc/nginx/sites-enabled/ or included by the main configuration. Confirm the live setup with nginx -T rather than relying on the file’s presence.

Can DNS cause an NGINX 404 even when the server block is correct?

Yes. If the apex or www record points to another server, load balancer, or unreachable address, the request never reaches this NGINX instance. Check each name with dig +short and compare the result with the address receiving traffic.

The Bottom Line

Prove the selected server block with an explicit Host test and nginx -T, then verify DNS, the enabled configuration, filesystem mapping, and logs. Treat port 80 and port 443 as separate configurations, and reload only after nginx -t succeeds.

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.

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