Skip to content

How to Fix nginx 403 Forbidden Error

DodaTech 2 min read

In this tutorial, you'll learn about How to Fix nginx 403 Forbidden Error. We cover key concepts, practical examples, and best practices.

The Problem

You visit your site in a browser and see:

403 Forbidden
nginx/1.24.0

or the response header HTTP/1.1 403 Forbidden. nginx refuses to serve the requested resource.

Quick Fix

1. Verify the index file exists

By default nginx looks for index.html (or index.htm, index.php) in the root directory. If the file is missing, nginx returns 403 when directory listing is disabled.

# Check which files exist in the web root
ls -la /var/www/example.com/public/

# Create a default index if missing
echo "<h1>Site is live</h1>" > /var/www/example.com/public/index.html

You can configure the index directive in the server block:

server {
    root /var/www/example.com/public;
    index index.html index.php;
}

2. Fix file and directory permissions

nginx runs as the www-data user (Debian/Ubuntu) or nginx (RHEL). It needs read and execute permissions on the directory and read permission on files:

# Set directory permissions (read + execute)
chmod 755 /var/www/example.com/public

# Set file permissions (read)
chmod 644 /var/www/example.com/public/index.html

# Change ownership if needed
sudo chown -R www-data:www-data /var/www/example.com/public

Directories must have the execute bit set. Without it nginx cannot enter the directory to find files.

3. Check SELinux context (RHEL/CentOS/Fedora)

SELinux blocks nginx from accessing files outside its default paths:

# Check SELinux status
getenforce

# Temporarily test (disables SELinux until reboot)
sudo setenforce 0

# Restore correct context permanently
sudo restorecon -Rv /var/www/example.com/public

For a lasting fix, set the correct SELinux boolean:

sudo setsebool -P httpd_read_user_content 1

4. Check AppArmor (Ubuntu/Debian)

AppArmor can block nginx from reading files:

# Check nginx profile status
sudo aa-status | grep nginx

# Check audit log for denials
sudo journalctl -u apparmor | grep nginx

If AppArmor is blocking access, adjust the profile in /etc/apparmor.d/ or move the web root to a location nginx is allowed to access (e.g., /var/www/).

5. Disable directory listing explicitly

If you do not want directory listing, ensure autoindex is off:

server {
    location / {
        autoindex off;
    }
}

When autoindex is off and no index file exists, nginx returns 403 instead of listing the directory contents. Either add an index file or set autoindex on if you intend to show a file listing.

6. Check the nginx error log

The error log pinpoints the cause:

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

Look for lines containing *403" or directory index of "/var/www/..." is forbidden. The log tells you exactly which directory nginx cannot read.

Test Configuration Changes First

sudo nginx -t
# nginx: the configuration file syntax is ok
# nginx: configuration file test is successful
sudo systemctl reload nginx

Always run nginx -t before reloading the configuration. This validates syntax, checks file paths, and verifies that SSL certificates are accessible before applying changes.

Prevention

  • Use a consistent directory structure under /var/www/ with www-data ownership.
  • Set file permissions automatically in your deployment script.
  • Run sudo nginx -t to test the configuration before reloading.
  • Add SELinux policies to your provisioning playbook if you use RHEL-based systems.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro