Skip to content

Generated nginx config returns 404 for /favicon.ico and /robots.txt while streaming file contents #1684

@futzlarson

Description

@futzlarson

Summary

On current Herd (1.28.0, macOS), the generated per-site nginx config returns HTTP 404 for /favicon.ico and /robots.txt while still streaming the correct file bytes from the site's public/ directory. Browsers honor the 404 and refuse to render the favicon; other static assets in public/ serve fine (200).

Environment

  • Herd 1.28.0
  • macOS (Darwin 25.4.0)
  • Laravel 11 site, parked normally
  • Site doc root via Herd is the project folder; favicon and robots.txt both live in public/

Reproduction

  1. herd park a Laravel 11 project that has public/favicon.ico and public/robots.txt.
  2. Visit https://<site>.test/favicon.ico.
  3. Observe response: status 404, content-type: image/x-icon, content-length matching the actual file size.
  4. Any other static asset in public/ (e.g. public/curitics.png) returns 200.

Verified with:

curl -sI https://care-management.test/favicon.ico -k
# HTTP/2 404
# content-type: image/x-icon
# content-length: 15086

Root cause

The generated config at ~/Library/Application Support/Herd/config/valet/Nginx/<site>.test contains:

server {
    ...
    root /;
    ...
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }
    ...
    error_page 404 "/Applications/Herd.app/Contents/Resources/valet/server.php";
}

The two location = blocks capture the request but contain no try_files, alias, or fastcgi_pass. With server-level root /, nginx looks for the file at filesystem root, fails, and emits 404. The error_page 404 directive then invokes Valet's server.php, which correctly serves the bytes from the site's public/ folder — but the 404 status is already set and server.php does not override it to 200 for this path, so browsers discard the body.

Other static files in public/ are unaffected because they hit the location / block which rewrites to server.php directly (no prior 404 set).

Workaround

Removing the two empty location = blocks from both server blocks (ports 443 and 60) in the generated config and running herd restart restores 200 responses. This edit is lost on any regeneration.

Suggested fix

Either:

  • Drop the empty location = /favicon.ico / location = /robots.txt blocks from the template — they no longer serve their original purpose (log silencing) because the requests already route through server.php cleanly without them.
  • Or point both blocks at server.php explicitly:
    location = /favicon.ico {
        access_log off;
        log_not_found off;
        try_files $uri /Applications/Herd.app/Contents/Resources/valet/server.php;
    }

Happy to provide additional diagnostic info.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions