Устранение распространенных ошибок Nginx: практическое руководство

Сталкиваетесь с ошибками Nginx? Это практическое руководство поможет вам диагностировать и устранять распространенные проблемы. Научитесь решать проблемы с конфигурацией, ошибки отказа в доступе, отказ в соединении, ошибки шлюза 502/504 и другие. Мы предоставляем понятные объяснения, действенные решения и основные команды Nginx, чтобы ваш сайт оставался доступным и работал без сбоев.

Устранение распространенных ошибок Nginx: практическое руководство

Устранение распространенных ошибок Nginx становится намного проще, когда вы перестаете рассматривать код состояния как единственную проблему. 502 может быть вызван упавшим приложением, неправильным путем к сокету или бэкендом, вернувшим некорректные заголовки. 403 может быть связан с правами доступа к файлам, отсутствующим индексным файлом или правилом запрета, которое сработало шире, чем вы ожидали.

Начните с доказательств: журнал ошибок, журнал доступа, nginx -t и журналы бэкенда, если Nginx выступает в роли прокси для приложения. Гадать, глядя только на страницу браузера, — пустая трата времени.

Начните с быстрых проверок

Выполните эти команды перед изменением конфигурации:

sudo nginx -t
sudo systemctl status nginx --no-pager
sudo tail -n 80 /var/log/nginx/error.log
sudo tail -n 80 /var/log/nginx/access.log

nginx -t сообщает, может ли быть разобран конфигурационный файл. Статус службы показывает, запущен ли Nginx. Журналы показывают, что Nginx видел при обработке запроса.

Если проблема связана с одним URL, воспроизведите её с помощью curl, чтобы четко увидеть заголовки и статус:

curl -I https://example.com/problem/path
curl -v https://example.com/problem/path

Если проблема возникает только для определенного имени хоста, укажите его:

curl -I -H 'Host: app.example.com' http://127.0.0.1/

Это отделяет маршрутизацию Nginx от поведения DNS, CDN и балансировщика нагрузки.

Nginx не запускается или не перезагружается

Ошибка запуска обычно связана с синтаксической ошибкой, дублирующейся директивой в неправильном контексте, отсутствующим файлом включения или проблемой с путем к сертификату.

Используйте:

sudo nginx -t
sudo journalctl -u nginx -n 100 --no-pager

Типичные сообщения говорят сами за себя:

  • unknown directive означает опечатку, неподдерживаемый модуль или директиву, размещенную в неправильной сборке Nginx.
  • directive is not allowed here означает, что директива находится в неправильном контексте, например, размещение директивы, предназначенной только для http, внутри server.
  • cannot load certificate означает, что путь неверен, файл отсутствует или права доступа не позволяют Nginx его прочитать.
  • bind() to 0.0.0.0:80 failed часто означает, что другой процесс уже использует этот порт.

Проверьте порты с помощью:

sudo ss -tulnp | grep ':80\|:443'

Не перезагружайте Nginx, пока nginx -t не пройдет успешно. Неудачная перезагрузка обычно оставляет старый рабочий процесс работающим, но неудачный перезапуск может привести к недоступности сайта.

(13: Permission denied) и 403 Forbidden

Permission denied появляется в журнале ошибок, когда пользователь рабочего процесса Nginx не может прочитать файл или получить доступ к каталогу. Браузер может показать 403 Forbidden.

Сначала найдите пользователя рабочего процесса:

grep -R '^user ' /etc/nginx/nginx.conf

В Debian и Ubuntu это часто www-data. В системах, совместимых с RHEL, это часто nginx.

Для статического корня, такого как /var/www/html, Nginx требуется право выполнения для каждой родительской директории и право чтения для файла:

sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;

Избегайте рефлекторного выполнения chown -R www-data:www-data для каталогов приложений. Это может заставить ошибку исчезнуть, но при этом предоставит веб-серверу права на запись, которые ему не нужны. Более безопасный подход — сохранить отдельные права владельца развертывания и предоставить Nginx доступ только на чтение.

Если права доступа выглядят нормально, проверьте, не является ли запрос к каталогу без индексного файла:

location / {
    root /var/www/html;
    index index.html index.htm;
}

Если в /docs/ нет index.html и autoindex выключен, Nginx возвращает 403. Это корректное поведение.

SELinux также может вызывать ошибки, связанные с правами доступа, в системах семейства RHEL. Если права доступа к файлам верны, но Nginx все равно не может прочитать файл или выполнить проксирование, проверьте журналы аудита перед отключением SELinux:

sudo ausearch -m avc -ts recent

(111: Connection refused) и 502 Bad Gateway

