Команды Диагностика VPS Хостинг vs VPS SSL Tools Email OpenSSL
502 Bad Gateway
504 Gateway Timeout
500 Internal Server Error
403 Forbidden
Почта
SSL
БД
DNS

502 Bad Gateway

Nginx получил неверный ответ от upstream-сервера (PHP-FPM, Node.js, proxy). Бэкенд недоступен, упал или возвращает некорректный HTTP-ответ. Чаще всего встречается в связке Nginx + PHP-FPM.

1
Проверить статус PHP-FPM / бэкенда
Цель: Убедиться что PHP-FPM (или другой бэкенд) запущен. Это самая частая причина 502.
systemctl status php8.2-fpm systemctl status php8.1-fpm ps aux | grep php-fpm | grep -v grep
Если видите active (running) — переходите к шагу 2. Если failed/inactive — переходите к шагу 3.
2
Проверить логи ошибок Nginx
Цель: Найти точную причину 502 в логах Nginx. Там будет написано что именно пошло не так: соединение拒绝了, upstream closed connection и т.д.
tail -50 /var/log/nginx/error.log | grep -i "502" tail -50 /var/log/nginx/error.log | grep -i "upstream" tail -50 /var/log/nginx/error.log | grep -i "connect()"
connect() failed (111: Connection refused) — бэкенд не слушает на указанном порту/сокете.
upstream closed prematurely — бэкенд упал во время обработки.
no live upstreams — все бэкенды в пуле нерабочие.
3
Проверить логи PHP-FPM
Цель: Узнать почему PHP-FPM упал или не работает. В логах могут быть ошибки сегментации, нехватка памяти, ошибки конфигурации.
tail -50 /var/log/php8.2-fpm.log journalctl -u php8.2-fpm --since "1 hour ago" --no-pager
Обратите внимание на: segfault, Out of memory, Address already in use, unable to bind.
4
Проверить сокет / порт PHP-FPM
Цель: Убедиться что Nginx и PHP-FPM используют одинаковый сокет/порт. Расхождение — частая причина 502 после обновления PHP.
grep "listen =" /etc/php/*/fpm/pool.d/www.conf grep "fastcgi_pass" /etc/nginx/sites-enabled/* ls -la /run/php/
Если Nginx настроен на php7.4-fpm.sock, а PHP-FPM слушает php8.2-fpm.sock — исправьте конфиг Nginx.
5
Проверить max_children — перегрузка
Цель: Проверить не достиг ли PHP-FPM лимита дочерних процессов. Когда все worker'ы заняты — новые запросы получают 502.
grep "max_children" /etc/php/*/fpm/pool.d/www.conf ps aux | grep php-fpm | grep -c pool grep "max children reached" /var/log/php8.2-fpm.log | tail -5
Если max children reached встречается в логах — увеличьте pm.max_children. Формула: RAM_в_MB / 50 = примерное кол-во процессов. Для 2GB RAM: pm.max_children = 40.
6
Перезапуск и проверка
Цель: Применить исправления и проверить что 502 ушла.
systemctl restart php8.2-fpm nginx -t systemctl reload nginx curl -sI https://example.com | head -1
Если HTTP/1.1 200 — проблема решена. Если всё ещё 502 — проверьте логи PHP приложения (laravel.log, wordpress debug и т.д.).

Частые причины 502

  • PHP-FPM остановлен или crashed
  • Несовпадение сокета в Nginx и PHP-FPM (после обновления PHP)
  • pm.max_children слишком мал — все worker'ы заняты
  • Нехватка RAM — OOM Killer убил PHP-FPM
  • PHP скрипт использует слишком много памяти и worker падает
  • Firewall блокирует соединение между Nginx и бэкендом

504 Gateway Timeout

Nginx дождался ответа от бэкенда, но тот не уложился в отведённое время. Бэкенд работает, но слишком медленно. Типично для тяжёлых запросов: импорт, экспорт, сложные SQL-запросы, медленные API.

