keepcalculator

06 Numbers and Powers

Nginx 404 on Second Virtual Host: Fix It

Card No. 06·30433 · Updated · Standard formula, shown below

If your second Nginx server block returns a 404, the fix is almost always one of three things: the server_name doesn’t match the Host header you’re sending, the root or index directive points to a directory that doesn’t contain the expected file, or the configuration file wasn’t reloaded after you enabled the site. This article walks through each cause and shows you how to diagnose and resolve it.

Background: How Nginx Chooses a Server Block

Nginx uses the server_name directive to match an incoming request’s Host header to a specific server block. When you have multiple virtual hosts, Nginx evaluates them in the order they appear in the configuration. If no server_name matches, it falls back to the default server (often the first block or one marked default_server). If that default block doesn’t have a root pointing to your second site’s files, you’ll see a 404 — even though your second block looks correct.

This is a common misconception: a 404 doesn’t mean Nginx didn’t find your server block; it means the block that handled the request couldn’t find the file it was told to serve. So the first step is always to verify which block is actually handling your request.

Step-by-Step: Diagnose and Fix the 404

  1. Check the server_name match. Run curl -H "Host: yourdomain.com" http://127.0.0.1/ and see what response you get. If it’s a 404, Nginx is using a different block. Verify the server_name in your second block exactly matches the domain you’re using, including www if needed.
  2. Verify the root and index. Ensure the root directive points to the absolute path of your site’s files, and that an index file (like index.html or index.php) exists in that directory. Permissions matter too: the Nginx user (often www-data) must have read and execute permissions on all parent directories.
  3. Check the configuration syntax. Run nginx -t to test for errors. If it passes, reload Nginx with systemctl reload nginx (or nginx -s reload). A common mistake is editing the file but forgetting to reload — Nginx still uses the old configuration.
  4. Confirm the symlink in sites-enabled. If you’re using the sites-available/sites-enabled structure, make sure you created a symlink from sites-enabled to your file in sites-available. Without it, the block is never loaded.
  5. Check for conflicting default_server. If another block is marked default_server or appears first, it will handle requests that don’t match any server_name. Add a catch-all block or explicitly set your second block as the default if that’s what you intend.

Common Mistakes That Cause 404s

  • Typo in server_name: A missing dot or an extra character will cause a mismatch. Copy the domain from your browser’s address bar.
  • Root path wrong: Using a relative path like root /var/www/site2 when the files are actually in /var/www/site2/public will result in 404.
  • Missing index directive: If you have index index.html; but the file is named index.htm, Nginx will try to list the directory (if autoindex is on) or return 403/404. Add all possible index names.
  • Forgetting to reload: After editing any config file, you must reload Nginx. A simple nginx -s reload is enough.
  • Using a different port: If your second block listens on port 8080 but you’re accessing port 80, the request goes to a different server block entirely.

Comparing server_name and listen Directives

Many people confuse server_name with listen. The listen directive tells Nginx which IP:port to accept connections on, while server_name tells it which Host header to match. If both of your blocks listen on port 80, Nginx uses server_name to differentiate them. If you want to serve two different sites on the same port, you must have distinct server_name values. If you want to serve them on different ports (e.g., 80 and 8080), you can use the same server_name but different listen lines.

For example, a block listening on port 8080 with server_name example.com; will only respond to requests on that port. If you access http://example.com (port 80), it won’t match — it might hit another block or the default, yielding a 404.

How to Choose the Right Root and Index

The root directive defines the base directory for the site. When a request comes in for /index.html, Nginx looks for $root/index.html. If you’re using a framework like Laravel or WordPress, the public files are often in a subdirectory like public or html. Set the root to that directory, not the project root. Similarly, the index directive lists the files Nginx tries when the request ends with a slash. For PHP sites, you’ll often need index index.php index.html; and a location ~ \.php$ block to handle them.

If you’re not sure what path your files are in, run ls -la /var/www/site2 to see the actual structure. Also check that the Nginx user has execute permission on the directories: chmod o+x /var/www/site2 (adjust as needed).

Advanced: Using Try_files and Location Blocks

Sometimes the 404 comes from a location block that doesn’t match. For example, if you have location / { try_files $uri $uri/ =404; }, and the file doesn’t exist, Nginx returns 404. This is correct behavior. But if you expected a rewrite to a front controller (like in Laravel or React), you should use try_files $uri $uri/ /index.php?$query_string;. This sends non-existent requests to the PHP script, which then handles routing.

Another common issue is a location block with a regex that accidentally matches your second site’s files. For instance, a location ~ \.php$ in the first server block might be inherited if you use a nested location incorrectly. Always test with nginx -t and use curl to see which block is actually serving.

Frequently Asked Questions

Why does my second server block return 404 even though the config looks fine?

The most likely reason is that Nginx isn’t using your second block at all. Check which block handles the request by looking at the Host header and the listen port. Use curl -I http://yourdomain.com and see if the response headers match what you expect. Also verify that the config file is actually loaded by running nginx -T and grepping for your server_name.

Should I put my second site in sites-available or directly in nginx.conf?

It’s best practice to use sites-available and create a symlink in sites-enabled. This keeps your config organized and makes it easy to enable/disable sites. However, you can also include the file directly in nginx.conf or in a separate file under /etc/nginx/conf.d/. The key is that Nginx must read the file — check the include directives in your main nginx.conf.

How do I make my second site the default if the domain doesn’t match?

Add the default_server flag to the listen directive in your second block, like listen 80 default_server;. This tells Nginx to use this block when no other server_name matches. Note that you can only have one default server per IP:port combination.

Why does my second site work on localhost but not on the domain?

This usually means the server_name in your block doesn’t match the domain you’re typing. If you’re testing locally, you might have added an entry in /etc/hosts pointing the domain to 127.0.0.1. Make sure the server_name in your config matches that domain exactly. Also check that your DNS resolves correctly if you’re on a real domain.

Can I have two server blocks with the same server_name?

Yes, but only if they listen on different ports or IPs. If they both listen on the same port, Nginx will use the first one defined. To avoid confusion, give each block a unique server_name or use different listen directives. If you need to serve the same domain on both HTTP and HTTPS, you’ll have two blocks (one for port 80, one for 443) with the same server_name — that’s normal.

What does “404 Not Found” mean in Nginx logs?

It means Nginx couldn’t find the file specified by the URI in the root directory. Check the error log (/var/log/nginx/error.log) for the exact path it tried. Often it will show something like open() "/var/www/site2/index.html" failed (2: No such file or directory). That tells you exactly where to look.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →