# Конфигурация FrankenPHP, Caddy, а также модули [Mercure](mercure.md) и [Vulcain](https://vulcain.rocks) могут быть настроены с использованием [форматов, поддерживаемых Caddy](https://caddyserver.com/docs/getting-started#your-first-config). Наиболее распространенным форматом является `Caddyfile`, который представляет собой простой, удобочитаемый текстовый формат. По умолчанию FrankenPHP будет искать `Caddyfile` в текущей директории. Вы можете указать пользовательский путь с помощью опции `-c` или `--config`. Ниже показан минимальный `Caddyfile` для обслуживания PHP-приложения: ```caddyfile # Хостнейм, на который будет отвечать сервер localhost # Опционально, директория для обслуживания файлов, иначе по умолчанию используется текущая директория #root public/ php_server ``` Более продвинутый `Caddyfile`, включающий дополнительные функции и предоставляющий удобные переменные окружения, можно найти [в репозитории FrankenPHP](https://github.com/php/frankenphp/blob/main/caddy/frankenphp/Caddyfile), а также в Docker-образах. PHP можно настроить [с помощью файла `php.ini`](https://www.php.net/manual/en/configuration.file.php). В зависимости от метода установки, FrankenPHP и PHP-интерпретатор будут искать конфигурационные файлы в местах, описанных ниже. ## Docker FrankenPHP: - `/etc/frankenphp/Caddyfile`: основной файл конфигурации - `/etc/frankenphp/Caddyfile.d/*.caddyfile`: дополнительные файлы конфигурации, которые загружаются автоматически PHP: - `php.ini`: `/usr/local/etc/php/php.ini` (по умолчанию `php.ini` не предоставляется) - дополнительные файлы конфигурации: `/usr/local/etc/php/conf.d/*.ini` - расширения PHP: `/usr/local/lib/php/extensions/no-debug-zts-/` - Вы должны скопировать официальный шаблон, предоставляемый проектом PHP: ```dockerfile FROM dunglas/frankenphp # Production: RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini # Или development: RUN cp $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini ``` ## RPM и Debian пакеты FrankenPHP: - `/etc/frankenphp/Caddyfile`: основной файл конфигурации - `/etc/frankenphp/Caddyfile.d/*.caddyfile`: дополнительные файлы конфигурации, которые загружаются автоматически PHP: - `php.ini`: `/etc/php-zts/php.ini` (по умолчанию предоставляется файл `php.ini` с производственными настройками) - дополнительные файлы конфигурации: `/etc/php-zts/conf.d/*.ini` ## Статический бинарный файл FrankenPHP: - В текущей рабочей директории: `Caddyfile` PHP: - `php.ini`: Директория, в которой выполняется `frankenphp run` или `frankenphp php-server`, затем `/etc/frankenphp/php.ini` - дополнительные файлы конфигурации: `/etc/frankenphp/php.d/*.ini` - расширения PHP: не могут быть загружены, их следует встраивать в сам бинарный файл - скопируйте один из шаблонов `php.ini-production` или `php.ini-development`, предоставленных [в исходниках PHP](https://github.com/php/php-src/). ## Конфигурация Caddyfile [HTTP-директивы](https://caddyserver.com/docs/caddyfile/concepts#directives) `php_server` или `php` могут быть использованы в блоках сайта для обслуживания вашего PHP-приложения. Минимальный пример: ```caddyfile localhost { # Включить сжатие (опционально) encode zstd br gzip # Выполнять PHP-файлы в текущей директории и обслуживать ресурсы php_server } ``` Вы также можете явно настроить FrankenPHP, используя [глобальную опцию](https://caddyserver.com/docs/caddyfile/concepts#global-options) `frankenphp`: ```caddyfile { frankenphp { num_threads # Устанавливает количество запускаемых потоков PHP. По умолчанию: 2x от числа доступных CPU. max_threads # Ограничивает количество дополнительных потоков PHP, которые могут быть запущены во время выполнения. По умолчанию: num_threads. Может быть установлено в 'auto'. max_wait_time # Устанавливает максимальное время, в течение которого запрос может ожидать свободный поток PHP до истечения таймаута. По умолчанию: отключено. max_idle_time # Устанавливает максимальное время бездействия автоматически масштабируемого потока до его деактивации. По умолчанию: 5s. php_ini # Устанавливает директиву php.ini. Может использоваться несколько раз для установки нескольких директив. worker { file # Устанавливает путь к worker-скрипту. num # Устанавливает количество запускаемых потоков PHP, по умолчанию 2x от числа доступных CPU. env # Устанавливает дополнительную переменную окружения с заданным значением. Может быть указано несколько раз для нескольких переменных окружения. watch # Устанавливает путь для отслеживания изменений файлов. Может быть указано несколько раз для нескольких путей. name # Устанавливает имя worker, используемое в логах и метриках. По умолчанию: абсолютный путь к файлу worker. max_consecutive_failures # Устанавливает максимальное количество последовательных сбоев, после которых worker считается неработоспособным; -1 означает, что worker всегда будет перезапускаться. По умолчанию: 6. } } } # ... ``` В качестве альтернативы можно использовать однострочную краткую форму для опции `worker`: ```caddyfile { frankenphp { worker } } # ... ``` Вы также можете определить несколько workers, если обслуживаете несколько приложений на одном сервере: ```caddyfile app.example.com { root /path/to/app/public php_server { root /path/to/app/public # позволяет лучше кэшировать worker index.php } } other.example.com { root /path/to/other/public php_server { root /path/to/other/public worker index.php } } # ... ``` Использование директивы `php_server` — это то, что нужно в большинстве случаев, но если требуется полный контроль, вы можете использовать более низкоуровневую директиву `php`. Директива `php` передает все входные данные PHP, не проверяя предварительно, является ли это PHP-файлом или нет. Подробнее об этом читайте на [странице производительности](performance.md#try_files). Использование директивы `php_server` эквивалентно следующей конфигурации: ```caddyfile route { # Добавить слэш в конец запросов к директориям @canonicalPath { file {path}/index.php not path */ } redir @canonicalPath {path}/ 308 # Если запрошенный файл не существует, попытаться использовать файлы index @indexFiles file { try_files {path} {path}/index.php index.php split_path .php } rewrite @indexFiles {http.matchers.file.relative} # FrankenPHP! @phpFiles path *.php php @phpFiles file_server } ``` Директивы `php_server` и `php` имеют следующие опции: ```caddyfile php_server [] { root # Устанавливает корневую папку для сайта. По умолчанию: директива `root`. split_path # Устанавливает подстроки для разделения URI на две части. Первая совпадающая подстрока будет использована для разделения "path info" от пути. Первая часть будет дополнена совпадающей подстрокой и будет считаться фактическим именем ресурса (CGI-скрипта). Вторая часть будет установлена как PATH_INFO для использования скриптом. По умолчанию: `.php`. resolve_root_symlink false # Отключает разрешение директории `root` до ее фактического значения путем оценки символической ссылки, если таковая существует (включено по умолчанию). env # Устанавливает дополнительную переменную окружения с заданным значением. Может быть указано несколько раз для нескольких переменных окружения. file_server off # Отключает встроенную директиву file_server. worker { # Создает worker, специфичный для этого сервера. Может быть указано несколько раз для нескольких workers. file # Устанавливает путь к worker-скрипту, может быть относительным к корню php_server num # Устанавливает количество запускаемых потоков PHP, по умолчанию 2x от числа доступных CPU. name # Устанавливает имя для worker, используемое в логах и метриках. По умолчанию: абсолютный путь к файлу worker. Всегда начинается с m# при определении в блоке php_server. watch # Устанавливает путь для отслеживания изменений файлов. Может быть указано несколько раз для нескольких путей. env # Устанавливает дополнительную переменную окружения с заданным значением. Может быть указано несколько раз для нескольких переменных окружения. Переменные окружения для этого worker также наследуются от родительского php_server, но могут быть переопределены здесь. match # сопоставляет worker с шаблоном пути. Переопределяет try_files и может использоваться только в директиве php_server. } worker # Также можно использовать краткую форму, как и в глобальном блоке frankenphp. } ``` ### Отслеживание изменений файлов Поскольку workers запускают ваше приложение только один раз и держат его в памяти, любые изменения в ваших PHP-файлах не будут отражены немедленно. Вместо этого workers могут быть перезапущены при изменении файлов с помощью директивы `watch`. Это полезно для сред разработки. ```caddyfile { frankenphp { worker { file /path/to/app/public/worker.php watch } } } ``` Эта функция часто используется в сочетании с [горячей перезагрузкой](hot-reload.md). Если директория для `watch` не указана, по умолчанию будет использоваться `./**/*.{env,php,twig,yaml,yml}`, который отслеживает все файлы с расширениями `.env`, `.php`, `.twig`, `.yaml` и `.yml` в директории и поддиректориях, где был запущен процесс FrankenPHP. Вы также можете указать одну или несколько директорий с использованием [шаблона имён файлов оболочки](https://pkg.go.dev/path/filepath#Match): ```caddyfile { frankenphp { worker { file /path/to/app/public/worker.php watch /path/to/app # отслеживает все файлы во всех поддиректориях /path/to/app watch /path/to/app/*.php # отслеживает файлы с расширением .php в /path/to/app watch /path/to/app/**/*.php # отслеживает PHP-файлы в /path/to/app и поддиректориях watch /path/to/app/**/*.{php,twig} # отслеживает PHP и Twig-файлы в /path/to/app и поддиректориях } } } ``` - Шаблон `**` указывает на рекурсивное отслеживание. - Директории также могут быть относительными (к месту запуска процесса FrankenPHP). - Если у вас определено несколько workers, все они будут перезапущены при изменении файлов. - Будьте осторожны с отслеживанием файлов, создаваемых во время выполнения (например, логов), так как это может вызвать нежелательные перезапуски workers. Механизм отслеживания файлов основан на [e-dant/watcher](https://github.com/e-dant/watcher). ## Сопоставление Worker с путем В традиционных PHP-приложениях скрипты всегда размещаются в публичной директории. Это также верно для worker-скриптов, которые обрабатываются как любые другие PHP-скрипты. Если вы хотите разместить worker-скрипт вне публичной директории, вы можете сделать это с помощью директивы `match`. Директива `match` является оптимизированной альтернативой `try_files`, доступной только внутри `php_server` и `php`. Следующий пример всегда будет обслуживать файл в публичной директории, если он присутствует, и в противном случае будет перенаправлять запрос worker, соответствующему шаблону пути. ```caddyfile { frankenphp { php_server { worker { file /path/to/worker.php # файл может находиться вне публичного пути match /api/* # все запросы, начинающиеся с /api/, будут обрабатываться этим worker } } } } ``` ## Переменные окружения Следующие переменные окружения могут быть использованы для внедрения директив Caddy в `Caddyfile` без его изменения: - `SERVER_NAME`: изменение [адресов для прослушивания](https://caddyserver.com/docs/caddyfile/concepts#addresses); предоставленные хостнеймы также будут использованы для генерации TLS-сертификата - `SERVER_ROOT`: изменение корневой директории сайта, по умолчанию `public/` - `CADDY_GLOBAL_OPTIONS`: внедрение [глобальных опций](https://caddyserver.com/docs/caddyfile/options) - `FRANKENPHP_CONFIG`: внедрение конфигурации под директиву `frankenphp` Как и для FPM и CLI SAPIs, переменные окружения по умолчанию доступны в суперглобальной переменной `$_SERVER`. Значение `S` в [директиве PHP `variables_order`](https://www.php.net/manual/en/ini.core.php#ini.variables-order) всегда эквивалентно `ES`, независимо от того, где расположена `E` в этой директиве. ## Конфигурация PHP Для загрузки [дополнительных конфигурационных файлов PHP](https://www.php.net/manual/en/configuration.file.php#configuration.file.scan) можно использовать переменную окружения `PHP_INI_SCAN_DIR`. Если она установлена, PHP загрузит все файлы с расширением `.ini`, находящиеся в указанных директориях. Вы также можете изменить конфигурацию PHP с помощью директивы `php_ini` в `Caddyfile`: ```caddyfile { frankenphp { php_ini memory_limit 256M # или php_ini { memory_limit 256M max_execution_time 15 } } } ``` ### Отключение HTTPS По умолчанию FrankenPHP автоматически включает HTTPS для всех хостнеймов, включая `localhost`. Если вы хотите отключить HTTPS (например, в среде разработки), вы можете установить переменную окружения `SERVER_NAME` в `http://` или `:80`: В качестве альтернативы вы можете использовать все другие методы, описанные в [документации Caddy](https://caddyserver.com/docs/automatic-https#activation). Если вы хотите использовать HTTPS с IP-адресом `127.0.0.1` вместо хостнейма `localhost`, пожалуйста, ознакомьтесь с разделом [известные проблемы](known-issues.md#using-https127001-with-docker). ### Полный дуплекс (HTTP/1) При использовании HTTP/1.x может быть желательно включить режим полного дуплекса, чтобы разрешить запись ответа до завершения чтения всего тела запроса. (например: [Mercure](mercure.md), WebSocket, Server-Sent Events и т.д.) Это конфигурация, которую необходимо добавить в глобальные опции в `Caddyfile`: ```caddyfile { servers { enable_full_duplex } } ``` > [!CAUTION] > > Включение этой опции может привести к зависанию устаревших HTTP/1.x клиентов, которые не поддерживают полный дуплекс. > Это также можно настроить с помощью переменной окружения `CADDY_GLOBAL_OPTIONS`: ```sh CADDY_GLOBAL_OPTIONS="servers { enable_full_duplex }" ``` Дополнительную информацию об этой настройке можно найти в [документации Caddy](https://caddyserver.com/docs/caddyfile/options#enable-full-duplex). ## Включение режима отладки При использовании Docker-образа установите переменную окружения `CADDY_GLOBAL_OPTIONS` в `debug`, чтобы включить режим отладки: ```console docker run -v $PWD:/app/public \ -e CADDY_GLOBAL_OPTIONS=debug \ -p 80:80 -p 443:443 -p 443:443/udp \ dunglas/frankenphp ``` ## Автодополнение команд оболочки FrankenPHP предоставляет встроенную поддержку автодополнения команд для Bash, Zsh, Fish и PowerShell. Это позволяет автоматически завершать все команды (включая пользовательские команды, такие как `php-server`, `php-cli` и `extension-init`) и их флаги. ### Bash Для загрузки автодополнения в текущую сессию оболочки: ```console source <(frankenphp completion bash) ``` Для загрузки автодополнения для каждой новой сессии выполните: **Linux:** ```console frankenphp completion bash > /usr/share/bash-completion/completions/frankenphp ``` **macOS:** ```console frankenphp completion bash > $(brew --prefix)/share/bash-completion/completions/frankenphp ``` ### Zsh Если автодополнение команд еще не включено в вашей среде, вам нужно будет его активировать. Вы можете выполнить следующее один раз: ```console echo "autoload -U compinit; compinit" >> ~/.zshrc ``` Чтобы загрузить автодополнение для каждой сессии, выполните один раз: ```console frankenphp completion zsh > "${fpath[1]}/_frankenphp" ``` Вам потребуется запустить новую оболочку, чтобы эти настройки вступили в силу. ### Fish Для загрузки автодополнения в текущую сессию оболочки: ```console frankenphp completion fish | source ``` Для загрузки автодополнения для каждой новой сессии выполните один раз: ```console frankenphp completion fish > ~/.config/fish/completions/frankenphp.fish ``` ### PowerShell Для загрузки автодополнения в текущую сессию оболочки: ```powershell frankenphp completion powershell | Out-String | Invoke-Expression ``` Для загрузки автодополнения для каждой новой сессии выполните один раз: ```powershell frankenphp completion powershell | Out-File -FilePath (Join-Path (Split-Path $PROFILE) "frankenphp.ps1") Add-Content -Path $PROFILE -Value '. (Join-Path (Split-Path $PROFILE) "frankenphp.ps1")' ``` Вам потребуется запустить новую оболочку, чтобы эти настройки вступили в силу. Вам потребуется запустить новую оболочку, чтобы эти настройки вступили в силу.