Play
online · 30 мин
Туториалы 10 мин чтения 13.07.2026

BitrixVM показывает PHP-код: причины и настройка PHP-FPM

Вместо рабочего сайта — голый PHP-код? Разбираем, почему BitrixVM 9.0.9 перестал обрабатывать скрипты. Пять основных причин разрыва связки Nginx и PHP-FPM, от сбитого сокета до нехватки ресурсов.

BitrixVM PHP код не выполняется: основные причины

Когда в браузере вместо страницы отображается исходный PHP-код — это классический симптом разрыва связки Nginx + PHP-FPM. В наших проектах такая ситуация возникает обычно после обновления BitrixVM, миграции на новый сервер или при неосторожной правке конфигов руками. Клиент видит голый текст <?php и пустые белые страницы — бизнес-критичная проблема, которую нужно решать в первую очередь. Мы регулярно сталкиваемся с этим у магазинов с высоконагруженным каталогом, где каждая минута простоя стоит денег. Основные причины сводятся к пяти сценариям: демон PHP-FPM не запущен, Nginx не знает, что .php нужно отдавать в обработку, путь к сокету в конфигах не совпадает с реальным, пул PHP-FPM сконфигурирован с ошибкой, или серверу просто не хватает ресурсов, памяти и дочерних процессов.

  • PHP-FPM не запущен, мастер-процесс упал после перегрузки памяти или не стартовал при перезапуске сервисов. Проверяется командой systemctl status php-fpm.
  • Nginx не передаёт .php в PHP-FPM, отсутствует или закомментирован блок location ~ \.php$ в конфиге виртуального хоста. Nginx отдаёт файл как статику.
  • Неверный путь к сокету, в fastcgi_pass указан unix-сокет, который не совпадает с listen в пуле PHP-FPM. Типичная ошибка после смены версии PHP.
  • Ошибки в конфигурации пула или синтаксическая ошибка в файлах /etc/php-fpm.d/ могут помешать запуску пула. Подробности следует искать в логах php-fpm.log.
  • Недостаточно памяти/процессов, пул исчерпал лимит pm.max_children, новые запросы встают в очередь или падают с 502/504.

Понимание архитектуры BitrixVM здесь критично. Связка стандартная: Nginx принимает HTTP-запросы, статику отдаёт сам, а .php-файлы передаёт в PHP-FPM через unix-сокет. Если Nginx по какой-то причине не видит в запросе .php или не может соединиться с сокетом, он честно отдаёт файл как есть, то есть в виде исходного кода. Типовая структура конфигов в BitrixVM: основные настройки Nginx лежат в /etc/nginx/bx/site_avaliable/, а пулы PHP-FPM настраиваются в соответствующих конфигурационных файлах (например, в каталоге /etc/php-fpm.d/). Мы обычно начинаем диагностику с проверки fastcgi_pass в конфиге сайта: там должен быть путь к сокету, совпадающий с listen в пуле. Об этом подробнее, в следующих секциях.

BitrixVM показывает исходный код: проверка состояния PHP-FPM

Самый частый запрос на эту тему — «сделал всё по инструкции, а в браузере по-прежнему голый PHP-код». В нашей практике примерно каждый второй случай отображения исходного кода на BitrixVM решается простой проверкой: жив ли PHP-FPM. Дело в том, что BitrixVM — это связка Nginx + PHP-FPM, и если второй компонент упал, Nginx честно отдаёт файл как есть, не понимая, что его нужно обработать. Типичный сценарий: после обновления пакетов, смены версии PHP или перезагрузки сервера демон PHP-FPM не стартует автоматически. Мы регулярно видим это у клиентов, которые обновляли BitrixVM через штатное меню окружения (1. Manage servers in the pool → 4. Update packages on host), процесс обновления сбрасывает автозапуск некоторых сервисов. Поэтому первым делом смотрим статус.

SHELL
# Проверка статуса PHP-FPM
systemctl status php-fpm

# Альтернативная проверка — поиск процессов
ps aux | grep php-fpm
  1. Выполнить systemctl status php-fpm, если вы видите active (running), PHP-FPM работает. Статус inactive (dead) или failed, причина найдена.
  2. Если сервис неактивен, запустить его: systemctl start php-fpm. После запуска проверьте статус повторно, он должен смениться на active.
  3. Включить автозапуск, чтобы PHP-FPM стартовал при перезагрузке сервера: systemctl enable php-fpm.
  4. Проверить, что сокет существует и доступен: grep -r '^listen' /etc/php-fpm.d/ # путь к сокету смотрим в конфиге пула, затем ls -la по нему. Если файла нет, PHP-FPM не смог создать сокет, проверьте логи: journalctl -u php-fpm --no-pager | tail -30.

