NGINX Location Directive 404 Error: Static Image Expiration Configuration Fix


3 views

When configuring NGINX for static content with expiration headers, many developers encounter 404 errors due to improper root path handling in location blocks. The issue stems from how NGINX processes the root directive within nested location contexts.

Your original configuration has two critical issues:

location /images {
    expires 1y;
    root /srv/www/static/images;  # This is problematic
}

The root directive inside location /images changes the document root for this location, making NGINX look for files at:

/srv/www/static/images/images/screenshots/something.png

Notice the duplicate images path? That's why you're getting 404 errors.

Here are two proper ways to configure this:

Option 1: Single Root with Location Prefix

server {
    listen 80;
    server_name static.*;

    root /srv/www/static;  # Define root once at server level
    
    location / {
        deny all;
    }

    location /images {
        expires 1y;
        log_not_found off;
        # No root needed here - inherits from server
    }
}

Option 2: Alias Directive for Special Cases

server {
    listen 80;
    server_name static.*;

    location / {
        root /srv/www/static;
        deny all;
    }

    location /images/ {
        expires 1y;
        log_not_found off;
        alias /srv/www/static/images/;  # Note trailing slash
    }
}
  • root appends the location path to the root path
  • alias replaces the location path with the alias path
  • Always include trailing slashes in alias paths
  • root is generally preferred for most cases

After making changes, always:

nginx -t  # Test configuration
systemctl reload nginx  # Apply changes

Check headers with:

curl -I http://static.example.com/images/test.jpg

For optimal static content delivery, consider adding these directives:

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 1y;
    add_header Cache-Control "public, no-transform";
    access_log off;
    log_not_found off;
}

When setting up NGINX to serve static content with custom cache headers, many developers encounter 404 errors specifically when trying to configure separate location blocks for images. The issue typically manifests when:

  • Files exist in the correct directory path
  • Basic root configuration works without location blocks
  • Custom location blocks return 404 errors unexpectedly

The primary issue in the original configuration comes from misunderstanding how NGINX's root directive works within location blocks. When you specify:

location /images {
    root /srv/www/static/images;
}

NGINX will actually look for files at /srv/www/static/images/images/... because the location path gets appended to the root path.

Here are two working solutions:

Option 1: Use alias instead of root

location /images {
    alias /srv/www/static/images;
    expires 1y;
    log_not_found off;
}

Option 2: Proper root directive structure

location /images {
    root /srv/www/static;
    expires 1y;
    log_not_found off;
}

When working with static file serving in NGINX, keep these points in mind:

  • alias replaces the matched path segment
  • root appends the matched path segment
  • Always verify file permissions (nginx user needs read access)
  • Consider adding try_files for better error handling

Here's a production-tested configuration that handles static files with proper caching:

server {
    listen 80;
    server_name static.example.com;
    
    location /images/ {
        alias /srv/www/static/images/;
        expires 1y;
        access_log off;
        add_header Cache-Control "public";
        
        # Optional: Enable brotli/gzip for images if precompressed
        gzip_static on;
    }
    
    location / {
        root /srv/www/static;
        try_files $uri =404;
    }
}