1
Найти таймаут в логах Nginx
Цель: Подтвердить что это именно таймаут и узнать какой URL вызывает проблему.
grep "timed out" /var/log/nginx/error.log | tail -10 grep "upstream timed out" /var/log/nginx/error.log | tail -10
В логе будет видно какой URL вызвал таймаут и какой upstream не ответил. Запомните URL для следующих шагов.
2
Проверить долгие SQL-запросы
Цель: Часто 504 вызван медленным SQL запросом. Нужно найти и оптимизировать его.
mysqladmin -u root -p processlist mysql -u root -p -e "SHOW FULL PROCESSLIST;"
Запросы со статусом Sending data или COPY to tmp table длящиеся более 30 секунд — кандидаты на оптимизацию. Убейте: KILL query_id;
3
Увеличить таймауты Nginx
Цель: Если запрос легитимно долгий (импорт данных, генерация отчёта) — увеличьте таймаут Nginx.
# Добавить в server или location блок Nginx: proxy_read_timeout 300s; proxy_send_timeout 300s; fastcgi_read_timeout 300s; fastcgi_send_timeout 300s;
nginx -t systemctl reload nginx
Увеличение таймаута — временное решение. Найдите и оптимизируйте медленный запрос.
4
Увеличить лимиты PHP
Цель: PHP тоже имеет свой лимит времени выполнения. Если Nginx ждёт 300с, а PHP останавливается через 30с — будет 504.
grep "max_execution_time" /etc/php/8.2/fpm/php.ini grep "request_terminate_timeout" /etc/php/8.2/fpm/pool.d/www.conf
systemctl restart php8.2-fpm
5
Проверить нагрузку на сервер
Цель: Если сервер перегружен (CPU 100%, диск I/O bottleneck), даже быстрые запросы будут тормозить.
uptime top -bn1 | head -15 iostat -x 1 3 free -h
Если %iowait высокий — диск bottleneck. Если load average > кол-ва ядер — сервер перегружен.

Частые причины 504

  • Медленный SQL запрос без индексов
  • Блокировка таблиц в MySQL (LOCK WAIT)
  • Внешний API не отвечает (curl запрос из PHP)
  • PHP request_terminate_timeout слишком мал
  • Nginx proxy_read_timeout / fastcgi_read_timeout слишком мал
  • Сервер перегружен (CPU/disk I/O)

500 Internal Server Error

Сервер столкнулся с непредвиденной ошибкой. Это «универсальная» ошибка — причина может быть в коде PHP, конфигурации Nginx, .htaccess, правах доступа, нехватке памяти. Диагностика идёт через логи.

1
Логи Nginx — первая точка входа
Цель: Посмотреть что записал Nginx в момент ошибки 500.
tail -50 /var/log/nginx/error.log tail -f /var/log/nginx/error.log
Используйте tail -f и обновите страницу в браузере — увидите ошибку в реальном времени.
2
Логи PHP-FPM и PHP приложения
Цель: PHP-FPM часто пишет детали ошибки в свой лог. Также проверьте логи самого приложения.
tail -50 /var/log/php8.2-fpm.log # Laravel tail -50 /var/www/site/storage/logs/laravel.log # WordPress tail -50 /var/www/site/wp-content/debug.log # Symfony tail -50 /var/www/site/var/log/prod.log
3
Включить отображение ошибок PHP
Цель: Если логи молчат, временно включите отображение ошибок PHP для диагностики.
# Создать тестовый файл: cat > /var/www/site/info.php << 'EOF'
Обязательно отключите display_errors после диагностики! Это раскрывает внутреннюю информацию сервера.
4
Проверить .htaccess (Apache)
Цель: На Apache ошибка 500 часто вызвана синтаксической ошибкой в .htaccess.
# Переименовать .htaccess mv /var/www/site/.htaccess /var/www/site/.htaccess.bak # Проверить логи Apache tail -50 /var/log/apache2/error.log
Если после переименования .htaccess сайт заработал — проблема в нём. Восстановите и исправьте построчно.
5
Проверить права и владение файлов
Цель: PHP не может читать файлы с неправильными правами. Типичные правильные права: файлы 644, директории 755, владелец www-data.
# Исправить права: chown -R www-data:www-data /var/www/site find /var/www/site -type d -exec chmod 755 {} \; find /var/www/site -type f -exec chmod 644 {} \;
6
Проверить PHP модули и зависимости
Цель: После обновления PHP или миграции могут отсутствовать необходимые модули (mbstring, xml, curl и т.д.).
php -m | grep -E "mbstring|xml|curl|json|mysqli|pdo" # Установить недостающие apt install php8.2-mbstring php8.2-xml php8.2-curl php8.2-mysql systemctl restart php8.2-fpm