BitrixVM 9.0.9 ошибка: настройка PHP-FPM для корректной работы

Распространённая ошибка: BitrixVM 9.0.9 стоит, PHP-FPM запущен, но в браузере — пустая страница или 502 Bad Gateway. Чаще всего причина не в том, что сервис упал, а в том, что пул настроен неправильно. В нашей практике это регулярно всплывает после обновления с более старых версий виртуальной машины — когда конфигурация пула остаётся «как была», а версия PHP и требования к ресурсам изменились. Стандартные настройки из коробки в BitrixVM 9.0.9 рассчитаны на минимальную нагрузку: один-два сайта с парой десятков посетителей. Если у вас магазин с активным каталогом или несколько проектов на одной машине, эти параметры гарантированно приведут к тому, что PHP-воркеры будут заканчиваться, а Nginx, отдавать ошибки вместо страниц. Поэтому после базовой проверки состояния сервиса (о ней ниже) мы всегда идём в конфигурацию пула.

Параметры пула pm.max_children и pm.start_servers

Главный параметр, который определяет, сколько PHP-воркеров одновременно может обрабатывать запросы, pm.max_children. В официальной документации «1С-Битрикс» указано, что настройки «по умолчанию» — это далеко не всегда хорошо, и их неграмотное изменение может дать обратный результат. Для одного сайта-визитки стандартных значений может хватить, но для магазина с 50–100 одновременными посетителями их, скорее всего, будет недостаточно. Мы в таких случаях поднимаем до 20–30, но только после расчёта по памяти: один воркер PHP 8.2 в среднем съедает 30–40 МБ. Если на сервере 2 ГБ ОЗУ, ставить 50 детей — значит гарантированно убить swap.

Второй важный параметр, pm.start_servers. Это количество воркеров, которые поднимаются сразу при старте PHP-FPM. Если поставить слишком мало (проверьте текущее значение в вашем www.conf), первые секунды после перезапуска сервиса все запросы будут ждать, пока пул «прогреется». Мы обычно ставим pm.start_servers = 4 при pm.max_children = 20, а pm.min_spare_servers и pm.max_spare_servers, 4 и 8 соответственно. Это даёт плавный старт без пиков.

SHELL
# /etc/php/8.2/fpm/pool.d/www.conf — BitrixVM 9.0.9
; Динамический менеджер процессов (рекомендуется для большинства проектов)
pm = dynamic

; Максимум детей  считайте по формуле: (RAM - резерв) / 40 МБ
pm.max_children = 20

; Стартовое количество воркеров
pm.start_servers = 4

; Минимум свободных воркеров (чтобы не ждать создания)
pm.min_spare_servers = 4

; Максимум свободных (чтобы не держать лишних)
pm.max_spare_servers = 8

Проверка прав доступа к сокету и listen.mode

Даже если пул настроен идеально, но сокет PHP-FPM недоступен для чтения и записи пользователю веб-сервера, соединения не будет. Стандартная ошибка: сокет создаётся с правами 0660 и владельцем, соответствующим пользователю мастер-процесса PHP-FPM (в BitrixVM — bitrix; www-data встречается в Debian-системах), а Nginx в BitrixVM может работать от другого пользователя (например, bitrix или nginx). В итоге, Permission denied в логах Nginx и 502 Bad Gateway на сайте.

Проверить это просто: смотрим, кто владелец сокета и какие права выставлены. Если владелец не совпадает с пользователем Nginx, нужно либо сменить владельца через listen.owner и listen.group в конфигурации пула, либо выставить listen.mode = 0666. Второе, временное решение, но для диагностики подходит.

SHELL
# Проверяем текущие права и владельца сокета
ls -la /var/run/php-fpm/php-fpm.sock

# Временное решение — дать доступ всем (ТОЛЬКО для диагностики!)
sudo chmod 666 /var/run/php-fpm/php-fpm.sock