Connection refused означает, что Nginx попытался подключиться к вышестоящему серверу, и тот активно отказал в соединении. Возможно, приложение не работает, прослушивает другой адрес или использует путь к сокету, который не существует.

Для этого прокси:

location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

проверьте:

sudo ss -tulnp | grep 3000
curl -I http://127.0.0.1:3000
sudo systemctl status your-app --no-pager

Если Nginx использует Unix-сокет, проверьте файл сокета:

ls -l /run/gunicorn/app.sock

Пользователь рабочего процесса должен иметь права на чтение и запись сокета.

502 Bad Gateway — более широкая ошибка. Nginx достиг вышестоящего сервера, но ответ был недействительным, неполным, закрыт слишком рано или не соответствовал ожиданиям Nginx. Проверьте журналы приложения на ту же временную метку, что и ошибка Nginx. Совпадение временных меток имеет значение; в противном случае вы будете искать вчерашнее исключение.

Для PHP-FPM убедитесь, что fastcgi_pass соответствует настроенному сокету или порту пула. Например:

fastcgi_pass unix:/run/php/php8.3-fpm.sock;

Затем проверьте:

sudo systemctl status php8.3-fpm --no-pager
ls -l /run/php/php8.3-fpm.sock

504 Gateway Timeout

504 означает, что Nginx ждал ответа от вышестоящего сервера и не получил его вовремя. Увеличение таймаутов может быть оправдано для отчетов, импорта или медленных административных операций, но это не должно быть единственным решением для публичной конечной точки, которая медленно работает при каждом запросе.

location /api/reports/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_connect_timeout 10s;
    proxy_send_timeout 60s;
    proxy_read_timeout 180s;
}

Затем посмотрите на время выполнения бэкенда. Добавьте время выполнения вышестоящего сервера в журналы доступа, если у вас его еще нет:

log_format proxy_timing '$remote_addr "$request" $status '
                        'request_time=$request_time '
                        'upstream_time=$upstream_response_time';

Если $upstream_response_time высокое, вероятно, проблема в приложении или базе данных. Если Nginx показывает таймауты, но журналы приложения говорят, что оно ответило быстро, проверьте сетевые переходы, контейнерную сеть, разрешение DNS внутри хоста или балансировщик нагрузки между Nginx и приложением.

413 Request Entity Too Large

413 обычно прямолинейна: тело запроса больше, чем позволяет Nginx. Загрузки, большие JSON-полезные нагрузки и отправка форм могут вызвать это.

Установите client_max_body_size в самом узком подходящем месте:

server {
    server_name example.com;

    location /upload/ {
        client_max_body_size 100M;
        proxy_pass http://127.0.0.1:3000;
    }
}

Установка огромного глобального лимита редко бывает хорошей идеей. Большинству маршрутов это не нужно, а увеличение допустимого размера тела увеличивает объем работы, который плохой клиент может навязать вашему стеку.

Ошибки SSL и сертификатов

Ошибки TLS часто выглядят по-разному в зависимости от того, где вы их замечаете. Nginx может не перезагружаться, браузеры могут предупреждать о сертификате, или клиенты могут не выполнить рукопожатие.

Проверьте даты сертификата:

openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -dates -subject -issuer

Проверьте, что представляет публичный сервис:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer

Если эти две команды показывают разные сертификаты, возможно, трафик обслуживается балансировщиком нагрузки, CDN или другим хостом.

400 Bad Request и проблемы с заголовками

400 обычно означает, что Nginx не принял синтаксис запроса. В реальных браузерах это встречается реже, но боты, старые клиенты, необычные прокси или слишком большие заголовки могут вызвать это.

Ищите сообщения, такие как client sent too large request header. Если легитимный SSO- или куки-файл приложения слишком велик, возможно, потребуется настроить параметры буфера заголовков. Относитесь к этому как к целевому исправлению, а не к первому ответу. Слишком большие куки часто лучше исправлять в приложении.

Практический порядок действий

Когда проблема с Nginx активна, используйте повторяемый порядок:

  1. Подтвердите точный URL, хост, код состояния и время.
  2. Проверьте nginx -t и статус службы.
  3. Найдите запрос в журнале доступа.
  4. Найдите ту же временную метку в журнале ошибок.
  5. Если используется прокси, проверьте статус и журналы вышестоящего сервиса.
  6. Протестируйте вышестоящий сервер напрямую с хоста Nginx.
  7. Внесите наименьшее изменение конфигурации, соответствующее доказательствам.
  8. Выполните nginx -t, перезагрузите и следите за журналами во время повторного тестирования.

Большинство проблем с Nginx становятся обычными, как только вы узнаете, где произошел сбой: до Nginx, внутри Nginx, между Nginx и вышестоящим сервером или внутри вышестоящего сервиса.