feat: OLS tier images — cac-lsphp (detached lsphp) + shared-ols #19
Reference in New Issue
Block a user
Delete Branch "feature/cac-lsphp-image"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Container images for the new shared-OpenLiteSpeed site tier. Pairs with whp PR
feature/ols-lsphp-tier(panel side).What
lsphp -b :9000), the LiteSpeed analogue of cac-fpm. Mounts the docroot at/home/<user>(identical to existing tiers) and symlinks the OLS-sent/mnt/users/...path back, so PHP sees/home/<user>/public_html— a true 1:1 drop-in.include, sorender-shared-ols-config.shassembleshttpd_config.conffrom per-site files. Daemon-mode supervision,.htaccesswatcher, admin bound to loopback,:443self-signed.Build-LSPHP-Images(php81–85) +Build-Shared-OLS.Verified locally (end-to-end)
SAPI=litespeedmiss→hit;.htaccesschange → graceful restart; real client IP +HTTPS=on__FILE__/ABSPATH/realpath/DOCUMENT_ROOTall/home/<user>/public_htmlNot yet done
Live validation (test → whp02 → whp01) once CI pushes the registry tags. Design notes + reproducible PoC:
whp:docs/superpowers/plans/2026-06-09-ols-lsphp-tier.md.One OLS container fronting many tenants' detached cac-lsphp sidecars — the OLS analogue of shared-httpd. Runs NO PHP locally; every site's PHP goes to its own sidecar over LSAPI (extProcessor type lsapi, address <sidecar>:9000). Key design fact (established by PoC): OLS has NO top-level 'include' directive, so render-shared-ols-config.sh assembles httpd_config.conf from the panel's per-site files (vhconf.conf + site.meta) at boot and on every change — the 'include' OLS lacks. Per-site detail uses the OLS-native configFile + vhost-scoped extprocessor model. LSCache is module-level (a configFile-loaded vhost rejects a bare cache{} block); the WP LiteSpeed plugin controls cacheability via X-LiteSpeed-Cache-Control headers. - Dockerfile.shared-ols: litespeed base + inotify-tools/envsubst/openssl, admin bound to loopback, :80/:443 self-signed, healthz HEALTHCHECK. - entrypoint-shared-ols.sh: cert + health vhost + render + watcher, then daemon-mode OLS supervision (reused from cac-litespeed so self-restarts don't kill PID 1). - render-shared-ols-config.sh: strip stock (incl local lsphp) + append base + per-site stanzas + listeners with all maps + catch-all health vhost. - ols-htaccess-watcher.sh: inotify debounce+floor -> lswsctrl restart (spec 5.3). - configs/shared-ols/{httpd_config_base,vhconf}.tpl. - CI: Build-Shared-OLS job. Verified locally end-to-end: zero-site boot healthy on :443; add site via the panel contract -> Host-routed to the right sidecar (SAPI=litespeed); real client IP + HTTPS behind X-Forwarded headers; LSCache miss->hit; .htaccess change triggers graceful restart; unknown Host hits health catch-all (200). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Local code-review applied (commit
6bb494c)A multi-angle local review was run on this diff; the image-side findings are fixed:
.htaccesswatcher starvation — the debounce drain read all inotify events unfiltered, so on a busy multi-tenant host it never timed out and the restart was starved (rewrite changes silently never applied). Now hard-bounded toDEBOUNCE. Verified live under continuous file-write noise → the.htaccesschange still triggered exactly one restart.render-shared-ols-config.shbuilthttpd_config.confin-place across several appends, so a concurrent OLS restart (watcher) or a parallel render could read a half-written config and 503 the whole tier. Nowflock-serialized, built into a temp file and atomicallymv'd into place; refuses to publish empty.chown -Ron every single-site change/boot → targeted chown of only the file written.source-ing panel data —site.metais now parsed withsed, not sourced as shell.configs/shared-ols/vhconf.tpl(the panel copy is the single source of truth).Full E2E re-verified: render → OLS serves
SAPI=litespeedat the 1:1/home/<user>/public_htmlpath.Second review pass complete
A fresh multi-angle review was run on the updated diff (after the fix commits), with three checks: (a) confirm the prior findings are resolved, (b) hunt for regressions introduced by the fixes, (c) cross-file caller impact.
All 10 prior findings verified RESOLVED (re-read against the current code).
4 regressions the fixes introduced — now fixed (this push):
create_siteonly surfaced$container_errorson container-creation failure, so the new "shared_ols site left unrouted (tier down)" warning was swallowed exactly when containers came up fine. The success response now carries awarningsfield + appends to the message; thepages/sites.phpform-create path surfaces it too.render-shared-ols-config.shnow usesflock -w 30so a hung render can't block the panel'sdocker exec(and the site-save request) indefinitely.$$suffix).require_onceinside the bulk per-site loop → hoisted above the loop.Reviewed and accepted as-is (pre-existing or cosmetic, not regressions): custom
mount_optionsnetwork-path edge with${WHP_DOMAIN}(standard types are filesystem paths — the safe name is correct);${WHP_CONTAINER_NAME}token with raw wildcard domain (pre-existing; cac-lsphp's startup_env doesn't use it);inotifywaitorphan on SIGTERM (cosmetic, ms);isOlsLsphpImageregex requiring a registry prefix (consistent with the codebase; seeds always include it).All
php -l/bash -nclean; render + serve E2E re-verified.