feat(roles/php): allow for PHP-FPM pools to be configured individually. - #248
Merged
Conversation
Contributor
Author
|
Contributor
Author
|
the systemd service on debian (php 8.4, sury repo) contains Debian
[Unit]
Description=The PHP 8.4 FastCGI Process Manager
Documentation=man:php-fpm8.4(8)
After=network.target
[Service]
Type=notify
ExecStart=/usr/sbin/php-fpm8.4 --nodaemonize --fpm-config /etc/php/8.4/fpm/php-fpm.conf
ExecStartPost=-/usr/lib/php/php-fpm-socket-helper install /run/php/php-fpm.sock /etc/php/8.4/fpm/pool.d/www.conf 84
ExecStopPost=-/usr/lib/php/php-fpm-socket-helper remove /run/php/php-fpm.sock /etc/php/8.4/fpm/pool.d/www.conf 84
ExecReload=/bin/kill -USR2 $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.targetRocky
# It's not recommended to modify this file in-place, because it
# will be overwritten during upgrades. If you want to customize,
# the best way is to use the "systemctl edit" command.
[Unit]
Description=The PHP FastCGI Process Manager
After=network.target
[Service]
Type=notify
ExecStart=/usr/sbin/php-fpm --nodaemonize
ExecReload=/bin/kill -USR2 $MAINPID
PrivateTmp=true
RuntimeDirectory=php-fpm
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target |
NavidSassan
force-pushed
the
feat/php_fpm_pool
branch
2 times, most recently
from
September 2, 2026 16:27
1d4e762 to
458f002
Compare
One pool template replaces the per-family Debian-pool.conf.j2 and RedHat-pool.conf.j2, and every pool carries its own user and group, process manager tuning, timeouts and php_admin_value overrides, so several applications can share a host without sharing a PHP process, a session store or a memory limit. Each pool gets an isolated session directory below the distribution session base, its own error and slow log in the per-service log directory, and its own socket. The role creates those directories, relabels them on SELinux hosts, and ships a logrotate config on Debian, where the packaged one only covers the single global log file. pm.max_spawn_rate is only rendered from PHP 8.1 on. The directive does not exist before that and php-fpm refuses to start with "unknown entry", which would break RHEL 8 and RHEL 9 with their distribution PHP. Verified on Rocky 9: rejected by 8.0, accepted by 8.1.32. request_terminate_timeout defaults to 60s so a worker that outlives the web server timeout is reclaimed instead of occupying its slot indefinitely. The status and ping paths stay at /fpm-status and /fpm-ping for every pool: the path never distinguished pools, the socket does, and the Monitoring Plugins, their Director baskets and the localhost vHost of the apache_httpd role all default to those paths.
Role entry now validates the user-facing variables and rejects unknown ones. The numeric __ini_* and __fpm_pool_conf_* slots are declared as raw, since an int spec would reject their empty default. vars/Ubuntu.yml is an explicit copy of vars/Debian.yml, per CONTRIBUTING: it keeps Ubuntu visible and gives later Ubuntu-specific drift a home.
A second pool with a static process manager and its own php_admin_value memory limit is deployed alongside the default www pool, and both are asked what they are actually running through their own sockets. That proves the pool reached the running workers, that a pool cannot be raised past its php_admin_value with ini_set(), and that each pool keeps its own private session directory.
Both PHP-FPM URLs of the localhost vHost are served by the www pool. Document how a host with further pools publishes them, one Location per pool socket, keeping /fpm-status as the path sent to FPM.
…emplates Every php__ini_*__role_var the templates reference is set in each vars/<version>.yml, so the __combined_var always resolves and the inline defaults never applied. Rendered output is unchanged, verified byte for byte against a Rocky 9 host, hence no timestamp bump in the templates.
php_admin_value[session.save_handler] was hardcoded to files, which an application cannot override via ini_set() since it is a php_admin_value. A host that has to share sessions across machines, behind a load balancer or a TLS-terminating proxy, needs redis or memcached instead. A pool that stores its sessions elsewhere also gets no session directory: its save_path is a connection string, not a path.
…both families The template had two branches only because the two distribution default pool files differ: Debian hands the socket to the webserver via listen.owner / listen.group, RedHat grants an ACL entry via listen.acl_users. Both mechanisms work on both families, verified on Debian 13 with php-fpm 8.4 and on Rocky 9, so the role now uses one path. acl_users decouples socket access from the pool own identity, which is what per-pool users need: a pool running as its own user still hands the webserver an explicit ACL entry on a root-owned socket. It also takes a list, so a second webserver user is a value change rather than a template change. On Debian the socket therefore changes from www-data:www-data to root:root plus an ACL entry. Nothing in LFOps reads it: apache_httpd addresses the socket by path, and php-fpm-socket-helper parses the `listen =` line out of www.conf.
…d pool file Following the "Deviating from an Upstream Default" section of CONTRIBUTING.md, the packaged pool files are now vendored under vars/vendor/ as the baseline they are measured against, every remaining deviation carries an "upstream default" comment where the value is defined and a "Deviates from" bullet in the README, and the review turned up three changes worth making: listen.acl_users becomes a per-pool list. The RedHat package grants apache,nginx; the role grants only the webserver LFOps deploys and lets a host serving through another user add it, instead of editing the template. listen.allowed_clients is no longer rendered. php-fpm applies it to tcp sockets only, and every pool here listens on a unix socket, so the line looked like an access restriction while enforcing nothing. soap.wsdl_cache_dir is set again, per pool. Dropping it left the SOAP extension caching parsed WSDL files in /tmp, which on RedHat is the unit PrivateTmp namespace and therefore lost on every restart, and on Debian the shared /tmp. A cached WSDL carries the internal endpoints of the service it describes, so it gets the same per-pool treatment as the session directory. Verified on Rocky 9 with php-soap installed: the running worker reports the per-pool directory. Also removes a duplicated php__fpm_pools entry: the README documented it in two sections with two different defaults.
The php molecule scenario passes on rocky10-vm, converge, verify and idempotence, alongside the four targets already marked proven.
NavidSassan
force-pushed
the
feat/php_fpm_pool
branch
from
September 3, 2026 11:26
458f002 to
d827ff1
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.