Частые причины 500

  • Синтаксическая ошибка в PHP коде (Parse error)
  • Отсутствует PHP модуль (mbstring, pdo, xml)
  • Неправильные права доступа к файлам
  • Ошибка в .htaccess (Apache)
  • Нехватка памяти: PHP Fatal error: Allowed memory size exhausted
  • Отсутствующие зависимости composer (vendor/)
  • Ошибка подключения к базе данных

403 Forbidden

Сервер понял запрос но отказал в доступе. Это не проблема авторизации (это было бы 401), а проблема прав. Сервер не разрешает доступ к ресурсу по конфигурации, правам файловой системы или правилам файрвола/WAF.

1
Проверить права доступа к файлам
Цель: Самая частая причина 403 — Nginx/Apache не может прочитать файл из-за прав.
ls -la /var/www/site/ ls -la /var/www/site/index.php # Проверить всю цепочку до корня: namei -l /var/www/site/index.php
namei -l покажет права каждого каталога в пути. Для доступа нужны r+x на КАЖДОМ каталоге в цепочке. Владелец файлов должен быть www-data (или тот, под которым работает веб-сервер).
2
Проверить конфиг Nginx — autoindex и deny
Цель: Nginx отдаёт 403 если нет index файла и autoindex выключен, либо есть правило deny.
# Проверить deny правила grep -rn "deny" /etc/nginx/sites-enabled/ grep -rn "autoindex" /etc/nginx/sites-enabled/
Если в директории нет index-файла и autoindex off — Nginx вернёт 403. Добавьте index файл или включите autoindex для листинга директорий.
3
Проверить SELinux / AppArmor
Цель: На CentOS/RHEL SELinux может блокировать доступ веб-сервера к файлам даже при правильных Unix-правах.
# Проверить статус SELinux getenforce # Посмотреть AVC denials ausearch -m AVC -ts recent # Исправить контекст файлов restorecon -Rv /var/www/
Если getenforce возвращает Enforcing — SELinux активен. Команда restorecon восстановит правильные контексты.
4
Проверить IP-блокировки и WAF
Цель: Ваш IP может быть заблокирован файрволом, Fail2ban, Cloudflare или WAF-правилами.
# Проверить свой IP curl -s ifconfig.me # Проверить Fail2ban fail2ban-client status nginx-http-auth # Разбанить свой IP fail2ban-client set sshd unbanip YOUR_IP
5
Проверить логи для точной причины
Цель: Логи точно скажут почему сервер вернул 403.
tail -20 /var/log/nginx/error.log | grep "403" tail -20 /var/log/nginx/access.log | grep "403"
directory index forbidden — нет index файла, autoindex off.
open() ... failed (13: Permission denied) — проблема с правами файловой системы.
access forbidden by rule — правило deny в конфиге Nginx.

Частые причины 403

  • Нет index файла и autoindex отключён
  • Неправильные права доступа (нет r+x для www-data)
  • Правило deny в конфиге Nginx
  • SELinux блокирует доступ (CentOS/RHEL)
  • IP заблокирован Fail2ban или файрволом
  • WAF-правило (Cloudflare, ModSecurity)
  • Файл принадлежит другому пользователю

Почта Письма не доходят / попадают в спам

Одна из самых частых проблем: контактные формы не отправляют письма, уведомления не доходят, или письма попадают в спам. Диагностика идёт от логов почты к DNS-записям.

