Перейти к содержимому
PHP Ecosystem
Explore

Configuring PHP for production

Это содержимое пока не доступно на вашем языке.

Configure the PHP runtime that serves your application, then verify its behavior through that runtime. This recipe targets up-to-date Yii 2.0 and Yii 22.0 applications behind nginx and PHP-FPM. Use it alongside VPS hardening with Tailscale and Cloudflare.

Reviewed on 2026-10-23. The security notice below is time-sensitive; check the linked PHP advisories before applying it later. These settings complement updates and application security; they are not a universal php.ini replacement.

1. Identify the serving runtime and configuration

Section titled “1. Identify the serving runtime and configuration”

Work on the server through your administration connection, or use the equivalent settings in your hosting control panel. PHP’s server interface (SAPI) is the way it runs: CLI handles terminal commands, while FPM serves web requests. An FPM pool groups PHP worker processes that share configuration.

Record the PHP service, executable, FPM pool, socket, package version, and configuration files for each application instance. Match nginx’s fastcgi_pass to that pool. A machine can serve several PHP versions simultaneously; php -v and php --ini describe the selected CLI executable, not necessarily the website.

Inspect the service’s startup arguments and its configuration file selection. Record the loaded php.ini and additional startup .ini files, then review pool overrides and any FastCGI PHP_VALUE or PHP_ADMIN_VALUE parameters. Back up the affected files and arrange a maintenance or rolling-restart procedure before editing.

Use PHP’s supported branches and the installed application’s Composer constraints. Yii’s master branch represents 2.0.x; it is distinct from 22.0. Both support the approach below, but their PHP requirements differ. Do not use a framework’s historical minimum PHP version as a production support recommendation.

On Debian/Ubuntu, a PHP 8.4 installation might use /etc/php/8.4/fpm/php.ini and /etc/php/8.4/fpm/pool.d/www.conf. These are examples, not paths to copy without checking. In managed hosting, ask the provider which settings apply before request parsing and how to restart all workers.

Stop if the public request cannot be mapped to its actual service and pool. Ask the server operator to identify them before editing files or restarting services.

2. Apply the security updates and current upload-progress precaution

Section titled “2. Apply the security updates and current upload-progress precaution”

The 21 October security release provides PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35 for CVE-2026-109618 and CVE-2026-109619. Update each serving runtime to a fixed release or verify the equivalent vendor backport. Choose a branch compatible with your application; this list does not override Yii’s PHP requirement.

The 23 October notice separately recommends disabling session upload progress until the next regular bugfix release. CVE-2026-115560 concerns an unusual combination: configuration selects php_binary or php_serialize, application code switches to php with ini_set() before session_start(), and upload progress remains enabled. Code that never switches handlers at runtime is outside that stated case. Do not assume the 21 October releases also resolve this later notice.

Replace the effective setting in the serving SAPI’s startup php.ini or a confirmed startup .ini file:

session.upload_progress.enabled = 0

Alternatively, enforce it in every affected FPM pool using pool syntax:

php_admin_flag[session.upload_progress.enabled] = off

Choose an authoritative location and remove conflicting overrides. Pool php_admin_* settings cannot be changed with ini_set(); bare PHP directives do not belong directly in an FPM pool file. See FPM configuration.

This directive is INI_PERDIR, not runtime-changeable. The stale-state advisory requires a setting effective before request parsing and a restart of every PHP worker. Neither a Yii bootstrap ini_set() nor FPM .user.ini is sufficient for this mitigation. Apply the restart and verification in step 7 before treating it as effective.

Disabling this feature removes PHP’s session-based upload-progress tracking, not ordinary file uploads. Test progress displays and cancellation flows that relied on it. Keep the existing session serializer; changing serialization formats blindly can invalidate stored sessions. Review application and dependency code for runtime serializer changes. Re-enable progress only after verifying the later fix and a real application requirement.

Treat this as an incident response decision, separate from the production baseline. The OOM advisory describes administratively enforced memory_limit=-1 as an incomplete workaround for one vulnerable path, with independent request and process-memory controls. It increases availability risk and is not a general tuning recommendation. An underlying allocation failure can still be vulnerable.

The stale-state advisory’s temporary measures, including fatal_error_backtraces=0 on affected PHP 8.5, cover specific paths rather than fixing the runtime. Hiding errors does not remediate these flaws. Use the complete vendor/advisory procedure; if exposure cannot be controlled, take the affected service out of traffic until it can be updated.

In the serving startup INI, use this small error-handling baseline:

display_errors = Off
display_startup_errors = Off
log_errors = On
error_reporting = E_ALL
zend.exception_ignore_args = On

Choose an error_log destination outside the public directory, or the appropriate system logging destination. Verify write access, retention, rotation, and alert delivery. zend.exception_ignore_args reduces argument disclosure in exception traces; it does not redact application logs. Exclude credentials, session identifiers, and request bodies from routine logs.

In Yii’s entry script, ensure YII_DEBUG is false and YII_ENV is prod before loading Yii. Review production bootstrap/modules so debug and Gii are not exposed. Check Yii’s own log targets and error views too; PHP’s display setting alone does not configure the application’s error response.

Verify a controlled failure in staging produces a generic response and a useful private log entry. Do not deploy an intentional public error endpoint to test this.

Section titled “4. Set session and cookie behavior for the application”

For an HTTPS-only application, start with these session settings in its serving INI:

