How to Fix nginx 403 Forbidden Error
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/withwww-dataownership. - Set file permissions automatically in your deployment script.
- Run
sudo nginx -tto 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