1
Проверить логи почты
Цель: Узнать отправляет ли сервер письма и что происходит с ними.
tail -50 /var/log/mail.log grep "status=sent" /var/log/mail.log | tail -5 grep "status=bounced" /var/log/mail.log | tail -5 mailq
sent — доставлено. bounced — отклонено получателем (смотрите reason в логе). deferred — задержано (сервер получателя временно недоступен).
2
Проверить SPF, DKIM, DMARC записи
Цель: Без SPF/DKIM/DMARC письма почти гарантированно попадут в спам Gmail, Yahoo, Outlook.
dig example.com TXT | grep "v=spf1" dig mail._domainkey.example.com TXT dig _dmarc.example.com TXT
SPF обязателен: v=spf1 mx a ~all. DKIM — криптографическая подпись. DMARC — начните с p=none для мониторинга. Без этих трёх записей Gmail/Yahoo будут отклонять письма с 2024 года.
3
Проверить PTR (reverse DNS)
Цель: PTR запись должна совпадать с hostname сервера. Многие почтовые серверы отклоняют письма без PTR.
curl -s ifconfig.me dig -x YOUR_IP +short
PTR настраивается в панели хостинг-провайдера (не в DNS панели). На VPS: откройте панель управления сервером → Network/rDNS → установите PTR = hostname. PTR должен совпадать с hostname сервера.
4
Использовать внешний SMTP (рекомендуется)
Цель: Отправка через свой сервер — путь в спам. Используйте внешний SMTP: SendGrid, Mailgun, Amazon SES, SMTP хостинга.
# WordPress: плагин WP Mail SMTP # Подключить через SendGrid, Mailgun, Amazon SES # Или SMTP вашего хостинга (порт 587 с TLS)
Рекомендация: Для сайтов на VPS используйте внешний SMTP. Это решает 95% проблем с доставкой. SendGrid (100 писем/день бесплатно), Mailgun (5000/мес бесплатно), Amazon SES ($0.10 за 1000 писем).

Почему письма попадают в спам

  • Отсутствует SPF запись
  • Отсутствует DKIM подпись
  • Отсутствует DMARC запись
  • PTR запись не настроена или не совпадает с hostname
  • IP сервера в чёрном списке (Spamhaus, SORBS)
  • Отправка с динамического IP (residential)
  • Содержимое письма похоже на спам (ссылки, CAPS, вложения)
  • Отсутствует обратный адрес или он не совпадает с доменом

SSL Проблемы с SSL сертификатами

Сертификат истёк, mixed content, невалидный сертификат, HSTS блокирует доступ. Диагностика и быстрое восстановление.

1
Проверить срок действия сертификата
Цель: Узнать когда истекает сертификат и нужно ли срочное обновление.
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -dates
Если сертификат истёк — срочно обновите: certbot renew --force-renewal и systemctl reload nginx.
2
Срочное обновление истёкшего сертификата
Цель: Быстро восстановить HTTPS.
certbot renew --force-renewal nginx -t && systemctl reload nginx
Если certbot не может пройти валидацию — проверьте что порт 80 открыт и домен правильно резолвится на этот сервер. Cloudflare должен быть в режиме «DNS only» (не прокси) на время валидации.
3
Mixed content — сайт показывает «не защищён»
Цель: Найти и исправить HTTP-ресурсы на HTTPS-странице.
# WordPress — заменить URL в БД: wp search-replace "http://example.com" "https://example.com" --all-tables # Nginx — автоматический upgrade: add_header Content-Security-Policy "upgrade-insecure-requests;" always;
Откройте DevTools (F12) → Console — увидите все mixed content ошибки. Проверьте также внешние ресурсы: шрифты Google Fonts, CDN, API.
4
Настроить автообновление и мониторинг
Цель: Автоматизировать обновление и получать уведомления об истечении.
# Cron — автообновление дважды в день: 0 0,12 * * * certbot renew --quiet --post-hook "systemctl reload nginx" # Проверить cron: crontab -l

Частые проблемы с SSL

  • Сертификат истёк — certbot не смог автообновить
  • Mixed content — ресурсы загружаются по HTTP
  • Сертификат не покрывает www поддомен
  • Cloudflare проксирует и показывает свой сертификат
  • HSTS блокирует доступ после истечения сертификата
  • Цепочка сертификатов неполная (missing intermediate)

