Files
RustProxy/docs/PHP_FPM_ISOLATION.md
T
2026-10-10 00:18:06 +02:00

4.1 KiB

Dedicated PHP-FPM pools for distinct Web Services

PHP-FPM may retain request-supplied PHP_VALUE and PHP_ADMIN_VALUE directives in long-lived workers. When two applications use one PHP-FPM socket but different INI overrides, a setting such as open_basedir can be inherited by the next request, even when RustProxy routes the request to the correct Web Service. RustProxy cannot provide process-level isolation inside a shared external PHP-FPM worker.

Affected operator configuration (0.29.6)

  • WordPress Web Service blog-linuxiarz-pl uses document root /var/www/linuxiarz.pl/ and endpoint unix:/run/php/php_rustproxy.sock, without an open_basedir override.
  • Roundcube Web Service webmail-linuxiarz-pl uses document root /var/www/webmail/public_html and the same endpoint. Its FastCGI PHP_ADMIN_VALUE includes open_basedir=/var/www/webmail/:/usr/lib/php/:/tmp/:/etc/enigma:....
  • WordPress PHP-FPM stderr confirms the Roundcube open_basedir at the WordPress file check. As a result, wp-config.php is not visible and WordPress redirects to /wp-admin/setup-config.php before triggering fatal errors. This is not a cache MISS defect.

Required operator remediation

  1. Back up the current FPM configuration. Provision separate, access-restricted PHP-FPM pools under the PHP-FPM service manager used by your system (NixOS configuration when applicable). Use distinct Unix sockets, for example /run/php/php_wordpress.sock and /run/php/php_roundcube.sock. Ensure RustProxy's runtime user may connect to both. Do not expose raw FastCGI publicly.
  2. Configure pool-level php_admin_value[open_basedir] for Roundcube only, with exactly the filesystem paths it requires, or keep its validated override in RustProxy on a dedicated pool. Keep WordPress in its own pool with appropriate policy. Pool-level directives are preferable to request-supplied administrator directives for security-sensitive settings.
  3. In Web Server > Web Services set blog-linuxiarz-pl > PHP-FPM endpoint to unix:/run/php/php_wordpress.sock and webmail-linuxiarz-pl to unix:/run/php/php_roundcube.sock. Shared PHP-FPM profiles must also refer to the corresponding correct endpoint.
  4. Apply PHP-FPM configuration and restart the affected PHP-FPM service/pools to retire workers with leaked directives. Save the RustProxy Web Service changes. Check that both web apps respond and that private files remain blocked.
  5. Repeat requests in alternating order from both vhosts and inspect PHP-FPM warnings. Suggested tests: curl -I https://blog.linuxiarz.pl/, curl -I https://blog.linuxiarz.pl/wp-login.php, curl -I https://webmail.linuxiarz.pl/. The WordPress home page must no longer redirect to /wp-admin/setup-config.php due to open_basedir.

If WordPress still redirects to setup-config.php with a dedicated pool, check whether wp-config.php really exists and is readable by the pool user, the configured pool's own php_admin_value restrictions, and database credentials. Do not fix the issue by using unrestricted open_basedir=/ globally or by disabling protections on Roundcube.

New 0.29.7 protection

During configuration compilation, RustProxy emits a warning identifying pairs of Web Services sharing an endpoint with unequal PHP_VALUE/PHP_ADMIN_VALUE maps. For backward compatibility, the existing configuration remains loadable; the warning does not automatically rewrite operator FPM configuration or claim that sharing becomes safe.

Per-backend health

For an internal 404 response origin, leave pool_eligible: false, set health_check_enabled: false, and continue routing a named internal location to its backend_id. If a backend does require separate probes, use an optional per-member health_check object (same shape as vhost load_balancing.health_check).

HIT-only cache diagnostic headers

Enable global cache.expose_only_hits: true, optionally override each vhost at vhosts[].cache.expose_only_hits. HIT-only mode filters RustProxy diagnostic cache headers for MISS/BYPASS without altering internal hit/miss metrics or upstream cache eligibility. Via is a separate proxy-header option and can be disabled using cache.via_header: null.