Files
cloud-apache-container/scripts/entrypoint-lsphp.sh
jknapp 19092911a3 feat(cac-lsphp): detached lsphp (LSAPI) site image for the shared-ols tier
New slim per-site PHP backend that runs 'lsphp -b 0.0.0.0:9000' (detached
LSAPI) and nothing else — the LiteSpeed analogue of cac-fpm, sitting behind
a shared OpenLiteSpeed container. Built on the same litespeedtech prebuilt
base as cac-litespeed so the lsphp runtime/extensions are identical.

- Dockerfile.lsphp: base + lsphpNN-ldap parity, reuses shared lsphp-overrides.ini,
  exposes only :9000, no webserver started (guaranteed by entrypoint, not by
  stripping OLS binaries).
- entrypoint-lsphp.sh: same uid/user contract + /home/$user/logs layout +
  ini drop-in mechanism as entrypoint-litespeed.sh; sizes PHP_LSAPI_CHILDREN
  from container memory (detect-memory-lsphp.sh) with panel override precedence;
  execs lsphp -b as the per-site user via setpriv (PID 1).
- detect-memory-lsphp.sh: LSAPI_CHILDREN sizing, no OLS daemon reserve.
- healthcheck-lsphp.sh: TCP :9000 + lsphp-alive (LSAPI isn't FastCGI).
- CI: Build-LSPHP-Images job, php81-85 matrix, OLS 1.8.4, cac-lsphp:phpNN.

Verified locally: builds php83+php85; sidecar runs lsphp as the per-site
user (uid 61045) as PID 1, healthcheck green, and a real shared OLS in front
serves PHP over LSAPI (HTTP 200, SAPI=litespeed) with identical docroot path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 18:28:34 -07:00

107 lines
4.9 KiB
Bash

#!/usr/bin/env bash
## entrypoint-lsphp.sh — PID 1 for cac-lsphp:phpNN.
##
## The per-site PHP backend for the SHARED OpenLiteSpeed tier. Runs lsphp in
## DETACHED LSAPI mode (`lsphp -b <addr:port>`) and nothing else — no
## webserver. The shared-ols container connects to this over the docker
## network (extProcessor type lsapi, address <this-container>:9000) exactly
## like the shared httpd connects to a cac-fpm container's php-fpm on :9000.
##
## Structurally this is the LiteSpeed analogue of entrypoint-fpm.sh: same
## `uid`/`user` contract, same /home/$user/{public_html,logs} layout, same
## per-site ini drop-in mechanism as entrypoint-litespeed.sh. The only
## difference from cac-litespeed is that OLS lives elsewhere, so this PID 1 is
## lsphp itself rather than a webserver supervisor.
##
## IMPORTANT (see whp memory feedback_ols_lsapi_no_script_filename_remap):
## OLS hands lsphp exactly its vhost docRoot path, so the shared-ols vhost
## docRoot and THIS container's docroot mount MUST be the same absolute path.
## The panel mounts the site at /mnt/users/<user>/<domain> in BOTH containers;
## this entrypoint does not assume any particular path — it just runs lsphp,
## which opens whatever absolute SCRIPT_FILENAME the webserver sends.
set -euo pipefail
: "${PHPVER:=83}"
: "${environment:=PROD}"
export CONTAINER_ROLE="lsphp_only"
export PHPVER environment
## ---- env validation (same contract as entrypoint-fpm / entrypoint-litespeed) ----
if [ -z "${uid:-}" ] || [ -z "${user:-}" ]; then
echo "FATAL: 'uid' and 'user' env vars are required (panel sets these from WHP_UID/WHP_USER)." >&2
exit 1
fi
export user
LSPHP_BIN="/usr/local/lsws/lsphp${PHPVER}/bin/lsphp"
if [ ! -x "$LSPHP_BIN" ]; then
echo "FATAL: lsphp binary not found at $LSPHP_BIN (PHPVER=$PHPVER)." >&2
exit 1
fi
## ---- user + directories (mirror entrypoint-litespeed.sh paths) ----
if ! id -u "$user" >/dev/null 2>&1; then
useradd -u "$uid" -m -s /bin/bash "$user"
fi
mkdir -p "/home/$user/public_html" "/home/$user/logs/php-fpm"
## ---- detached-lsphp pool sizing ----
# shellcheck source=/dev/null
source /scripts/detect-memory-lsphp.sh
## LSAPI tuning (spec §5.1). PHP_LSAPI_CHILDREN MUST equal the shared-ols vhost
## maxConns — the WHP panel writes both from the single fpm_max_children value,
## so they can't drift. LSAPI_MAX_IDLE is THE RAM win: idle children exit, so an
## idle site's footprint collapses toward baseline (ondemand-like).
export PHP_LSAPI_CHILDREN="${PHP_LSAPI_CHILDREN:-$LSAPI_CHILDREN}"
export PHP_LSAPI_MAX_REQUESTS="${PHP_LSAPI_MAX_REQUESTS:-500}"
export LSAPI_MAX_IDLE="${LSAPI_MAX_IDLE:-30}"
export LSAPI_EXTRA_CHILDREN="${LSAPI_EXTRA_CHILDREN:-5}"
export LSAPI_AVOID_FORK="${LSAPI_AVOID_FORK:-0}"
LSPHP_BIND="${LSPHP_BIND:-0.0.0.0:9000}"
echo "Container memory: ${CONTAINER_MEMORY_MB}MB | PHP_LSAPI_CHILDREN=${PHP_LSAPI_CHILDREN} | LSAPI_MAX_IDLE=${LSAPI_MAX_IDLE} | PHPVER=${PHPVER} | bind=${LSPHP_BIND}"
## ---- per-site ini drop-ins (identical mechanism to entrypoint-litespeed.sh) ----
## error_log → the same customer-visible path cac:phpNN / cac-litespeed use, so
## "where's my PHP error log?" is answered identically across all site types.
SCAN_DIR=$("$LSPHP_BIN" -i 2>/dev/null | awk -F'=> ' '/^Scan this dir/ {print $2; exit}')
if [ -n "$SCAN_DIR" ]; then
mkdir -p "$SCAN_DIR"
cat > "$SCAN_DIR/99-user-error-log.ini" <<EOF
; rendered at container start by entrypoint-lsphp.sh
error_log = /home/${user}/logs/php-fpm/error.log
log_errors = On
EOF
## Per-site opcache override (panel: Advanced Tuning → OpCache size); falls
## back to the baked lsphp-overrides.ini defaults when unset.
if [ -n "${OPCACHE_MEMORY_MB:-}" ] || [ -n "${OPCACHE_MAX_FILES:-}" ]; then
{
echo "; rendered at container start by entrypoint-lsphp.sh"
echo "; per-site override from WHP whp.sites.opcache_*_override"
[ -n "${OPCACHE_MEMORY_MB:-}" ] && echo "opcache.memory_consumption = ${OPCACHE_MEMORY_MB}"
[ -n "${OPCACHE_MAX_FILES:-}" ] && echo "opcache.max_accelerated_files = ${OPCACHE_MAX_FILES}"
} > "$SCAN_DIR/99-user-opcache.ini"
fi
fi
## ---- ownership ----
touch "/home/$user/logs/php-fpm/error.log"
chown -R "$user:$user" "/home/$user"
chmod 755 "/home/$user"
## ---- exec lsphp -b as the customer user (PID 1) ----
## Bind port is unprivileged (9000), so no root port-bind step is needed — start
## directly as $user. Prefer setpriv (util-linux, on the Ubuntu base); fall back
## to runuser. exec so lsphp becomes PID 1 and receives Docker's signals
## directly (clean stop/restart, matches the php-fpm container's lifecycle).
echo "entrypoint-lsphp: exec $LSPHP_BIN -b $LSPHP_BIND as $user (uid=$uid)"
if command -v setpriv >/dev/null 2>&1; then
exec setpriv --reuid "$uid" --regid "$uid" --init-groups "$LSPHP_BIN" -b "$LSPHP_BIND"
elif command -v runuser >/dev/null 2>&1; then
exec runuser -u "$user" -- "$LSPHP_BIN" -b "$LSPHP_BIND"
else
exec sudo -u "$user" -E "$LSPHP_BIN" -b "$LSPHP_BIND"
fi