БД Ошибка подключения к базе данных

«Error establishing a database connection», «Too many connections», MySQL упал. Диагностика от базовых проверок к оптимизации.

1
Проверить статус MySQL
Цель: Убедиться что MySQL запущен и отвечает.
systemctl status mysql mysqladmin -u root -p ping dmesg | grep -i "oom\|kill" | tail -10
Если OOM Killer убил MySQL — увеличьте RAM, добавьте swap, уменьшите innodb_buffer_pool_size. Если MySQL не запускается — смотрите логи.
2
Проверить credentials и подключение
Цель: Убедиться что имя БД, пользователь и пароль правильные.
# Проверить wp-config.php: grep -E "DB_NAME|DB_USER|DB_PASSWORD|DB_HOST" /var/www/site/wp-config.php # Тест подключения: mysql -u db_user -p -h localhost db_name
3
Too many connections — увеличить лимит
Цель: Увеличить max_connections и найти что создаёт столько подключений.
# Проверить лимиты: SHOW VARIABLES LIKE 'max_connections'; SHOW STATUS LIKE 'Threads_connected'; # Увеличить: SET GLOBAL max_connections = 300;
Каждое подключение MySQL потребляет ~2-5MB RAM. max_connections = 300 = до 1.5GB RAM только на подключения. Используйте пул соединений (PGBouncer для PostgreSQL, ProxySQL для MySQL).
4
Таблицы повреждены — восстановить
Цель: Проверить и восстановить повреждённые таблицы.
# Проверить и восстановить: mysqlcheck -u root -p --check --all-databases mysqlcheck -u root -p --repair --all-databases # Для InnoDB: ALTER TABLE dbname.table_name FORCE;
Всегда делайте бэкап перед repair! Если таблица сильно повреждена — восстановите из бэкапа. Для InnoDB используйте ALTER TABLE ... FORCE вместо REPAIR TABLE.

Частые причины проблем с БД

  • MySQL упал из-за OOM Killer (нехватка RAM)
  • Неверные credentials в конфиге сайта
  • max_connections достигнут — новые подключения отклоняются
  • Таблица повреждена после abrupt shutdown
  • Диск заполнен — MySQL не может писать
  • Медленные запросы блокируют таблицу (LOCK WAIT)
  • InnoDB buffer pool слишком мал — постоянные disk I/O

DNS DNS проблемы

Домен не резолвится, DNS propagation затянулся, сайт недоступен после смены DNS. Диагностика и ускорение propagation.

1
Проверить DNS записи
Цель: Проверить все типы DNS записей для домена.
dig example.com A +short dig example.com MX +short dig example.com NS +short dig example.com TXT +short # Через конкретный DNS: dig @8.8.8.8 example.com A +short
A — IPv4 адрес. AAAA — IPv6. MX — почтовые серверы. NS — серверы имён. TXT — SPF, DKIM, DMARC. CNAME — алиас.
2
Проверить DNS propagation
Цель: Узнать распространились ли изменения DNS по всему миру.
# Проверить TTL: dig example.com A +noall +answer # У разных провайдеров: dig @8.8.8.8 example.com A +short dig @1.1.1.1 example.com A +short
DNS propagation занимает время = TTL старой записи. Если TTL был 86400 (24 часа) — ждите до 24 часов. Перед сменой DNS установите TTL на 300 (5 минут) за 24 часа до изменения.
3
Очистить локальный DNS кеш
Цель: Сбросить кеш на сервере и локальном компьютере.
# Linux (systemd-resolved): sudo systemd-resolve --flush-caches # macOS: sudo dscacheutil -flushcache # Windows: ipconfig /flushdns

Частые DNS проблемы

  • DNS propagation ещё не завершена (ждите TTL)
  • NS серверы указаны неправильно у регистратора
  • A запись указывает на старый IP сервера
  • Отсутствует www CNAME запись
  • MX записи отсутствуют — почта не работает
  • Cloudflare проксирует (оранжевый облако) — валидация SSL не проходит
  • Локальный DNS кеш показывает старые данные