Resolve Nginx 403: directory index of "/usr/share/nginx/html/" is forbidden
When a new Nginx install returns 403 Forbidden and the error log shows:
directory index of "/usr/share/nginx/html/" is forbidden
it typically means Nginx reached the web root but found no default index file and directory listing is not allowed.
Verify an index file exists
If the document root (/usr/share/nginx/html by default on many distros) does not contain an index page (index.html, index.htm, or index.php), Nginx will deny access when you request the directory.
- To quickly test with PHP:
# Remove an existing placeholder (optional)
sudo rm -f /usr/share/nginx/html/index.html
# Create a minimal PHP index
echo "<?php phpinfo();" | sudo tee /usr/share/nginx/html/index.php >/dev/null
- Or, to test with a static page instead of PHP:
echo "<!doctype html><title>Nginx OK</title>" | sudo tee /usr/share/nginx/html/index.html >/dev/null
Ensure the server block points to the correct root
A common misconfiguration is omitting or mispointing the root directive. In your server block, explicitly set the root and default index files.
Example (adjust to your environment):
server {
listen 80;
server_name _;
location / {
root /usr/share/nginx/html;
index index.php index.html index.htm;
}
}
Using an absolute path for root avoids issues that can come from relying on the implicit html path.
Configure PHP handling (if you serve .php files)
If you intend to serve PHP, route .php requests to PHP-FPM. Make sure php-fpm is running (usually on 127.0.0.1:9000 or a Unix socket) and add a PHP location block.
Variant using TCP (127.0.0.1:9000):
location ~ \.php$ {
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
}
If your system uses a socket (comon on many distributions), switch fastcgi_pass to the socket path, for example:
fastcgi_pass unix:/run/php-fpm/www.sock;
Without a PHP handler, Nginx will not execute PHP files and may return 403/404 depending on other rules.
Reload or restart Nginx after changes
Always test configuration before applying:
sudo nginx -t
Reload to apply updates without dropping connections:
sudo nginx -s reload
# or
sudo service nginx reload
# or (systemd)
sudo systemctl reload nginx
Restart if needed:
sudo nginx -s stop && sudo nginx
# or
sudo systemctl restart nginx
Find where Nginx is installed
which nginx
# Example output:
# /usr/sbin/nginx
Check available Nginx options
nginx -h
# nginx version: nginx/1.10.2
# Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]
# -?,-h : this help
# -v : show version and exit
# -V : show version and configure options then exit
# -t : test configuration and exit
# -T : test configuration, dump it and exit
# -q : suppress non-error messages during configuration testing
# -s signal : send signal to a master process: stop, quit, reopen, reload
# -p prefix : set prefix path (default: /usr/share/nginx/)
# -c filename : set configuration file (default: /etc/nginx/nginx.conf)
# -g directives: set global directives out of configuration file