PQ
PQ.Hosting

Валюта

Ошибка 404 в Nginx: причины и пошаговое устранение — root, try_files, права, редиректы

Автор
PQ
04 марта 2026
4 мин чтения
706 просмотров
Ошибка 404 в Nginx: причины и пошаговое устранение — root, try_files, права, редиректы

Перезапустили сервер — и всё. Сайт молчит, браузер показывает белую страницу с цифрами «404». Или другая история: переехали на новый VPS, перенесли файлы, запустили Nginx — работает половина сайта, вторая половина в 404. Обе ситуации лечатся за пять минут. Но только если смотреть в правильное место.

Первым делом — error.log

Прежде чем что-то трогать в конфиге — открыть лог. Nginx уже знает в чём дело и написал об этом:

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

Строка вида:

open() "/var/www/html/about" failed (2: No such file or directory)

говорит всё: сервер полез за файлом about по пути /var/www/html/ — и не нашёл. Половина диагностики уже сделана.

Если виртуальные хосты с раздельными логами:

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

Неверный путь — и сервер слепнет

На VPS чаще всего виновата директива root. Одна буква не там — и Nginx ищет файлы в несуществующей папке:

sudo nano /etc/nginx/sites-available/yourdomain.com

Убедиться что директория вообще существует:

ls -la /var/www/mysite/public

Директория есть, 404 остаётся? Дело в правах. Nginx на Debian и Ubuntu работает от имени www-data, и если папка принадлежит другому пользователю — сервер просто не видит содержимое:

sudo chown -R www-data:www-data /var/www/mysite
sudo chmod -R 755 /var/www/mysite

SPA и CMS: почему вложенные маршруты дают 404

Страница / открывается, /catalog/item — нет. Знакомо? У React, Vue, Angular и большинства CMS (WordPress, Laravel) маршруты виртуальные: файла catalog/item на диске нет. Nginx честно об этом сообщает.

Решается одной директивой try_files. Без неё приложение просто не работает:

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

Для статической сборки React или Vue:

location / {
    try_files $uri $uri/ /index.html;
}

Логика такая: сначала ищем файл точно по пути, затем папку, затем — если ничего нет — отдаём точку входа. Без этого try_files любой переход по ссылке внутри SPA даёт 404.

Конфликт блоков location

Nginx читает location-блоки по своим правилам приоритетов, и бывает что один блок перехватывает запросы которые предназначались другому. Типичная жертва — API-роуты, которые попадают в блок статики:

location ~* \.(js|css|png|jpg)$ {
    expires 30d;
}

Если паттерн написан неаккуратно — он может «поймать» /api/users. Nginx полезет искать файл api/users на диске и вернёт 404.

Проверить синтаксис конфига:

sudo nginx -t

Проверить ответ по конкретному адресу:

curl -I https://yourdomain.com/api/users

PHP-FPM: сокет не тот

Если сайт на PHP и 404 только на .php-файлах — скорее всего дело в сокете. Конфиг указывает один путь, реальный сокет лежит в другом месте:

location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

Посмотреть что реально лежит в папке:

ls /var/run/php/

Убедиться что PHP-FPM вообще работает:

sudo systemctl status php8.1-fpm

Несовпадение пути к сокету — одна из самых частых причин 404 после обновления PHP или переезда конфига с другого сервера.

Нет индексного файла в директории

Nginx не умеет «угадывать» что отдать если в папке нет индексного файла. Запрос на /about/ без index.html внутри — 404:

location / {
    index index.html index.php;
}

Для файловых серверов где нужен листинг:

location /downloads/ {
    autoindex on;
}

Своя страница вместо стандартного 404

Дефолтная страница Nginx с белым полем — не лучшее что можно показать посетителю. Плюс она отдаёт версию сервера, что лишняя информация для посторонних:

server {
    error_page 404 /404.html;

    location = /404.html {
        root /var/www/html;
        internal;
    }
}

internal здесь принципиален: он закрывает прямой доступ к файлу снаружи — страница отдаётся только как ошибка, не как обычный URL.

Если 404 приходит от бэкенда (Node.js, Python), а нужно показать свою страницу:

proxy_intercept_errors on;
error_page 404 /custom_404.html;

Редирект вместо 404 — правильное решение при переезде

Сайт переехал, структура URL изменилась. Правильный ответ здесь не «починить 404», а настроить 301. Поисковик обновит индекс, пользователь попадёт куда нужно:

location = /old-page {
    return 301 /new-page;
}

Массовый редирект по шаблону:

rewrite ^/category/(.*)$ /catalog/$1 permanent;

Применить правки без простоя

После изменений — сначала проверка:

sudo nginx -t

Если всё чисто:

sudo systemctl reload nginx

reload перечитывает конфиг не обрывая текущие соединения. Это важно для продакшна — restart прервёт активные запросы.

Что и где смотреть

Картина Куда идти
404 на все страницы сразу Директива root, существование папки
Главная открывается, вложенные нет try_files не настроен
Только .php файлы дают 404 Статус PHP-FPM, путь к сокету
После переезда на новый сервер Права на папку: chown, chmod
После редизайна со сменой URL 301-редиректы через rewrite
Первичная диагностика sudo tail -f /var/log/nginx/error.log
Проверить конфиг sudo nginx -t
Применить без простоя sudo systemctl reload nginx



Поделиться статьей

Похожие статьи