open() "/usr/share/nginx/html/static/app.css" failed (2: No such file or directory), client: 203.0.113.5
#Как nginx формирует путь
Для root nginx добавляет URI к указанному пути: root /var/www/site; location /static/ {} при запросе /static/app.css ищет /var/www/site/static/app.css. Для alias часть URI, совпавшая с location, заменяется на путь из alias: location /static/ { alias /var/www/assets/; } ищет /var/www/assets/app.css. Путаница между ними — самая частая причина 404 на статике. Сообщение в error.log содержит точный путь, который nginx пытался открыть, и этого достаточно, чтобы увидеть расхождение.
#Типичные причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Неверный rootУказан не тот каталог. | В логе другой путь. | Исправьте root. |
| Путаница root и aliasЛишний префикс в пути. | Путь содержит /static/static/. | Используйте alias или поправьте root. |
| Слэши в aliaslocation с / и alias без /. | Склеенные имена. | Слэши должны совпадать. |
| Регистр имёнApp.CSS и app.css. | Работает на Windows, не на Linux. | Приведите регистр. |
| Нет прав на каталогx для others. | Permission denied (13). | chmod/chown. |
| Регулярное выражение перехватывает запросlocation ~ \.php$ или ~* \.(css). | Статика уходит не туда. | Проверьте приоритет. |
#Порядок
- Откройте error.log и найдите путь в сообщении open() ..Подключитесь к серверу по SSH, выполните
sudo tail -n 50 /var/log/nginx/error.logи воспроизведите конкретный адрес статического файла в браузере. Скопируйте путь послеopen()и URL запроса: Nginx показывает файл, который он пытался открыть, — это позволяет отличить отсутствие файла от прав и неправильного правилаlocation. - Проверьте, существует ли такой файлПроверьте
ls -l "/фактический/путь/файла"с путём из error.log. Если файла нет, найдите его в каталоге сборки: возможно, не загружены файлы frontend или в HTML указан старый адрес. Если файл есть, дополнительно проверьте регистр имени и командойnamei -lдоступ к родительским каталогам. - Определите обработавший запрос location и путь к файлуВыполните
sudo nginx -T 2>&1 | grep -nE "server_name|root|alias|location", найдите нужный виртуальный хост. Приroot /var/www/site;Nginx прибавляет URI запроса к корню, а приaliasзаменяет совпадающую часть URI указанным каталогом; прочитайте правило целиком и сопоставьте рассчитанный путь со строкой из error.log. - Для alias проверьте совпадение завершающих слэшей в location и aliasЕсли используется
location /static/ { alias /srv/assets/; }, убедитесь, что завершающий слэш вlocationиaliasсогласован; запрос/static/app.cssдолжен вести на/srv/assets/app.css. Перед изменением скопируйте исходный блок и проверьте его на стенде. Не меняйте наroot, пока не рассчитан новый путь. - Проверьте регистр имён: на Linux App.css и app.cssНа Linux выполните
ls -laв реальном каталоге и сравните имя файла посимвольно:App.cssиapp.cssразличаются. Исправьте либо путь в HTML/сборке, либо имя файла, избегая переименования библиотек, на которые ссылаются другие страницы. При использовании CDN проверьте, обновилась ли версия ресурсов. - Проверьте права на файл и родительские каталогиЕсли файл существует, а журнал сообщает
Permission deniedвместоNo such file, проверьте процесс Nginx иnamei -l /путь/файл. У пользователя Nginx должны быть права прохода через каталоги и чтения файла; если используется ACL, дополнительно посмотритеgetfacl. Не применяйте массовыйchmodна всё дерево сайта. - Проверьте порядок location и приоритет регулярных выраженийПроверьте приоритет точного
location =, префиксных правил и регулярных выраженийlocation ~; специальное правило для.css/.jsможет перехватывать путь, отличный от ожидаемого/static/. Измените минимальный нужный блок и проверьтеsudo nginx -tпередreload. - Проверьте SELinux на RHEL-системахНа RHEL-подобных серверах с SELinux проверьте события
sudo ausearch -m AVC -ts recentи контексты каталогаls -Z. Если блокировка подтверждена, настройте правильный тип для веб-контента по политике системы. После изменений проверьтеcurl -Iдля того же URL и убедитесь в HTTP 200 и корректном содержимом. - Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
#Docker и проксирование
Если nginx работает в контейнере, путь в root относится к файловой системе контейнера, а не хоста. Убедитесь, что каталог смонтирован через volumes, а в контейнере виден нужный файл: docker exec nginx ls -l /usr/share/nginx/html/static/. При проксировании на приложение (proxy_pass) статика может обслуживаться самим приложением, и тогда 404 вернёт оно, а не nginx: проверьте заголовок Server в ответе.