php-lsapi compiles .user.ini support in but leaves it disabled by default — sapi/litespeed/lsapi_main.c has static int parse_user_ini = 0; and only sets it when the process env contains LSPHP_ENABLE_USER_INI=on. WHP never set it, so lsphp never entered the user-ini chain.
The failure is silent: phpinfo() still reports user_ini.filename=.user.ini and user_ini.cache_ttl=300, because those are core INI defaults that are inert under this SAPI. Every other WHP PHP tier (cac, cac-fpm, cac-litespeed) honors .user.ini, so shared_ols was quietly inconsistent.
Production impact (29 sites across whp01/whp02/sdbees/TrueSelfCA)
Wordfence auto_prepend_file WAF never loaded on ANY shared_ols site. 11 sites had the plugin installed and reporting Extended Protection enabled while the prepend never executed.
Verified live before committing
Injected the env var via whp.container_types.startup_env and recreated shadowdao.com-01 on whp01:
The platform normalize prepend still chains in behind Wordfence bootstrap, so DOCUMENT_ROOT canonicalisation is not lost.
Why two places
ENV in the Dockerfile makes it visible in docker inspect and survives an entrypoint override; the entrypoint re-exports it with the same default because the runuser fallback exec path resets the environment. Still overridable per-container (LSPHP_ENABLE_USER_INI=off) as an escape hatch.
Rollout warning
Enabling this activates every previously-inert .user.ini at once. A fleet audit found and remediated stale cPanel directives first: session.save_path under /var/cpanel/ (absent in container) on 3 sites, upload_max_filesize = 500 (500 bytes) on 1, memory_limit above the cgroup cap on 2, and upload_max_filesize/post_max_sizebelow platform defaults on 1. Those are already fixed on whp01/whp02; sdbees and TrueSelfCA have no .user.ini files at all.
php-lsapi compiles `.user.ini` support in but leaves it **disabled by default** — `sapi/litespeed/lsapi_main.c` has `static int parse_user_ini = 0;` and only sets it when the process env contains `LSPHP_ENABLE_USER_INI=on`. WHP never set it, so lsphp never entered the user-ini chain.
The failure is silent: `phpinfo()` still reports `user_ini.filename=.user.ini` and `user_ini.cache_ttl=300`, because those are core INI defaults that are inert under this SAPI. Every other WHP PHP tier (cac, cac-fpm, cac-litespeed) honors `.user.ini`, so shared_ols was quietly inconsistent.
## Production impact (29 sites across whp01/whp02/sdbees/TrueSelfCA)
- Per-site `memory_limit` / `max_input_vars` overrides ignored.
- **Wordfence `auto_prepend_file` WAF never loaded on ANY shared_ols site.** 11 sites had the plugin installed and reporting Extended Protection enabled while the prepend never executed.
## Verified live before committing
Injected the env var via `whp.container_types.startup_env` and recreated `shadowdao.com-01` on whp01:
```
before: auto_prepend_file=/scripts/cac-lsphp-normalize.php (WAF absent)
after: auto_prepend_file=/home/shadowdao/public_html/wordfence-waf.php
wordfence-waf.php present in get_included_files()
class_exists(wfWAF) === true
```
The platform normalize prepend still chains in behind Wordfence bootstrap, so `DOCUMENT_ROOT` canonicalisation is not lost.
## Why two places
`ENV` in the Dockerfile makes it visible in `docker inspect` and survives an entrypoint override; the entrypoint re-exports it with the same default because the `runuser` fallback exec path resets the environment. Still overridable per-container (`LSPHP_ENABLE_USER_INI=off`) as an escape hatch.
## Rollout warning
Enabling this activates every previously-inert `.user.ini` at once. A fleet audit found and remediated stale cPanel directives first: `session.save_path` under `/var/cpanel/` (absent in container) on 3 sites, `upload_max_filesize = 500` (500 *bytes*) on 1, `memory_limit` above the cgroup cap on 2, and `upload_max_filesize`/`post_max_size` *below* platform defaults on 1. Those are already fixed on whp01/whp02; sdbees and TrueSelfCA have no `.user.ini` files at all.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
php-lsapi compiles .user.ini support in but leaves it DISABLED by default.
sapi/litespeed/lsapi_main.c has `static int parse_user_ini = 0;` and only
sets it when the process environment contains LSPHP_ENABLE_USER_INI=on.
WHP never set it, so lsphp never entered the user-ini chain at all.
The failure was silent: phpinfo() still reports user_ini.filename=.user.ini
and user_ini.cache_ttl=300, because those are core INI defaults that are
simply inert under this SAPI. Every other WHP PHP tier (cac, cac-fpm,
cac-litespeed) honors .user.ini, so shared_ols was quietly inconsistent.
Impact found in production (whp01/whp02/sdbees/TrueSelfCA, 29 sites):
- Per-site memory_limit / max_input_vars overrides were ignored. A Divi
site's max_input_vars stayed at the 2000 default while its .user.ini
asked for 20000.
- Wordfence's auto_prepend_file WAF never loaded on ANY shared_ols site.
11 sites had the plugin installed and reporting "Extended Protection"
enabled while the prepend was never executed.
Verified on a live sidecar (shadowdao.com, whp01) before this commit by
injecting the env var via whp.container_types.startup_env and recreating:
before: auto_prepend_file=/scripts/cac-lsphp-normalize.php (WAF absent)
after: auto_prepend_file=/home/shadowdao/public_html/wordfence-waf.php
wordfence-waf.php present in get_included_files()
class_exists('wfWAF') === true
The platform normalize prepend still chains in behind Wordfence's bootstrap,
so DOCUMENT_ROOT canonicalisation is not lost.
Set in two places on purpose: the Dockerfile ENV makes the value visible in
`docker inspect` and survives an entrypoint override, and the entrypoint
re-exports it with the same default because the runuser fallback exec path
resets the environment. Still overridable per-container
(LSPHP_ENABLE_USER_INI=off) as an escape hatch for a site whose legacy
cPanel-generated .user.ini has not been remediated yet.
NOTE: enabling this activates every previously-inert .user.ini at once.
Audit the fleet for stale cPanel directives before rolling this image —
session.save_path values under /var/cpanel/ that do not exist in the
container, memory_limit above the cgroup cap, and upload_max_filesize
values below the platform default were all found and remediated first.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jknapp
merged commit 03b8f3f730 into trunk2026-08-02 22:38:03 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
php-lsapi compiles
.user.inisupport in but leaves it disabled by default —sapi/litespeed/lsapi_main.chasstatic int parse_user_ini = 0;and only sets it when the process env containsLSPHP_ENABLE_USER_INI=on. WHP never set it, so lsphp never entered the user-ini chain.The failure is silent:
phpinfo()still reportsuser_ini.filename=.user.inianduser_ini.cache_ttl=300, because those are core INI defaults that are inert under this SAPI. Every other WHP PHP tier (cac, cac-fpm, cac-litespeed) honors.user.ini, so shared_ols was quietly inconsistent.Production impact (29 sites across whp01/whp02/sdbees/TrueSelfCA)
memory_limit/max_input_varsoverrides ignored.auto_prepend_fileWAF never loaded on ANY shared_ols site. 11 sites had the plugin installed and reporting Extended Protection enabled while the prepend never executed.Verified live before committing
Injected the env var via
whp.container_types.startup_envand recreatedshadowdao.com-01on whp01:The platform normalize prepend still chains in behind Wordfence bootstrap, so
DOCUMENT_ROOTcanonicalisation is not lost.Why two places
ENVin the Dockerfile makes it visible indocker inspectand survives an entrypoint override; the entrypoint re-exports it with the same default because therunuserfallback exec path resets the environment. Still overridable per-container (LSPHP_ENABLE_USER_INI=off) as an escape hatch.Rollout warning
Enabling this activates every previously-inert
.user.iniat once. A fleet audit found and remediated stale cPanel directives first:session.save_pathunder/var/cpanel/(absent in container) on 3 sites,upload_max_filesize = 500(500 bytes) on 1,memory_limitabove the cgroup cap on 2, andupload_max_filesize/post_max_sizebelow platform defaults on 1. Those are already fixed on whp01/whp02; sdbees and TrueSelfCA have no.user.inifiles at all.🤖 Generated with Claude Code
php-lsapi compiles .user.ini support in but leaves it DISABLED by default. sapi/litespeed/lsapi_main.c has `static int parse_user_ini = 0;` and only sets it when the process environment contains LSPHP_ENABLE_USER_INI=on. WHP never set it, so lsphp never entered the user-ini chain at all. The failure was silent: phpinfo() still reports user_ini.filename=.user.ini and user_ini.cache_ttl=300, because those are core INI defaults that are simply inert under this SAPI. Every other WHP PHP tier (cac, cac-fpm, cac-litespeed) honors .user.ini, so shared_ols was quietly inconsistent. Impact found in production (whp01/whp02/sdbees/TrueSelfCA, 29 sites): - Per-site memory_limit / max_input_vars overrides were ignored. A Divi site's max_input_vars stayed at the 2000 default while its .user.ini asked for 20000. - Wordfence's auto_prepend_file WAF never loaded on ANY shared_ols site. 11 sites had the plugin installed and reporting "Extended Protection" enabled while the prepend was never executed. Verified on a live sidecar (shadowdao.com, whp01) before this commit by injecting the env var via whp.container_types.startup_env and recreating: before: auto_prepend_file=/scripts/cac-lsphp-normalize.php (WAF absent) after: auto_prepend_file=/home/shadowdao/public_html/wordfence-waf.php wordfence-waf.php present in get_included_files() class_exists('wfWAF') === true The platform normalize prepend still chains in behind Wordfence's bootstrap, so DOCUMENT_ROOT canonicalisation is not lost. Set in two places on purpose: the Dockerfile ENV makes the value visible in `docker inspect` and survives an entrypoint override, and the entrypoint re-exports it with the same default because the runuser fallback exec path resets the environment. Still overridable per-container (LSPHP_ENABLE_USER_INI=off) as an escape hatch for a site whose legacy cPanel-generated .user.ini has not been remediated yet. NOTE: enabling this activates every previously-inert .user.ini at once. Audit the fleet for stale cPanel directives before rolling this image — session.save_path values under /var/cpanel/ that do not exist in the container, memory_limit above the cgroup cap, and upload_max_filesize values below the platform default were all found and remediated first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>