Fix Nginx 403 Forbidden: Wrong Permissions or Missing Index File

beginnerโšก Nginx2026-03-18| Nginx on Linux (Ubuntu 20.04/22.04, Debian, CentOS/RHEL 7/8)

Error Message

403 Forbidden
#nginx#permissions#403#directory#index

The Problem

You set up Nginx, open the browser, and get a blank 403 Forbidden. No stack trace, no helpful message. It almost always comes from one of two causes: Nginx can't read your files because of permission issues, or it's looking for an index file that isn't there.

Nine times out of ten, it happens right after a fresh server setup, after deploying files as root, or after changing the document root in your config.

Debug First: Read the Error Log

Don't touch anything yet. Check what Nginx is actually complaining about:

sudo tail -f /var/log/nginx/error.log

You'll see one of these two patterns:

# Case 1 โ€” permission denied reading a file
2024/01/15 10:23:45 [error] 1234#0: *1 open() "/var/www/html/index.html" failed (13: Permission denied)

# Case 2 โ€” no index file found in the directory
2024/01/15 10:23:45 [error] 1234#0: *1 directory index of "/var/www/html/" is forbidden

Different cause, different fix. Knowing which one you're dealing with saves you from chasing the wrong solution.

Fix 1: Wrong File or Directory Permissions

The Permission denied message means Nginx's worker process can't read your files. The worker runs as a specific user โ€” www-data on Debian/Ubuntu, nginx on CentOS/RHEL.

Check current permissions

ls -la /var/www/html/

Two numbers cover almost every case:

  • Directories: 755 โ€” must be executable (traversable)
  • Files: 644 โ€” readable by everyone, writable only by owner

Fix permissions recursively

# Fix all directories
sudo find /var/www/html -type d -exec chmod 755 {} \;

# Fix all files
sudo find /var/www/html -type f -exec chmod 644 {} \;

Fix ownership

Even with correct permissions, if the files are owned by root and Nginx runs as www-data, access still fails:

# Confirm which user the worker runs as
ps aux | grep nginx | grep worker

# Fix ownership (swap www-data for nginx on CentOS/RHEL)
sudo chown -R www-data:www-data /var/www/html/

Don't forget the parent directories โ€” Nginx needs execute permission on every directory in the path, not just the web root itself:

ls -la /var/
ls -la /var/www/

Fix 2: Missing Index File

Got directory index is forbidden? Nginx found the directory just fine โ€” it simply has no matching index file to serve, and it won't list directory contents because autoindex is off by default.

Check what index files Nginx expects

grep -r "index" /etc/nginx/sites-enabled/
# or check the http block default
grep "index" /etc/nginx/nginx.conf

Default is usually index index.html index.htm or index index.php index.html for PHP stacks.

Check if the file exists

ls -la /var/www/html/

If you only have a home.html but Nginx is looking for index.html, pick one of these fixes:

Option A โ€” Create or rename the index file:

mv /var/www/html/home.html /var/www/html/index.html

Option B โ€” Update your Nginx server block to include your actual filename:

server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    index home.html index.html index.htm;
}

Need directory listing instead?

server {
    location /files/ {
        autoindex on;
    }
}

Only enable this for non-sensitive paths. Never on your web root.

Fix 3: SELinux Blocking Access (CentOS/RHEL)

On RHEL-based systems, SELinux can silently block Nginx even when permissions and ownership look correct:

# Check audit log for Nginx denials
sudo audit2why -a | grep nginx

# Restore the correct SELinux context
sudo restorecon -Rv /var/www/html/

# Or set it manually
sudo chcon -Rt httpd_sys_content_t /var/www/html/

Verify the Fix

# Test the config, then reload without downtime
sudo nginx -t && sudo systemctl reload nginx

# Confirm the response
curl -I http://localhost
# Expected: HTTP/1.1 200 OK

# Check the error log is now clean
sudo tail -20 /var/log/nginx/error.log

Quick Checklist

  • Error log says Permission denied โ†’ fix chmod and chown
  • Error log says directory index is forbidden โ†’ add or point to the index file
  • Directories are 755, files are 644
  • Owner matches Nginx worker user (www-data or nginx)
  • Parent directories are also traversable
  • SELinux context set correctly on RHEL/CentOS

Tip: Calculate Permissions Without Guessing

If you ever need something other than 644 or 755 and aren't sure of the octal value, the Unix Permissions Calculator on ToolCraft is handy โ€” click the checkboxes for owner/group/other and it shows the number. Useful when setting up upload directories or CGI scripts with non-standard permission requirements.

Lessons Learned

Most 403 errors trace back to two habits: deploying files as root without fixing ownership afterward, and not checking whether the index filename matches the Nginx config. The error log is blunt about it โ€” it names the exact file and the exact reason. Start there, not from the browser message, and you'll usually have a fix in under two minutes.

Related Error Notes