- Опубликовано: 30 июл 2026
- 29
Ошибка 500 после загрузки сайта: где искать причину до обращения в поддержку
Часть 10 из 14 · Серия «Хостинг без магии»
Проект перенесли на новый хостинг. Файлы на месте, база импортирована, домен подключён. Разработчик открывает сайт и вместо главной страницы видит:
500 Internal Server Error
Иногда браузер показывает просто белую страницу. Иногда главная открывается, но административная панель падает. Иногда сайт работал до обновления, а после git pull и composer install перестал отвечать.
Первая мысль — проблема на стороне хостинга.
Разработчик меняет версию PHP, выдаёт всем каталогам права 777, удаляет .htaccess, очищает кэш, снова загружает файлы и перезапускает Composer. После каждого действия страница обновляется — но ошибка остаётся.
Через час в поддержку отправляется сообщение:
Сайт не работает. Исправьте ошибку 500.
Такое обращение почти не содержит информации. Код 500 говорит лишь о том, что сервер не смог нормально завершить запрос. Настоящая причина может находиться в одной строке лога:
Failed opening required vendor/autoload.php
или:
SQLSTATE[HY000] [1045] Access denied for user
или:
Permission denied
Ошибка 500 — не диагноз. Это конверт, внутри которого лежит настоящее сообщение.
В этой статье разберём, как найти его самостоятельно: от первого HTTP-ответа и журналов до Composer, .env, базы данных, прав, кэшей и миграций.
Сначала определите, что именно сломалось
Фраза «сайт не работает» может описывать несколько разных ситуаций:
- домен вообще не открывается;
- соединение завершается по тайм-ауту;
- браузер сообщает об ошибке сертификата;
- сервер возвращает 403;
- сервер возвращает 404;
- сервер возвращает 500;
- сервер возвращает 502 или 503;
- HTML загружается, но нет CSS и JavaScript;
- главная страница работает, а остальные маршруты — нет;
- сайт открывается, но конкретное действие вызывает ошибку.
Эти проблемы находятся на разных уровнях и требуют разных проверок.
Упрощённая карта выглядит так:
| Симптом | Где чаще искать |
|---|---|
| Домен не найден | DNS |
| Ошибка сертификата | SSL и настройки домена |
| 403 Forbidden | Корневая папка, индексный файл, права или правила доступа |
| 404 Not Found | Маршрут, rewrite, Document Root или отсутствующий файл |
| 500 Internal Server Error | PHP, приложение, конфигурация, зависимости или права |
| 502 Bad Gateway | Связь веб-сервера с обработчиком приложения |
| 503 Service Unavailable | Режим обслуживания, перегрузка или временная недоступность |
| Сайт без CSS и JavaScript | Frontend-сборка, URL ресурсов или содержимое public/build |
Код 500 обычно означает, что запрос дошёл до серверной части, но при обработке произошёл сбой. Напротив, 502 чаще указывает на проблему связи веб-сервера с обработчиком, а 503 может появляться при обслуживании или временной недоступности приложения.
Зафиксируйте точный адрес и время
До любых изменений запишите:
Домен: example.com
URL: https://example.com/admin/orders
Время: 21 июля 2026, 10:42
Действие: открытие списка заказов
Результат: HTTP 500
Последнее изменение: composer install и миграции
Время важно, потому что большой журнал может содержать тысячи строк. Зная минуту возникновения ошибки, легче найти нужную запись.
Проверить HTTP-заголовки можно из консоли:
curl -I https://example.com/
Для адреса, который может перенаправлять запрос:
curl \
--location \
--silent \
--show-error \
--output /dev/null \
--write-out "%{http_code}\n" \
https://example.com/
Результат:
500
Это не объяснит причину, но подтвердит, какой ответ возвращает сервер без влияния кэша браузера.
Главное правило: сначала лог, потом исправление
Плохой порядок диагностики выглядит так:
ошибка 500
↓
chmod 777
↓
смена PHP
↓
удаление .htaccess
↓
переустановка vendor
↓
непонятно, что именно помогло или сломало ещё сильнее
Хороший порядок:
ошибка 500
↓
точная строка из лога
↓
проверка одной гипотезы
↓
одно изменение
↓
повторная проверка
Не изменяйте одновременно права, версию PHP, конфигурацию базы и структуру каталогов. После пяти случайных действий исходная причина может исчезнуть под четырьмя новыми.
Где искать настоящее сообщение об ошибке
У современного PHP-сайта может быть несколько журналов.
Журнал PHP и веб-сервера
В зависимости от панели и конфигурации он может называться:
error.log
php-error.log
php_errors.log
apache_error.log
В нём находятся ошибки, возникшие до полноценного запуска фреймворка:
- синтаксическая ошибка PHP;
- отсутствующий файл;
- неподдерживаемая функция;
- превышение памяти;
- ошибка загрузки расширения;
- некорректная директива
.htaccess; - невозможность открыть
vendor/autoload.php; - ошибка прав до инициализации приложения.
Пример:
PHP Fatal error:
Uncaught Error: Failed opening required
'/home/user/www/example.com/project/vendor/autoload.php'
В этом случае искать запись в Laravel-логе бессмысленно: фреймворк ещё не успел запуститься.
Лог Laravel
В типовой конфигурации Laravel записи сохраняются в:
storage/logs/laravel.log
или в файлы по датам:
storage/logs/laravel-2026-07-21.log
Посмотреть последние строки:
cd ~/www/example.com/project
tail -n 100 storage/logs/laravel.log
Следить за появлением новой ошибки в реальном времени:
tail -f storage/logs/laravel.log
После запуска команды нужно снова открыть проблемную страницу. Новая запись обычно появится внизу.
Laravel регистрирует исключения через настроенную систему логирования. При этом APP_DEBUG определяет, сколько сведений показывать посетителю, а не нужно ли вообще записывать ошибку. В production подробный debug должен оставаться выключенным, чтобы не раскрывать конфигурацию и другие чувствительные данные.
Лог Symfony
В Symfony расположение production-лога зависит от конфигурации Monolog.
В development-окружении часто используется:
var/log/dev.log
В production современные конфигурации могут отправлять журнал в STDERR. Если настроена запись в файл, это может быть, например:
var/log/prod.log
Поэтому сначала следует открыть:
config/packages/prod/monolog.yaml
и посмотреть, куда направлен обработчик логов. Symfony официально указывает, что production-вывод может идти в STDERR, а запись в var/log/prod.log должна быть настроена в обработчике отдельно.
Для файлового лога:
tail -n 100 var/log/prod.log
Если лог пустой
Пустой журнал не означает, что ошибки нет.
Возможные причины:
- приложение не успевает загрузиться;
- PHP не может записать лог;
- открыт не тот файл;
- production-лог отправляется в STDERR;
- ошибка находится в журнале веб-сервера;
- PHP настроен не записывать ошибки;
- запрос попадает в другой каталог или на другой сайт;
- приложение использует отдельный канал логирования;
- ошибка происходит до запуска Laravel или Symfony.
Проверьте даты изменения файлов:
find storage/logs \
-maxdepth 1 \
-type f \
-printf '%TY-%Tm-%Td %TH:%TM %p\n' \
2>/dev/null |
sort
Для Symfony:
find var/log \
-maxdepth 1 \
-type f \
-printf '%TY-%Tm-%Td %TH:%TM %p\n' \
2>/dev/null |
sort
Если файлы не меняются, переходите к журналу PHP и проверке прав.
Не включайте подробные ошибки для всех посетителей
Иногда для диагностики советуют установить:
APP_DEBUG=true
и оставить сайт в таком состоянии.
Это опасно.
Подробная страница исключения может показать:
- абсолютные пути;
- SQL-запросы;
- части конфигурации;
- имена сервисов;
- фрагменты входных данных;
- стек вызовов;
- сведения об установленных пакетах.
Laravel прямо рекомендует всегда устанавливать APP_DEBUG=false в production, поскольку включённый debug способен раскрыть чувствительные значения. PHP также разделяет показ ошибок и их запись: для рабочего сайта ошибки следует скрывать от посетителей, но сохранять в журнале.
Правильная схема:
display_errors = Off
log_errors = On
error_reporting = E_ALL
На виртуальном хостинге эти параметры обычно задаются в панели или управляются хостером.
Если нужно увидеть ошибку консольной команды, её можно временно вывести только в SSH-сессии:
php \
-d display_errors=1 \
-d display_startup_errors=1 \
-d error_reporting=-1 \
artisan about
Посетителям сайта такой вывод не показывается.
Шаг 1. Проверьте, запускается ли PHP вообще
Создайте в публичной директории временный файл:
<?php
echo 'PHP OK: ', PHP_VERSION;
Например:
project/public/php-check.php
Откройте:
https://example.com/php-check.php
Возможные результаты:
Появилась версия PHP
PHP OK: 8.4.12
Значит:
- домен направлен на этот каталог;
- веб-сервер видит файл;
- PHP-обработчик запускается;
- ошибка находится глубже — в приложении или его конфигурации.
Скачивается исходный PHP-файл
PHP не обрабатывается веб-сервером. Это уже проблема конфигурации сайта, а не Laravel или Symfony.
Возвращается 404
Файл создан не в той публичной директории либо домен указывает на другой каталог.
Возвращается 500
Ошибка возникает ещё на уровне PHP или серверной конфигурации. Смотрите журнал PHP и правила .htaccess.
После проверки файл обязательно удалите:
rm project/public/php-check.php
Не оставляйте диагностические файлы в публичном доступе.
Шаг 2. Проверьте корневую папку сайта
Одна из самых частых ошибок после переноса — неправильный Document Root.
Для Laravel и Symfony домен должен указывать на:
/home/user/www/example.com/project/public
а не на:
/home/user/www/example.com/project
и не на:
/home/user/www/example.com
Laravel рекомендует обслуживать приложение из корня публичного web-каталога, а не открывать весь проект или размещать его как подпапку публичного каталога: иначе чувствительные файлы приложения могут стать доступны извне.
Правильная структура:
project/
├── app/
├── bootstrap/
├── config/
├── storage/
├── vendor/
├── .env
└── public/ ← корень домена
└── index.php
Проверьте наличие входного файла:
test -f public/index.php \
&& echo "index.php найден" \
|| echo "index.php отсутствует"
Проверьте, что сам проект расположен там, где ожидает index.php:
test -f vendor/autoload.php \
&& echo "autoload найден" \
|| echo "autoload отсутствует"
Как это устроено на Siteko. В панели можно назначить корневой папкой домена произвольную подпапку проекта:
publicу Laravel и Symfony,webу Yii или другой каталог. При заказе с опцией «Подготовить окружение под фреймворк» корень сразу настраивается наpublic.
Как понять, что домен смотрит не туда
Характерные признаки:
- открывается список каталогов;
- вместо сайта показывается содержимое другого проекта;
- временный
php-check.phpне находится; - открывается стандартная страница хостинга;
- главная страница доступна только по адресу
/public; - браузер получает 403;
- в логе фигурирует другой абсолютный путь.
Не исправляйте это переносом содержимого public в корень вслепую. Лучше настроить Document Root и сохранить стандартную структуру проекта.
Шаг 3. Проверьте vendor и Composer
Laravel, Symfony и большинство современных PHP-приложений загружают зависимости через:
vendor/autoload.php
Если каталога vendor нет, приложение не запустится.
Проверка:
cd ~/www/example.com/project
ls -lah vendor/autoload.php
Если файл отсутствует:
composer install \
--no-dev \
--prefer-dist \
--optimize-autoloader \
--no-interaction
Для production Symfony также рекомендует устанавливать зависимости через composer install --no-dev --optimize-autoloader, а затем очищать production-кэш.
Если vendor есть, но класс не найден
Пример:
Class "App\Service\PaymentService" not found
Возможные причины:
- класс не попал в Git;
- отличается регистр символов в имени файла;
- автозагрузчик устарел;
- namespace не соответствует пути;
- часть
vendorзагружена по FTP; - Composer выполнялся с ошибкой;
- production использует другой релиз.
Пересоберите автозагрузчик:
composer dump-autoload \
--optimize \
--no-dev
Проверьте состояние Composer:
composer diagnose
Проверьте реальные требования окружения:
composer check-platform-reqs --no-dev
check-platform-reqs сравнивает требования установленных пакетов с фактическими версиями PHP и расширений на сервере. Composer рекомендует использовать эту проверку в production-сборке и останавливать деплой, если она завершилась с ошибкой.
Не скрывайте несовместимость
Не исправляйте ошибку командой:
composer install --ignore-platform-reqs
Она не устанавливает отсутствующее расширение и не делает старую версию PHP совместимой. Она только запрещает Composer остановить установку.
В результате зависимости появятся, но сайт может упасть уже во время запроса.
Шаг 4. Сравните версии PHP
На некоторых хостингах сайт и SSH могут использовать разные версии PHP.
В консоли:
php -v
На сайте временный диагностический файл выводит:
<?php
echo PHP_VERSION;
Версии должны соответствовать требованиям проекта.
Например:
CLI: 8.4
Web: 8.1
Composer успешно установил зависимости через PHP 8.4, но сайт запускает их под PHP 8.1. Результатом может стать синтаксическая или фатальная ошибка.
Проверьте ограничения проекта:
grep -A 10 '"require"' composer.json
Но окончательное заключение лучше получить через:
composer check-platform-reqs --no-dev
Как это устроено на Siteko. Версия PHP выбирается отдельно для каждого сайта, при этом обычная команда
phpв SSH и cron использует ту же версию, что и сайт. Доступны версии PHP от 5.2 до 8.5 — подробнее в восьмой статье серии.
Даже при совпадении версий проверьте, что команда выполняется в правильном каталоге. Иначе Composer может анализировать другой composer.json.
Шаг 5. Проверьте PHP-расширения
Сообщение:
could not find driver
обычно означает отсутствие PDO-драйвера базы.
Сообщение:
Call to undefined function mb_strlen()
указывает на отсутствие mbstring.
Сообщение:
Class "IntlDateFormatter" not found
может означать отсутствие intl.
Посмотреть модули:
php -m | sort
Найти конкретный:
php -m | grep -iE 'pdo|mysql|pgsql|mbstring|intl|curl|zip|gd'
Но ручной список всегда неполон. Надёжнее:
composer check-platform-reqs --no-dev
Composer рассматривает PHP и расширения как платформенные зависимости и проверяет их реальные версии на сервере.
Если нужного расширения нет:
- включите его в панели, если доступно;
- выберите другую версию PHP с нужным модулем;
- обратитесь в поддержку;
- замените несовместимую зависимость;
- при нестандартном требовании рассмотрите VDS.
Копирование файлов или chmod 777 отсутствующее расширение не установит.
Шаг 6. Проверьте .env
После успешного запуска PHP и Composer следующая частая причина — настройки окружения.
Проверьте наличие файла:
test -f .env \
&& echo ".env найден" \
|| echo ".env отсутствует"
Проверьте основные параметры без вывода паролей:
grep -E \
'^(APP_ENV|APP_DEBUG|APP_URL|DB_CONNECTION|DB_HOST|DB_PORT|DB_DATABASE)=' \
.env
Типовая production-конфигурация Laravel:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://example.com
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=example
DB_USERNAME=example_user
DB_PASSWORD=strong-password
Laravel хранит значительную часть настроек окружения в корневом .env; соединения с базами определяются в config/database.php и обычно получают параметры из переменных окружения.
Частые ошибки в .env
- файл называется
.env.txt; - файл не загрузился как скрытый;
- остались настройки локального Docker;
DB_HOST=mysql, хотя на хостинге нуженlocalhost;- указано старое имя базы;
- пароль содержит символы, требующие кавычек;
- в конце значения оказался пробел;
- используется неверный
APP_URL; - включён
APP_DEBUG=true; - production-кэш содержит предыдущие значения;
- строка была закомментирована символом
#.
Проверьте имя:
ls -la | grep -E '\.env'
Проверьте синтаксис конкретной строки:
grep '^DB_HOST=' .env | cat -A
cat -A помогает заметить скрытые символы и окончание строки.
Не публикуйте содержимое .env целиком в тикете, чате или скриншоте.
Шаг 7. Проверьте APP_KEY, но не создавайте новый бездумно
Laravel использует APP_KEY для шифрования.
Проверка наличия значения без его вывода:
if grep -qE '^APP_KEY=.+$' .env; then
echo "APP_KEY задан"
else
echo "APP_KEY отсутствует"
fi
Для совершенно нового проекта ключ можно создать:
php artisan key:generate
Laravel рекомендует генерировать его этой командой.
Но на существующем рабочем сайте нельзя просто создавать новый ключ вместо потерянного.
После смены APP_KEY могут перестать расшифровываться:
- cookies;
- сессии;
- ранее зашифрованные значения;
- токены;
- данные, сохранённые приложением через Laravel Encrypter.
Правильный источник ключа при переносе — старый production-файл .env или защищённая резервная копия конфигурации.
Шаг 8. Очистите закэшированную конфигурацию
Разработчик исправил пароль базы в .env, но приложение продолжает использовать старое значение.
Причина может находиться в закэшированной конфигурации.
Для Laravel:
php artisan optimize:clear
или только:
php artisan config:clear
После исправления и проверки production-кэши можно создать заново:
php artisan optimize
При использовании конфигурационного кэша Laravel не должен обращаться к env() из произвольных файлов приложения: значения окружения следует получать через файлы в config. Официальная документация предусматривает config:clear для удаления старой закэшированной конфигурации.
Для Symfony:
APP_ENV=prod APP_DEBUG=0 \
php bin/console cache:clear
Очистка и прогрев production-кэша входят в стандартные действия после развёртывания Symfony.
Если команда очистки сама падает
Это полезный результат: ошибка появится прямо в SSH.
Например:
SQLSTATE[HY000] [1045] Access denied
или:
The stream or file "var/log/prod.log" could not be opened
Теперь причина уже известна: база или права, а не абстрактный «хостинг не запускает сайт».
Шаг 9. Проверьте подключение к базе
Сообщения базы обычно достаточно конкретны.
Неверные логин или пароль
SQLSTATE[HY000] [1045]
Access denied for user
Проверьте:
DB_USERNAME=
DB_PASSWORD=
а также разрешён ли этому пользователю доступ к выбранной базе.
База не найдена
Unknown database
Проверьте:
DB_DATABASE=
На хостинге к имени базы может автоматически добавляться префикс аккаунта.
Сервер базы недоступен
Connection refused
или:
php_network_getaddresses:
getaddrinfo failed
Проверьте:
DB_HOST=
DB_PORT=
Значение из локального Docker:
DB_HOST=mysql
может не работать на обычном хостинге.
Нет драйвера
could not find driver
Это не ошибка пароля. Требуется PHP-расширение:
pdo_mysql
pdo_pgsql
pdo_sqlite
Проверка через приложение
Для Laravel:
php artisan migrate:status
Команда должна подключиться к базе и показать состояние миграций.
Для Symfony с Doctrine:
APP_ENV=prod \
php bin/console doctrine:migrations:status
Если команда падает, сообщение в SSH обычно точнее браузерной страницы 500.
Шаг 10. Проверьте миграции
После обновления код может ожидать таблицу или столбец, которых ещё нет.
Пример:
SQLSTATE[42S02]:
Base table or view not found
или:
Unknown column 'external_id'
Для Laravel:
php artisan migrate:status
Если есть невыполненные миграции и вы понимаете их последствия:
php artisan migrate --force
Для Symfony:
APP_ENV=prod \
php bin/console doctrine:migrations:status
и затем:
APP_ENV=prod \
php bin/console doctrine:migrations:migrate \
--no-interaction
Composer не применяет миграции автоматически, если это не прописано в отдельном deploy-сценарии. Получение кода, установка зависимостей, обновление структуры базы и очистка кэша — разные этапы деплоя.
Не запускайте миграции вслепую на единственной production-базе. Перед изменениями, которые удаляют или преобразуют данные, нужна резервная копия.
Шаг 11. Проверьте права на запись
Сообщения:
Permission denied
The stream or file could not be opened in append mode
Failed to open stream
указывают, что приложение не может читать или изменять нужный файл.
Для Laravel проверяем:
test -w storage \
&& echo "storage доступен для записи" \
|| echo "нет записи в storage"
test -w bootstrap/cache \
&& echo "bootstrap/cache доступен" \
|| echo "нет записи в bootstrap/cache"
Можно отдельно проверить лог:
touch storage/logs/write-test.log \
&& rm storage/logs/write-test.log \
&& echo "запись работает"
Для Symfony:
test -w var/cache \
&& echo "var/cache доступен"
test -w var/log \
&& echo "var/log доступен"
Symfony требует, чтобы var/log был доступен веб-процессу и консольному пользователю, а var/cache — процессам, которые создают и прогревают кэш.
Не используйте универсальный chmod 777
Команда:
chmod -R 777 .
разрешает запись во всём проекте всем пользователям системы.
Она:
- не объясняет исходную причину;
- открывает для записи код приложения;
- может изменить права секретов;
- усложняет дальнейшую диагностику;
- маскирует неправильного владельца файлов;
- не помогает, если проблема вообще не связана с правами.
Выдавайте запись только runtime-каталогам приложения.
Как это устроено на Siteko. PHP и SSH работают от одного пользователя, а аккаунты изолированы друг от друга. Поэтому
storage,bootstrap/cacheи runtime-каталоги работают со штатными правами; выдавать всему проекту777не требуется.
Шаг 12. Проверьте владельца и источник файлов
Даже правильные числовые права не помогут, если файлы принадлежат другому пользователю.
Посмотрите:
ls -ld \
. \
storage \
storage/logs \
bootstrap/cache
Пример проблемы:
drwxr-xr-x root root storage
При этом PHP работает от пользователя аккаунта и не может создать лог.
На виртуальном хостинге менять владельца через chown обычно нельзя. Причиной может быть:
- некорректно распакованный архив;
- импорт, выполненный службой панели;
- файлы, созданные другим способом;
- перенос с сохранением лишних атрибутов;
- конфликт между FTP-, SSH- и PHP-пользователями.
В такой ситуации поддержке уже можно отправить конкретный запрос:
Каталог
storageпринадлежит другому пользователю. PHP и SSH не могут создать файл. Помогите исправить владельца.
Это значительно полезнее сообщения «ошибка 500».
Шаг 13. Проверьте .htaccess и rewrite
Этот раздел относится к Apache и совместимым с ним веб-серверам. Nginx не читает .htaccess.
Ошибка в директиве может вызвать 500 до запуска приложения.
Примеры:
- неподдерживаемая директива;
- синтаксическая ошибка;
- правило из другого хостинга;
- попытка изменить запрещённый параметр PHP;
- старые настройки
AddHandler; - абсолютный путь предыдущего сервера.
Для диагностики можно временно переименовать файл:
mv public/.htaccess public/.htaccess.disabled
Если код 500 исчез и сменился на 404 либо открылась главная страница без маршрутов, причина находится в .htaccess.
Вернуть файл:
mv public/.htaccess.disabled public/.htaccess
Не оставляйте проект без rewrite-правил: главная страница может работать, а остальные маршруты — возвращать 404.
Для Symfony на shared-хостинге с Apache может потребоваться пакет или конфигурация, добавляющая подходящие rewrite-правила; официальная документация упоминает symfony/apache-pack для такого сценария.
Не переносите старый обработчик PHP
В .htaccess после другого хостинга могут остаться строки вроде:
AddHandler application/x-httpd-php74 .php
На новом сервере такого обработчика может не существовать. Версию PHP следует выбирать через панель нового хостинга, если это предусмотрено.
Шаг 14. Проверьте синтаксис PHP
После ручного исправления файла могла появиться опечатка:
Parse error:
unexpected token
Проверить один файл:
php -l app/Services/PaymentService.php
Проверить все PHP-файлы проекта:
find app config routes \
-type f \
-name '*.php' \
-print0 |
xargs -0 -n1 php -l
Команда может вывести много строк. Оставить только ошибки:
find app config routes \
-type f \
-name '*.php' \
-print0 |
xargs -0 -n1 php -l 2>&1 |
grep -v 'No syntax errors detected'
Если код был разработан под более новую версию PHP, синтаксическая ошибка также может означать не опечатку, а несовместимость версий.
Шаг 15. Проверьте регистр имён файлов
На Windows пути часто нечувствительны к регистру:
use App\Services\Paymentservice;
Файл:
app/Services/PaymentService.php
На локальном компьютере проект может работать, а на Linux — вернуть:
Class not found
Проверьте:
- регистр имени файла;
- регистр каталогов;
- namespace;
use;- PSR-4-настройки в
composer.json.
После исправления:
composer dump-autoload --optimize
Особенно внимательно проверяйте изменения, в которых файл переименовали только изменением регистра. Git на некоторых рабочих системах может не заметить такое переименование сразу.
Шаг 16. Проверьте память, время выполнения и диск
Приложение может запускаться, но падать на тяжёлой операции.
Память
Сообщение:
Allowed memory size of ... bytes exhausted
означает, что PHP-процесс достиг лимита памяти.
Причиной может быть:
- обработка большого изображения;
- загрузка большого файла в память;
- бесконечная рекурсия;
- выборка всей таблицы;
- крупный экспорт;
- слишком тяжёлая Composer-команда;
- утечка в коде;
- слишком низкий лимит.
Увеличение лимита может временно скрыть проблему, но сначала нужно понять, почему операция потребляет столько памяти.
Время
Сообщение:
Maximum execution time exceeded
говорит о превышении времени выполнения.
Частые причины:
- медленный SQL-запрос;
- внешний API не отвечает;
- большой импорт выполняется внутри HTTP-запроса;
- отправка множества писем без очереди;
- блокировка базы;
- цикл без условия завершения.
Диск и inode
Если приложение не может создать кэш или лог, проверьте:
df -h
И, если доступно:
df -i
Даже при свободных гигабайтах может закончиться допустимое количество файлов. Современные проекты создают тысячи объектов в vendor, node_modules, кэшах и сессиях.
Шаг 17. Воспроизведите ошибку через консоль
Браузер скрывает подробности, а CLI часто показывает их напрямую.
Для Laravel:
php artisan about
php artisan route:list
php artisan migrate:status
php artisan optimize:clear
Для Symfony:
APP_ENV=prod APP_DEBUG=0 \
php bin/console about
APP_ENV=prod APP_DEBUG=0 \
php bin/console cache:clear
APP_ENV=prod \
php bin/console doctrine:migrations:status
Если уже первая команда завершается исключением, проблема находится в базовой загрузке приложения.
Если консольные команды работают, а браузер возвращает 500, сравните:
- версию PHP web и CLI;
- переменные окружения;
- пользователя процесса;
- текущий каталог;
- web-конфигурацию;
- rewrite;
- права.
Шаг 18. Сравните рабочую и сломанную версии
Если сайт перестал работать после деплоя, не диагностируйте проект как неизвестную систему. У вас есть точка сравнения.
Посмотрите текущий коммит:
git rev-parse --short HEAD
Последние изменения:
git log \
--oneline \
--decorate \
-n 10
Изменённые файлы:
git show \
--stat \
--oneline \
HEAD
Проверьте, менялись ли:
composer.lock
package-lock.json
database/migrations/
config/
.env.example
public/
Сравнить два релиза:
git diff \
--stat \
PREVIOUS_COMMIT..HEAD
Если предыдущий релиз сохранён отдельно, можно проверить его без повторной сборки.
Но помните: возврат кода не откатывает базу данных и пользовательские файлы. Именно поэтому в девятой статье мы разделяли код, конфигурацию и изменяемые данные.
Быстрый алгоритм диагностики Laravel
Выполняйте по порядку:
cd ~/www/example.com/project
1. Проверяем файлы
test -f public/index.php \
&& echo "public/index.php OK"
test -f vendor/autoload.php \
&& echo "vendor/autoload.php OK"
test -f .env \
&& echo ".env OK"
2. Проверяем PHP
php -v
php -m
3. Проверяем Composer
composer check-platform-reqs --no-dev
composer diagnose
4. Проверяем права
test -w storage \
&& echo "storage writable"
test -w bootstrap/cache \
&& echo "bootstrap/cache writable"
5. Запускаем приложение в CLI
php artisan about
6. Очищаем старую конфигурацию
php artisan optimize:clear
7. Проверяем базу
php artisan migrate:status
8. Возвращаем production-кэши
php artisan optimize
9. Читаем журнал
tail -n 100 storage/logs/laravel.log
Если ошибка появилась на каком-то шаге, не переходите дальше. Сначала разберите её текст.
Быстрый алгоритм диагностики Symfony
cd ~/www/example.com/project
1. Проверяем файлы
test -f public/index.php \
&& echo "public/index.php OK"
test -f vendor/autoload.php \
&& echo "vendor/autoload.php OK"
test -f .env \
&& echo ".env OK"
2. Проверяем окружение
php -v
composer check-platform-reqs --no-dev
3. Проверяем права
test -w var/cache \
&& echo "var/cache writable"
test -w var/log \
&& echo "var/log writable"
4. Запускаем приложение
APP_ENV=prod APP_DEBUG=0 \
php bin/console about
5. Очищаем кэш
APP_ENV=prod APP_DEBUG=0 \
php bin/console cache:clear
6. Проверяем миграции
APP_ENV=prod \
php bin/console doctrine:migrations:status
7. Читаем лог
Если configured file logging используется:
tail -n 100 var/log/prod.log
Если файла нет, проверьте настройки Monolog и журнал PHP.
Таблица: сообщение, причина и следующее действие
| Сообщение | Вероятная причина | Следующее действие |
|---|---|---|
Failed opening required vendor/autoload.php |
Не установлен или неполон vendor |
Выполнить composer install |
Class ... not found |
Ошибка namespace, регистра или autoload | Проверить файл и выполнить composer dump-autoload -o |
Your Composer dependencies require a PHP version... |
Неподходящая версия PHP | Выбрать совместимую версию |
requires ext-intl |
Нет PHP-расширения | Включить модуль или изменить окружение |
could not find driver |
Нет PDO-драйвера базы | Подключить pdo_mysql, pdo_pgsql или нужный драйвер |
Access denied for user |
Неверный пользователь или пароль базы | Проверить .env и права пользователя БД |
Unknown database |
Неправильное имя базы | Сверить имя в панели и .env |
Connection refused |
Неверный хост/порт или база недоступна | Проверить DB_HOST, DB_PORT |
No application encryption key |
Не задан APP_KEY |
Восстановить ключ или создать для нового проекта |
Permission denied |
Нет прав на чтение или запись | Проверить конкретный файл, каталог и владельца |
could not be opened in append mode |
Приложение не может записать лог | Проверить storage/logs или var/log |
Allowed memory size exhausted |
Превышен лимит памяти | Найти тяжёлую операцию и проверить лимиты |
Maximum execution time exceeded |
Слишком долгая операция | Проверить SQL, API, импорт или цикл |
Unknown column |
Код новее структуры базы | Проверить и применить миграции |
Base table or view not found |
Нет таблицы или выбрана не та база | Проверить миграции и DB_DATABASE |
Parse error |
Ошибка синтаксиса или старая версия PHP | Выполнить php -l, сравнить версии |
Primary script unknown |
Неверная публичная директория или путь | Проверить Document Root |
| Главная работает, остальные страницы 404 | Не работает rewrite | Проверить .htaccess или web-конфигурацию |
| Сайт открывается без стилей | Не собран frontend | Выполнить npm ci && npm run build |
Ошибка сохраняется после правки .env |
Закэширована старая конфигурация | Выполнить config:clear или optimize:clear |
Что не следует делать
Не ставьте 777 на весь проект
Права следует исправлять только там, где приложению действительно нужна запись.
Не запускайте composer update
Для восстановления production-проекта обычно нужен набор из composer.lock:
composer install
update может подобрать новые версии пакетов и создать уже другую проблему.
Не используйте --ignore-platform-reqs
Он скрывает несовместимость, а не исправляет её.
Не удаляйте .env
Перед удалением конфигурации убедитесь, что существует резервная копия.
Не создавайте новый APP_KEY на работающем сайте
Сначала восстановите исходный ключ.
Не включайте debug публично
Читайте журнал или воспроизводите ошибку в SSH.
Не очищайте всё подряд
Удаление пользовательских загрузок, сессий или общего storage не является очисткой кэша.
Не возвращайте старый код без учёта базы
Несовместимая миграция может сделать откат ещё опаснее.
Не скрывайте первую ошибку
После каждого исправления снова читайте лог. Следующая ошибка может быть уже другой.
Что приложить к обращению в поддержку
Если самостоятельная диагностика не помогла, хорошее обращение выглядит так:
Домен: example.com
URL: https://example.com/admin/orders
Время ошибки: 21 июля 2026, 10:42
HTTP-код: 500
Ошибка появилась после:
git pull origin main
composer install
php artisan migrate --force
Версия PHP в SSH: 8.4.12
Версия PHP на сайте: 8.4.12
Результат:
composer check-platform-reqs --no-dev — успешно
php artisan about — завершается ошибкой
Строка из лога:
The stream or file
"/home/user/www/example.com/project/storage/logs/laravel.log"
could not be opened in append mode: Permission denied
Проблемный путь:
storage/logs
Пароли и содержимое .env не прикладываю.
По такому сообщению поддержка сразу понимает:
- какой сайт проверять;
- когда искать запись;
- где воспроизводится ошибка;
- какие действия уже выполнены;
- что именно требуется проверить.
Плохое обращение:
Ошибка 500. Ничего не работает.
Оно вынуждает начать диагностику с нуля.
Как это применить на Siteko
Для проекта на тарифах с SSH последовательность выглядит так:
- проверить корневую папку домена;
- перейти в каталог проекта;
- выполнить
php -v; - проверить
vendor/autoload.php; - запустить
composer check-platform-reqs; - выполнить
php artisan aboutили Symfony Console; - проверить
.envбез публикации секретов; - проверить доступность runtime-каталогов для записи;
- очистить старые кэши;
- проверить миграции;
- прочитать журнал приложения и PHP;
- передать поддержке точный текст ошибки, если проблема относится к окружению.
Из предыдущей статьи уже известно, что Siteko позволяет назначить произвольный Document Root, использует совпадающую версию PHP для сайта, SSH и cron, предоставляет глобальный Composer, а PHP и SSH работают от одного пользователя. Эти особенности убирают несколько распространённых источников расхождений, но не отменяют ошибки в .env, зависимостях, миграциях и коде проекта.
Если проекту требуется отсутствующее системное расширение, отдельный сервис, нестандартная конфигурация PHP-FPM или собственный веб-сервер, это уже может быть границей виртуального хостинга. Но вывод следует делать после чтения конкретной ошибки, а не только по коду 500.
Что в итоге
Ошибка 500 кажется непрозрачной только в браузере.
За ней почти всегда находится конкретное сообщение:
не найден файл
не установлена зависимость
не подходит версия PHP
отсутствует расширение
неверен пароль базы
нет нужной таблицы
закэширована старая конфигурация
нет прав на запись
закончилась память
Главный навык здесь — не знание всех возможных ошибок наизусть, а правильная последовательность:
зафиксировать симптом
↓
найти журнал
↓
прочитать первую ошибку
↓
проверить одну причину
↓
внести одно изменение
↓
повторить запрос
Начинайте с логов. Затем проверяйте публичную директорию, vendor, PHP, расширения, .env, базу, права, кэш и миграции.
И только после этого обращайтесь в поддержку — уже не с сообщением «сайт не работает», а с точным текстом ошибки и результатами проверок.
Но иногда сайт не падает. Он открывается — просто делает это пять секунд, периодически зависает и оживает после перехода на более дорогой тариф лишь на несколько дней.
В следующей части разберёмся, кто действительно виноват в медленной работе: ограничения хостинга, PHP-код, база данных, внешние API, изображения или фоновые задачи.
- 1 Как выбрать хостинг для сайта и не купить себе вторую работу
- 2 Виртуальный хостинг, VPS или облако: что действительно нужно вашему сайту
- 3 Гигабайты ничего не решают: как читать характеристики тарифа хостинга
- 4 «Безлимитный» хостинг: что заканчивается раньше дискового пространства
- 5 Домен подключён, а сайт не открывается: DNS без мистики
- 6 HTTPS включён, а браузер всё равно ругается: SSL без паники
- 7 Письма с сайта пропадают: SMTP, SPF, DKIM и DMARC на пальцах
- 8 Современный PHP-хостинг: зачем Laravel и Symfony нужны SSH, Composer, Node.js, cron и отдельная public-директория
- 9 Деплой без FTP на виртуальном хостинге: Git, Composer и безопасный откат
- 10 Ошибка 500 после загрузки сайта: где искать причину до обращения в поддержку вы здесь
- 11 Сайт тормозит на хостинге: виноват тариф, код, база или внешний сервис скоро
- 12 Бэкап есть — восстановить нельзя: проверяем резервные копии до аварии скоро
- 13 Переезд на другой хостинг без потери сайта, писем и заказов скоро
- 14 Когда виртуальный хостинг стал тесен: пора на VPS или ещё можно остаться скоро
Была статья полезной: