Fix Nginx “stat() failed (13: Permission denied)”

Locate the inaccessible directory or security-policy denial, then grant the worker only the access required to serve the file.

Best practices
Illustration of server operations and request logs

This error means a filesystem metadata lookup was denied. For a normal file path on Linux, stat() needs search permission on each directory in the path; it does not require read permission on the final file merely to inspect its metadata. Serving the file later also requires read access.

Inspect the entire path

namei -l /var/www/site/uploads/avatar.jpg
ps aux | grep '[n]ginx: worker'

A representative permission chain might include:

drwxr-xr-x root   root   /
drwxr-xr-x root   root   /var
drwxr-xr-x root   root   /var/www
drwxr-x--- deploy deploy /var/www/site
drwxr-xr-x deploy deploy /var/www/site/uploads
-rw-r--r-- deploy deploy /var/www/site/uploads/avatar.jpg

If the worker is neither deploy nor a member of an allowed group, /var/www/site blocks traversal. Check ACLs and numeric identities as well as the displayed mode bits. A symlink target has its own path that also needs to be accessible.

Grant the intended access

For an intentionally public directory, chmod 755 /var/www/site allows traversal and listing by other users. If that is too broad, use a dedicated read-only group or an ACL instead. For example, on a system with POSIX ACL tools:

sudo setfacl -m u:www-data:--x /var/www/site
sudo setfacl -m u:www-data:--x /var/www/site/uploads
sudo setfacl -m u:www-data:r-- /var/www/site/uploads/avatar.jpg

This example grants access to that file through those directories without permitting directory listing. Substitute the actual worker user and verify all earlier parents. Plan inherited ACLs or deployment permissions separately for future files.

Adding the worker to a group is another option, but choose a group whose other permissions are also appropriate. Adding it to a deployment group may grant unintended write access elsewhere. Group-membership changes must reach newly started workers; a controlled service restart is one way to ensure that.

Handle home directories and SELinux deliberately

A site under /home/alice/site may be blocked by a private parent directory. Prefer a dedicated web-content location when appropriate. If it must stay there, grant narrowly scoped traversal instead of opening the entire home directory to all users.

On SELinux systems:

getenforce
ls -Z /var/www/site/
sudo ausearch -m AVC -ts recent
sudo restorecon -Rv /var/www/site/

restorecon restores labels defined by policy. For a nonstandard path without the required mapping, establish a persistent semanage fcontext rule first. Static content commonly uses httpd_sys_content_t; writable application data needs a policy suited to that use. Do not disable enforcement to hide an unexplained denial.

Retry the same URL and examine the same path in the error log. A successful reload does not demonstrate that filesystem access is fixed.

FAQ

Will chmod 777 solve it?

It may bypass a Unix mode-bit restriction while granting unnecessary writes, but it will not override SELinux, a broken path, or all mount restrictions. Fix the specific permission or policy instead.

What changes for a Docker bind mount?

Check the worker's numeric UID/GID inside the container, host directory permissions, mount flags, and labels. A different owner UID is not automatically a problem if group or other permissions already grant the needed access.

How is open() failed different?

Opening a file adds checks on the requested file access, but both open() and stat() can fail because a parent directory cannot be searched. The syscall name alone does not identify the exact blocked component. Use the full path, worker credentials, ACLs, and security-policy logs together.

References: Linux stat permissions, SELinux file-context configuration.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting