directory index of "/var/www/html/" is forbidden / open() "/var/www/html/index.html" failed (13: Permission denied)
#Две разные причины одного кода
Сообщение directory index of ... is forbidden значит, что в каталоге нет файла из списка index, а автоиндекс (autoindex) выключен: nginx не имеет права показывать содержимое. Сообщение failed (13: Permission denied) — nginx нашёл файл или каталог, но у его пользователя нет прав доступа. Эти случаи различаются по записи в error.log, поэтому начните с чтения журнала и не меняйте права наугад.
#Возможные причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Нет индексного файлаindex.html отсутствует. | directory index forbidden. | Создайте файл или укажите index. |
| Нет права x на каталог/home/user закрыт. | Permission denied (13). | chmod o+x или перенос сайта. |
| Неверный пользователь nginxВладелец файлов другой. | Файлы 600. | Выставьте 644. |
| SELinuxНеверный контекст. | Только на RHEL. | restorecon. |
| allow/denyОграничение по IP. | 403 для части клиентов. | Проверьте правила. |
| Файл пустой или сломанная ссылкаСимлинк на удалённое. | Не открывается. | Исправьте ссылку. |
#Порядок
- Прочитайте запись в error.logНа сервере через SSH откройте журнал Nginx командой
sudo tail -n 60 /var/log/nginx/error.logи повторите проблемный запрос. Если видите именноdirectory index of ... is forbidden, Nginx нашёл каталог, но не обнаружил разрешённый индексный файл. Если запись говоритPermission denied, это другой сценарий и нужно проверить права, а не индекс. - Если «directory index forbidden»: создайте индексный файл или включитеВ панели файлов сайта или по SSH проверьте наличие
index.php/index.htmlименно в каталоге из лога. Если страница должна открывать PHP, проверьте такжеfastcgi_passи обработчик.php. Не включайтеautoindex onна корне публичного сайта: это позволяет посетителям просматривать список файлов. Включение листинга допускается только для специально опубликованного каталога без секретных данных. - Проверьте директиву indexВ конфигурации нужного блока
serverпроверьте строкуindex index.php index.html;и фактическийrootс помощьюsudo nginx -T. Еслиindex.phpсуществует, но Nginx не передаёт PHP-запрос в FPM, исправляйте только связанный блокlocation. Сохраните копию конфигурации, затемsudo nginx -tдо применения. - Если «Permission denied»: определите пользователя nginxЕсли журнал указывает
Permission denied, найдите пользователя рабочих процессов поps -o user,cmd -C nginxили конфигурацииuser, затем выполнитеnamei -l /реальный/путь/index.php. На каждом родительском каталоге нужны права проходаx, а на файле — чтения для нужной учётной записи или группы; не назначайте777. - Проверьте права на каждый каталог пути: у пользователя nginx должно бытьПроверьте доступ к каталогам через безопасную команду
namei -lи просмотрите ACLgetfaclдля проблемного пути, если инструмент установлен. Исправляйте только конкретный каталог/файл, для которого доказано отсутствие права, с учётом владельца и процессов PHP-FPM; массовоеchmod -Rможет нарушить изоляцию виртуальных хостов. - Если сайт лежит в домашнем каталоге, добавьте право x на домашнюю папкуЕсли сайт лежит под
/home/пользователь, проверьте права прохода на/homeи домашнем каталоге; не делайте домашний каталог доступным всем ради сайта. Предпочтительнее отдельный корень сайта и доступ через ограниченную группу/ACL. Перед переносом сохраните конфигурацию и проверьте связанные пути загрузок и журналов. - Проверьте SELinux/AppArmorНа системах с SELinux прочитайте
sudo ausearch -m AVC -ts recentи контекстыls -Zдля реального пути, а на системах с AppArmor — соответствующие сообщения журнала. Исправляйте контекст по системной политике и только после подтверждения блокировки; отключать SELinux/AppArmor целиком не нужно. - Проверьте правила allow/deny в блокахНаконец проверьте у нужного
locationдирективыdeny,allow,auth_basicи внешние правила WAF. Выполнитеsudo nginx -t && sudo systemctl reload nginx; поcurl -I https://ваш-сайт/убедитесь, что нужный URL открывается и закрытые каталоги по-прежнему защищены. - Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
#Проверка после правок
Выполните запрос с командной строки: curl -I https://example.ru/ должен вернуть 200. Если по-прежнему 403, посмотрите последнюю запись журнала: она всегда указывает точную причину. Отдельно проверьте, не перехватывает ли запрос другой блок server (команда nginx -T | grep server_name) и не включена ли в блоке защита от доступа к скрытым файлам (location ~ /\. { deny all; }), которая блокирует и нужные пути вроде /.well-known/.