# Nginx 403 Forbidden Directory Access
You browse to a directory on your Nginx server and get a 403 Forbidden response. The error page is stark, and the logs confirm Nginx is actively denying access. This is one of the most common Nginx errors, and it almost always comes down to filesystem permissions, missing index files, or configuration restrictions.
Understanding the Error
A 403 Forbidden means Nginx understood the request but refuses to authorize it. Unlike a 404 where the resource doesn't exist, the resource is there - Nginx just won't let you see it.
Check the Nginx error log for the real reason:
tail -f /var/log/nginx/error.logTypical log entries look like:
2026/04/04 10:15:32 [error] 1234#1234: *1 directory index of "/var/www/html/downloads/" is forbidden, client: 192.168.1.100, server: example.com, request: "GET /downloads/ HTTP/1.1"2026/04/04 10:16:45 [error] 1234#1234: *2 access forbidden by rule, client: 192.168.1.100, server: example.com, request: "GET /admin/ HTTP/1.1"Common Cause 1: Missing Index File
When you request a directory (like /downloads/), Nginx looks for an index file. If none exists and directory listing is disabled, you get 403.
Diagnosis:
```bash # Check if index file exists ls -la /var/www/html/downloads/
# Check Nginx index configuration grep -r "index" /etc/nginx/sites-enabled/ ```
The error log confirms this:
``
directory index of "/var/www/html/downloads/" is forbidden
Solution:
Option 1 - Add an index file:
``bash
# Create a simple index.html
echo "<h1>Downloads</h1>" > /var/www/html/downloads/index.html
Option 2 - Enable directory listing: ```nginx server { listen 80; server_name example.com;
location /downloads/ { autoindex on; autoindex_exact_size off; autoindex_localtime on; } } ```
Reload Nginx:
``bash
sudo nginx -t && sudo systemctl reload nginx
Common Cause 2: Filesystem Permission Denied
Nginx runs as a specific user (usually www-data or nginx). If that user can't read the files, you get 403.
Diagnosis:
```bash # Find which user Nginx runs as ps aux | grep nginx # or grep -r "user" /etc/nginx/nginx.conf
# Check permissions on the directory ls -la /var/www/html/downloads/
# Test if Nginx user can access the path sudo -u www-data ls /var/www/html/downloads/ ```
Typical error log:
``
2026/04/04 10:20:15 [error] 1234#1234: *3 open() "/var/www/html/downloads/" failed (13: Permission denied), client: 192.168.1.100
Solution:
```bash # Fix directory permissions (directories need execute permission to traverse) sudo chmod 755 /var/www/html/downloads/
# Fix file permissions (files need read permission) sudo chmod 644 /var/www/html/downloads/*
# Fix ownership if needed sudo chown -R www-data:www-data /var/www/html/downloads/ ```
For the entire web root: ```bash # Set directory permissions find /var/www/html -type d -exec chmod 755 {} \;
# Set file permissions find /var/www/html -type f -exec chmod 644 {} \; ```
Common Cause 3: Parent Directory Execute Permission
Even if the target directory has correct permissions, every parent directory must have execute permission for the Nginx user.
Diagnosis:
# Check each parent directory
namei -l /var/www/html/downloads/Output shows permission at each level:
``
f: /var/www/html/downloads/
drwxr-xr-x root root /
drwxr-xr-x root root var
drwxr-xr-x root root www
drwx------ someuser someuser html <-- Problem: no execute for others
drwxr-xr-x www-data www-data downloads
Solution:
# Fix the problematic parent directory
sudo chmod 755 /var/www/html/Common Cause 4: SELinux Restrictions (RHEL/CentOS)
On SELinux-enabled systems, even correct Unix permissions won't help if SELinux context is wrong.
Diagnosis:
```bash # Check SELinux status getenforce
# Check file context ls -Z /var/www/html/downloads/
# Check for SELinux denials ausearch -m AVC -ts recent | grep nginx ```
Solution:
```bash # Set correct SELinux context for web content sudo chcon -R -t httpd_sys_content_t /var/www/html/downloads/
# For directories that need write access sudo chcon -R -t httpd_sys_rw_content_t /var/www/html/uploads/
# Make changes permanent sudo restorecon -R /var/www/html/ ```
Or temporarily disable SELinux to test:
``bash
sudo setenforce 0
Common Cause 5: Nginx Configuration Restrictions
Check for deny directives or missing allow rules.
Diagnosis:
```nginx # Check for access restrictions grep -r "deny|allow" /etc/nginx/
# Example problematic config location /admin/ { allow 10.0.0.0/8; deny all; # This denies everyone outside 10.x.x.x } ```
Solution:
Update the access rules:
``nginx
location /admin/ {
allow 192.168.1.0/24; # Your network
allow 10.0.0.0/8; # Internal network
deny all;
}
Common Cause 6: Alias Directive Issues
When using alias, the trailing slash matters.
Problematic config:
``nginx
location /images {
alias /var/www/html/images; # Missing trailing slash
}
Solution:
``nginx
location /images/ {
alias /var/www/html/images/; # Both have trailing slashes
}
Or use root instead:
``nginx
location /images/ {
root /var/www/html;
}
Verification Steps
- 1.Test Nginx configuration:
- 2.```bash
- 3.sudo nginx -t
- 4.
` - 5.Reload Nginx:
- 6.```bash
- 7.sudo systemctl reload nginx
- 8.
` - 9.Test access:
- 10.```bash
- 11.curl -I http://localhost/downloads/
- 12.
` - 13.Monitor logs:
- 14.```bash
- 15.tail -f /var/log/nginx/error.log
- 16.
`
Quick Reference
| Error Log Message | Cause | Solution |
|---|---|---|
directory index ... is forbidden | No index file, autoindex off | Add index.html or enable autoindex |
Permission denied | Filesystem permissions | chmod/chown files and directories |
access forbidden by rule | Nginx allow/deny rules | Update access control directives |
13: Permission denied | SELinux or filesystem | Check SELinux context or chmod |
open() ... failed (13: ...) | Execute permission missing | chmod +x on parent directories |
The 403 Forbidden error is almost always about permissions - either filesystem, SELinux, or Nginx configuration. Start with the error log, identify the specific denial reason, and apply the appropriate fix.