# Правильное решение — настроить владельца в пуле
# В /etc/php/8.2/fpm/pool.d/www.conf:
# listen.owner = nginx
# listen.group = nginx
# listen.mode = 0660

PHP не обрабатывается BitrixVM: проверка конфигурации Nginx

Типичный сценарий: systemctl status php-fpm показывает active (running), пул BitrixVM настроен, а в браузере — всё тот же исходный PHP-код. Значит, проблема не в самом интерпретаторе, а в том, что Nginx не передаёт ему запросы к .php-файлам. В нашей практике это второй по частоте случай после остановленного PHP-FPM. Проверка конфигурации Nginx — обязательный шаг, когда базовые проверки пройдены, а симптом остался. Если не разобраться здесь, можно потратить часы на переустановку пакетов, которые и так работают.

Проверка location ~ \.php$ в конфиге хоста

Nginx обрабатывает PHP-запросы через специальный блок location ~ \.php$. Если он отсутствует, отсутствует или закомментирован, все запросы к .php будут отдаваться как статические файлы, то есть исходным кодом. В BitrixVM этот блок по умолчанию находится в файле конфигурации вашего сайта, обычно /etc/nginx/bx/site_enabled/ваш_сайт.conf. Откройте его и убедитесь, что секция присутствует и не закомментирована символом #.

