Nginx 403 Forbidden Root Cause Checklist
Nginx 403 Forbidden means the server understood the request but refuses to serve it. This can come from permissions, missing index file, deny rules, wrong root path, directory listing rules or security restrictions.
Core principle
403 is an access decision. Find who is trying to access what path and why Nginx refuses it.
Checklist
- Identify the exact URL returning 403.
- Check Nginx error log for the reason.
- Check root path and file existence.
- Check index directive if directory is requested.
- Check file and parent directory permissions.
- Check Nginx user access.
- Check deny or allow rules.
- Check location rules.
- Check SELinux context on Red Hat systems.
- Apply the smallest fix and retest.
Reusable lesson
This applies to static files, WordPress uploads, admin paths, staging folders, downloads, custom apps and protected directories.
When to Use This Checklist
Use this checklist when Nginx returns 403 Forbidden for a page, folder, upload, asset, admin path or static file.
Required Tools
SSH access, Nginx error log, server block, file path, permissions, Nginx user, SELinux tools if relevant
Before You Start
Do not fix 403 by making everything world-writable. Identify the exact denied path first.
Structured Checklist Steps
- Identify URL.
- Read error log.
- Check root path.
- Check index file.
- Check permissions.
- Check Nginx user.
- Check deny rules.
- Check location rules.
- Check SELinux if relevant.
- Retest.
Verification Steps
- Error log reason is known.
- File path exists if expected.
- Nginx user can read required files.
- No unintended deny rule blocks access.
- 403 is resolved without unsafe permissions.
Rollback Plan
If permission changes create security risk or break the site, restore previous ownership and mode, then apply a narrower access fix.
Common Mistakes
- Using chmod 777.
- Ignoring parent directory execute permission.
- Wrong root path.
- Missing index file.
- Forgetting deny rules.
Related Commands
curl -I https://example.com/protected-path/
sudo tail -n 100 /var/log/nginx/error.log
grep -R "deny" /etc/nginx/sites-enabled/
ls -ld /var/www/example.com
ls -la /var/www/example.com
ps aux | grep nginx
sudo nginx -t