session.use_cookies = 1
session.use_only_cookies = 1
session.use_strict_mode = 1
session.cookie_secure = 1
session.cookie_httponly = 1

Review Yii’s session component, especially cookieParams and useStrictMode, because application configuration can change these runtime values. Confirm the final Set-Cookie attributes after login. With custom session storage, verify that the handler validates uninitialized session IDs; an enabled INI flag alone is not proof. See PHP’s strict-mode caveat and Yii sessions.

Choose session.cookie_samesite for the actual browser flows. Lax is a useful starting point for many applications, but cross-site POST callbacks can require a different policy. Test SSO and payments before selecting Lax or Strict; flows requiring None must also use Secure and their protocol’s CSRF/state protections. Keep Yii’s CSRF protection enabled. Scope cookie domain/path and session storage to the application rather than sharing them by accident.

Test login, logout, session renewal, expiration, and concurrent requests. Behind Cloudflare, confirm Yii detects HTTPS correctly using the nginx/FPM setup; broad proxy-header trust is not a cookie fix.

5. Choose limits from legitimate traffic and measured capacity

Section titled “5. Choose limits from legitimate traffic and measured capacity”

Set limits in the startup INI or appropriate pool configuration after measuring normal requests and uploads. Use PHP’s directive reference to check each setting’s scope.

Setting or controlHow to choose and verify it
upload_max_filesize, post_max_size, max_file_uploadsAllow required files and the complete multipart body, including overhead. Keep post_max_size above upload_max_filesize; test both valid and excessive uploads.
max_input_vars, max_input_nesting_levelAccommodate real forms while bounding unexpected input. Verify truncation cannot turn a rejected submission into a partial update.
memory_limitUse a finite budget on patched PHP, informed by request measurements. Include image processing/import peaks; do not treat the PHP setting as an exact operating-system memory ceiling.
Execution/input timeouts and FPM request_terminate_timeoutCoordinate PHP, upstream, and application deadlines. Put long-running jobs in a separate worker workflow; test cleanup after interruption.

An oversized POST can leave $_POST and $_FILES empty. Return a clear error rather than interpreting it as a valid empty submission. Align web-server/proxy and application limits; a header-only Content-Length check is insufficient for all requests. Keep upload temporary storage writable by the pool user, outside the public tree, and monitor free space. Preserve legitimate uploads unless the application does not need them.

Size FPM pm.max_children from measured worker memory, expected concurrency, and the memory reserved for the OS and other services. Load-test and observe saturation rather than copying a worker count. Review slow requests privately. Keep FPM reachable only by its intended frontend; a separate pool does not provide complete isolation from other pools.

6. Make OPcache match the deployment procedure

Section titled “6. Make OPcache match the deployment procedure”

Confirm OPcache is installed and enabled in the web SAPI. A CLI check or reset does not establish the state of the serving FPM instance.

Keep opcache.validate_timestamps=1 unless the deployment system explicitly invalidates the relevant cache or replaces the serving processes on every deployment and rollback. With timestamp checking disabled, copying corrected files may leave old code executing. Size OPcache memory and script capacity from observations; preserve comments if dependencies use annotations. Avoid introducing JIT or preloading solely as a generic production switch. See OPcache configuration.

7. Validate, restart all workers, and check real requests

Section titled “7. Validate, restart all workers, and check real requests”

For a confirmed Debian/Ubuntu service named php8.4-fpm using its default configuration, this example tests the configuration and restarts the service only if the test passes:

Terminal window
sudo php-fpm8.4 -t && sudo systemctl restart php8.4-fpm

Replace the version and service with the ones identified in step 1. If the service uses custom configuration arguments such as -y, -c, or -d, reproduce those in the validation command. A restart can interrupt requests: use the maintenance or rolling-restart procedure prepared earlier.

  1. Validate the edited configuration with the actual installed FPM binary and configuration path. Resolve unknown directives and startup warnings. Stop on validation failure; restore the saved configuration or correct it before proceeding.
  2. Apply the change to every relevant service, pool, container, and replica. For the security update and upload-progress mitigation, restart all PHP workers and verify the old processes have exited. Restarting nginx alone does not replace PHP-FPM workers; a successful reload command alone does not prove they are gone.
  3. Through a private request handled by each serving configuration, inspect only PHP_VERSION, PHP_SAPI, php_ini_loaded_file(), php_ini_scanned_files(), and an explicit allowlist of the changed directives using ini_get(). Use existing protected instrumentation, or record this small diagnostic in a private server log from an existing application route. Do not add an executable PHP file to the public directory, publish phpinfo(), dump the environment, or return secrets. Restrict access and remove temporary instrumentation afterward. Without access to a private check, ask the operator to run it; configuration-file inspection alone does not verify the serving runtime.
  4. Confirm upload progress is disabled and trace that value to startup/pool configuration. A runtime readback cannot prove when a value took effect: .user.ini can make a late value look correct. For other runtime-changeable settings, also check after Yii has initialized. Match the serving package to the vendor’s security-fix evidence; its version string alone may not identify a backport.
  5. Exercise normal pages, HTTPS redirects, login/logout, SSO, file uploads, deliberate limit violations, and application error handling. Verify cookies, private logs, resource usage, and the deployed application version. Do not use an exploit payload as a configuration test.

If checks fail, keep the affected instance out of traffic and recover a known working, patched configuration. Preserve required security mitigations during rollback; do not restore a vulnerable runtime merely to make a health check pass.