SHELL
# Пример корректного блока location для обработки PHP в Nginx
location ~ \.php$ {
    fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

Проверка fastcgi_pass: сокет или TCP?

Даже если блок location ~ \.php$ на месте, запросы могут не доходить до PHP-FPM из-за неверного адреса в директиве fastcgi_pass. В BitrixVM по умолчанию используется UNIX-сокет, это быстрее и безопаснее, чем TCP-соединение через localhost. Однако после обновлений или ручной правки конфигов адрес может сбиться. Проверьте, совпадает ли путь в fastcgi_pass с тем, что указан в пуле PHP-FPM (обычно в /etc/php-fpm.d/www.conf).

SHELL
# Команда для поиска fastcgi_pass в конфигах
grep -r 'fastcgi_pass' /etc/nginx/

Разница между сокетом и TCP, не только в производительности. UNIX-сокет (например, unix:/tmp/php-fpm.sock — так в BitrixVM, или unix:/var/run/php-fpm/php-fpm.sock в типовом CentOS) работает только между процессами на одном сервере, исключая лишние сетевые накладные расходы. TCP (например, 127.0.0.1:9000) нужен, если PHP-FPM и Nginx находятся на разных хостах, но в стандартной BitrixVM это избыточно. Мы в проектах всегда оставляем сокет, он быстрее и проще в диагностике: если сокет-файл существует и доступен для чтения Nginx, значит, связка работает.

Настройка PHP-FPM BitrixVM: оптимизация пула и устранение ошибок

После того как базовая проблема решена, стоит оптимизировать пул PHP-FPM для производительности. BitrixVM поставляется с консервативными настройками — в расчёте на то, что администратор их подгонит под свой проект. В нашей практике это одна из первых задач, которую мы решаем на этапе приёмки сервера: дефолтный пул рассчитан на небольшое число одновременных процессов, что для магазина с каталогом на 30 тысяч товаров и 300 посетителями в пике — гарантированный простой. Клиенты приходят с жалобами на «тормоза» в админке и медленную выдачу товарных карточек, а причина часто именно в том, что пул упирается в лимит pm.max_children. Оптимизация пула даёт прямой прирост скорости без изменения кода, только правка конфигурации. Эта настройка комбинируется с предыдущей проверкой pm.status_path и корректировкой таймаутов Nginx, о которых мы говорили выше.

Настройка pm.max_children под нагрузку

Главный параметр, который определяет, сколько PHP-процессов сможет работать одновременно. Если поставить слишком мало, запросы будут вставать в очередь, пользователи увидят «задумчивый» сайт. Если слишком много, сервер уйдёт в своп и упадёт. У нас в проектах мы подбираем pm.max_children под реальную пиковую нагрузку: смотрим логи php-fpm через pm.status_path, замеряем active processes в час пик и добавляем запас 20–30%. Для типового магазина на BitrixVM с 2–4 ГБ ОЗУ рабочий диапазон, 20–40 процессов. Если сайт отдаёт статику через CDN, а PHP-нагрузка идёт только на динамические страницы, можно ставить ближе к нижней границе.

Формула расчёта: (память сервера / память на один PHP-процесс). Память на один процесс в BitrixVM обычно 30–50 МБ (замеряем через ps aux | grep php-fpm). Пример для сервера с 4 ГБ ОЗУ: 4096 МБ / 40 МБ ≈ 102 процесса. Но это теоретический максимум, на практике мы не поднимаем выше 40–50, оставляя память для MySQL, Nginx и самого Bitrix. Если на сервере крутится ещё и Elasticsearch, запас нужно увеличить. Важно помнить: pm.max_children, это не количество воркеров, которые работают постоянно, а максимум одновременно запущенных. При pm = dynamic PHP-FPM сам регулирует количество в пределах от pm.min_spare_servers до pm.max_children.

Настройка pm.max_requests для предотвращения утечек

Второй критичный параметр, pm.max_requests. Он задаёт, сколько запросов обработает один PHP-процесс, прежде чем будет перезапущен. Утечки памяти в PHP-расширениях или в самом Bitrix, не редкость, особенно если используются тяжёлые модули вроде imagemagick или curl с длинными сессиями. Без лимита процесс со временем «раздувается» до сотен мегабайт, и пул начинает потреблять всю доступную память. В наших проектах мы ставим pm.max_requests = 500, это баланс между стабильностью и производительностью. Если сайт использует кеширование и редко генерирует динамику, можно поднять до 1000–2000. Для высоконагруженных магазинов с частыми обменами с 1С, 300–500 оптимально.

SHELL
cat /etc/php-fpm.d/*.conf # имя файла пула зависит от версии окружения

[bitrix]
pm = dynamic
pm.max_children = 40
pm.start_servers = 8
pm.min_spare_servers = 4
pm.max_spare_servers = 16
pm.max_requests = 500

Частые вопросы

Можно ли использовать PHP-FPM с другим пользователем, кроме bitrix, и не сломает ли это права доступа?

Да, можно, но тогда в пуле PHP-FPM (например, в /etc/php-fpm.d/www.conf) нужно явно указать user и group нового пользователя, а также скорректировать права на папки /home/bitrix и /tmp/php-upload, иначе BitrixVM не сможет записывать кеш и временные файлы.

Что делать, если после настройки PHP-FPM сайт открывается, но скачивается файл index.php вместо страницы?

Проверьте, что в location ~ \.php$ в конфиге Nginx указан fastcgi_pass на unix-сокет (например, unix:/var/run/php-fpm/php-fpm.sock), а не на localhost:9000, и что директива try_files не переопределяет обработку PHP-файлов.

А если у меня BitrixVM 9.0.9, но PHP-FPM не стартует с ошибкой «ERROR: unable to bind listening socket»?

Это значит, что сокет или порт уже занят — проверьте, не запущен ли второй экземпляр PHP-FPM, и удалите старый sock-файл в /var/run/php-fpm/ перед перезапуском службы.

Чем отличается настройка обработчика .php через location ~ \.php$ от использования map $uri в Nginx?

location ~ \.php$ — это прямой блок для передачи всех PHP-запросов в PHP-FPM, а map $uri используется для динамического выбора бэкенда или пула в зависимости от URI; для типовой BitrixVM достаточно первого варианта без map.

Можно ли отключить проверку прав доступа к сокету PHP-FPM, чтобы не настраивать listen.mode?

Нет, отключать проверку нельзя — это снизит безопасность. Вместо этого установите listen.mode = 0660 в пуле и добавьте пользователя nginx в группу, владеющую сокетом (обычно group = nginx).

#Bitrix #PHP #Nginx #Linux
автор · Backend / SRE Engineer
Артем Колячек

Backend-разработчик и SRE в студии Paradigma. Занимается тем, что у других проектов обычно обнаруживается за неделю до запуска: переездом Bitrix-проектов между серверами, починкой кешей после миграций, выстраиванием pipeline для контейнеров, мониторингом под нагрузкой.

До Paradigma — 7 лет в backend (PHP + Postgres) и в operations (Linux, Docker, Coolify, restic-бэкапы). Любит когда логи разговаривают полным синтаксисом ошибки, а не «что-то пошло не так».

На блоге пишет ровно про те ситуации с которыми сам разбирался руками: какой Bitrix-апдейт сломал кеш и как откатить, почему Docker-сеть не находит контейнер после рекрейта, что делать когда asyncpg ругается на event loop.