Nginx on Ubuntu Server throws 404 not found

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Nginx on Ubuntu Server Throws 404 Not Found: Debugging Laravel Routing Failures

As a senior developer, I’ve seen countless deployment headaches. When setting up a modern framework like Laravel behind a reverse proxy like Nginx on an Ubuntu server, it often seems straightforward. However, when you encounter intermittent 404 errors—especially after reboots or service restarts—it usually points to a subtle misconfiguration in path handling rather than a simple file permission issue.

The scenario you described—where the homepage loads but dynamic routes fail with 404s, and the error log indicates "No such file or directory"—is a classic symptom of Nginx failing to correctly interpret the request path relative to its defined root directory. Let’s dive deep into why this happens and how to fix it.

The Illusion of Permission Issues

You correctly attempted setting permissions using chown and chmod. While file ownership and read/write permissions are crucial for application execution (especially writing logs or cache files), they rarely cause a server-side routing error like a 404 inside the web server configuration. If Nginx cannot even resolve the path to the requested file on disk, permission issues become secondary to structural errors.

The fact that the error log shows: open() "/var/www/ozunimate/public/student/register" failed (2: No such file or directory) confirms that the problem lies in Nginx's mapping logic, not the PHP-FPM execution itself.

Deconstructing the Nginx Configuration

Let’s examine your provided configuration and see where the pathing might be breaking down.

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;
    root /var/www/foo-bar/public;  # <-- This is critical
    index index.php index.html index.htm;

    server_name 120.25.203.113;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri /index.php =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

The core directive is root /var/www/foo-bar/public;. This tells Nginx that everything requested must be resolved relative to this path. The try_files directive attempts to find the requested URI ($uri), then a directory ($uri/), and finally falls back to index.php.

If your application structure is slightly inconsistent, or if there are issues with symbolic links created during deployment (which often happens when moving code between environments), Nginx will fail this sequence, resulting in a 404.

The Solution: Verifying Path Structure and Symlinks

In a Laravel setup, the entire public-facing web root should be explicitly defined. Since you are trying to access /student/register, Nginx expects that path to exist immediately under the root directory.

Here is the recommended debugging process:

1. Verify Absolute Paths

Ensure that the actual file system structure exactly matches what Nginx expects. If your Laravel project root is /var/www/foo-bar, then everything must be correctly placed within that context. Use an absolute path check:

ls -ld /var/www/foo-bar/public/student/register

If this command fails, the file simply does not exist at that exact location, regardless of permissions. The fix is to ensure your deployment process (e.g., Git pull, Docker build, or manual copying) correctly places all files.

2. Review Symlinks and Ownership

Although you checked permissions, sometimes broken symbolic links can confuse the web server. Ensure that all necessary directories within /var/www/foo-bar/public are present and owned by the web user (www-data).

If you are deploying code following Laravel best practices, always ensure ownership is set correctly:

sudo chown -R www-data:www-data /var/www/foo-bar

3. Revalidate the try_files Logic

Your configuration for PHP handling looks mostly correct for standard Laravel setups. The issue is most likely upstream—the filesystem structure itself. When working with complex routing, remember that robust application frameworks like those found on laravelcompany.com rely heavily on clean, predictable file structures to function correctly under a reverse proxy.

Conclusion

The 404 error in this scenario is almost always a path resolution failure, not a permission denial. By moving past checking basic permissions and focusing instead on the precise relationship between your Nginx root directive and the actual physical directory structure where Laravel places its public assets, you will resolve this issue. Always treat the server configuration as a strict map of the filesystem; if the map is wrong, the requests will fail silently with 404s.