All checks were successful
Cloud Apache Container / Build-and-Push (74) (push) Successful in 1m18s
Cloud Apache Container / Build-and-Push (80) (push) Successful in 2m14s
Cloud Apache Container / Build-and-Push (81) (push) Successful in 3m21s
Cloud Apache Container / Build-and-Push (82) (push) Successful in 2m18s
Cloud Apache Container / Build-and-Push (83) (push) Successful in 2m15s
Cloud Apache Container / Build-and-Push (84) (push) Successful in 2m11s
Cloud Apache Container / Build-and-Push (85) (push) Successful in 2m22s
Cloud Apache Container / Build-FPM-Images (74) (push) Successful in 4m22s
Cloud Apache Container / Build-FPM-Images (80) (push) Successful in 3m46s
Cloud Apache Container / Build-FPM-Images (81) (push) Successful in 1m17s
Cloud Apache Container / Build-FPM-Images (82) (push) Successful in 1m21s
Cloud Apache Container / Build-FPM-Images (83) (push) Successful in 2m15s
Cloud Apache Container / Build-FPM-Images (84) (push) Successful in 2m21s
Cloud Apache Container / Build-FPM-Images (85) (push) Successful in 3m29s
Cloud Apache Container / Build-LiteSpeed-Images (81) (push) Successful in 31s
Cloud Apache Container / Build-LiteSpeed-Images (82) (push) Successful in 31s
Cloud Apache Container / Build-LiteSpeed-Images (83) (push) Successful in 30s
Cloud Apache Container / Build-LiteSpeed-Images (84) (push) Successful in 32s
Cloud Apache Container / Build-LiteSpeed-Images (85) (push) Successful in 31s
Cloud Apache Container / Build-Shared-httpd (push) Successful in 1m33s
Two correctness fixes and a tuning improvement.
CORRECTNESS:
1. Strip the stock 'extProcessor lsphp' from httpd_config.conf before
appending ours. Previously the stock block (hard-coded
PHP_LSAPI_CHILDREN=10 regardless of container memory) always won
because our APPEND fragment didn't include an extProcessor block.
detect-memory-litespeed.sh was computing LSAPI_CHILDREN but never
plumbing it anywhere — silent dead code.
2. Bump LSPHP_WORKER_ESTIMATE_MB from 96 → 115 per the 2026-06-02
memory-sizing finding (vantagehealth OOM-spawn loop). Each lsphp
carries ~115 MB shmem-rss accounted per worker. 115 MB matches the
real per-worker baseline.
TUNING (idle reduction, the original ask):
- LSAPI_MAX_IDLE_CHILDREN=2 (was CHILDREN/2 = 5 default)
- LSAPI_MAX_IDLE=60s (was 300s default)
- PHP_LSAPI_MAX_REQUESTS=500 (recycle workers, prevents bloat)
- memSoftLimit=1024M / memHardLimit=1500M per worker (RLIMIT_AS;
catches runaway scripts at the worker level, cgroup still backstops
the container)
Effective LSAPI_CHILDREN per container:
2 GiB → ~17 (was 10 — brain-jar was saturating)
1 GiB → ~8
512 MiB → ~3 (cap-marginal per the memory note; bump container if
site grows)
Dropped LSAPI_MEM_SOFT/HARD computation in detect-memory: AVAILABLE/CHILDREN
was conflating VSZ with RSS-budget arithmetic and would have killed
legitimate workers. The 1024/1500 hard-coded values in the template
comfortably fit typical Divi/WooCommerce VSZ (280-365 MB).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
169 lines
6.9 KiB
Bash
169 lines
6.9 KiB
Bash
#!/usr/bin/env bash
|
|
## entrypoint-litespeed.sh — PID 1 for cac-litespeed:phpNN.
|
|
## Built on litespeedtech/openlitespeed:1.8.x-lsphp83 prebuilt base. Native
|
|
## LSAPI (no FPM proxy), one customer per container.
|
|
##
|
|
## Process supervision: starts OLS via `openlitespeed -n` (no-daemon +
|
|
## crash-guard, per OLS source: lshttpdmain.cpp). SIGTERM is forwarded.
|
|
## crond runs in the background for customer crontabs; OLS itself is the
|
|
## process we wait on (if OLS dies, the container exits and Docker
|
|
## restarts it per its restart policy).
|
|
|
|
set -euo pipefail
|
|
|
|
: "${PHPVER:=83}"
|
|
: "${environment:=PROD}"
|
|
: "${LSCACHE_AUTOINSTALL:=1}"
|
|
|
|
export CONTAINER_ROLE="litespeed_only"
|
|
export PHPVER environment LSCACHE_AUTOINSTALL
|
|
|
|
## ---- env validation ----
|
|
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
|
|
: "${domain:=localhost}"
|
|
export user domain
|
|
|
|
## ---- user + directories ----
|
|
if ! id -u "$user" >/dev/null 2>&1; then
|
|
## Ubuntu's useradd; mirror what the AL10 entrypoints do with adduser
|
|
useradd -u "$uid" -m -s /bin/bash "$user"
|
|
fi
|
|
|
|
mkdir -p "/home/$user/public_html"
|
|
## Log dirs mirror cac:phpNN exactly — apache/ for web server access+error,
|
|
## php-fpm/ for PHP errors. OLS isn't Apache and lsphp isn't php-fpm, but
|
|
## the customer-facing paths stay identical so log-gathering, analytics,
|
|
## and the customer's "where do I find my access log?" mental model all
|
|
## just work without per-image-family special cases.
|
|
mkdir -p "/home/$user/logs/apache" "/home/$user/logs/php-fpm"
|
|
mkdir -p "/home/$user/lscache"
|
|
|
|
mkdir -p /tmp/lshttpd/swap
|
|
chmod 1777 /tmp/lshttpd
|
|
|
|
## ---- memory + lsphp pool sizing ----
|
|
# shellcheck source=/dev/null
|
|
source /scripts/detect-memory-litespeed.sh
|
|
echo "Container memory: ${CONTAINER_MEMORY_MB}MB | LSAPI_CHILDREN=${LSAPI_CHILDREN} | PHPVER=${PHPVER}"
|
|
|
|
## ---- self-signed cert (idempotent) ----
|
|
mkdir -p /usr/local/lsws/conf/cert
|
|
if [ ! -f /usr/local/lsws/conf/cert/self.crt ]; then
|
|
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
|
|
-keyout /usr/local/lsws/conf/cert/self.key \
|
|
-out /usr/local/lsws/conf/cert/self.crt \
|
|
-subj "/CN=${domain}" 2>/dev/null
|
|
fi
|
|
|
|
## ---- render httpd_config + vhconf from templates ----
|
|
/scripts/create-vhost-litespeed.sh
|
|
|
|
## ---- point PHP error_log at the same customer-visible path that
|
|
## cac:phpNN uses for php-fpm errors. Drop-in compat: customer code that
|
|
## was tailing /home/$user/logs/php-fpm/error.log on the old image will
|
|
## see lsphp's PHP errors in the exact same file on the new image.
|
|
## Rendered as a tiny ini in lsphp's scan dir; PHP merges it after the
|
|
## production-tuning overrides at startup.
|
|
SCAN_DIR=$(/usr/local/lsws/lsphp${PHPVER}/bin/lsphp -i 2>/dev/null | awk -F'=> ' '/^Scan this dir/ {print $2; exit}')
|
|
if [ -n "$SCAN_DIR" ]; then
|
|
cat > "$SCAN_DIR/99-user-error-log.ini" <<EOF
|
|
; rendered at container start by entrypoint-litespeed.sh
|
|
error_log = /home/${user}/logs/php-fpm/error.log
|
|
log_errors = On
|
|
EOF
|
|
fi
|
|
|
|
## ---- ownership: OLS master/workers run as nobody; lsphp suexecs to the
|
|
## customer per request (setUIDMode 2 in httpd_config.tpl). So the customer
|
|
## owns everything under /home/$user — clean ownership model, no nobody
|
|
## chowning. OLS's own runtime dirs stay nobody-owned.
|
|
chown -R nobody:nogroup /usr/local/lsws/logs /usr/local/lsws/conf/cert /tmp/lshttpd 2>/dev/null || true
|
|
chown -R "$user:$user" "/home/$user"
|
|
chmod 755 "/home/$user"
|
|
## logs/apache and logs/php-fpm are written by OLS (running as the customer
|
|
## via setUIDMode 2) so they need to be customer-owned, not nobody. The
|
|
## chown -R above already covers them since they're under /home/$user.
|
|
|
|
## ---- drop healthz so docker HEALTHCHECK passes before customer files
|
|
## Always rewrite as customer; suexec lsphp will read it as that uid too.
|
|
sudo -u "$user" sh -c "echo ok > /home/$user/public_html/healthz"
|
|
|
|
## ---- DEV: local mariadb + memcached for parity with cac entrypoints ----
|
|
if [ "$environment" = "DEV" ]; then
|
|
echo "Starting Dev Deployment (litespeed)"
|
|
mkdir -p "/home/$user/_db_backups"
|
|
## mariadb-server + memcached are NOT baked into the image (saves ~500MB
|
|
## on PROD pulls). Install them at runtime, but only once per container —
|
|
## the command -v guard means a restart of an already-bootstrapped
|
|
## container skips the apt step and DEV boot stays ~1.5s like PROD.
|
|
## First-boot in DEV adds ~30-60s for the apt install; acceptable
|
|
## tradeoff per the design spec.
|
|
if ! command -v mysqld >/dev/null 2>&1; then
|
|
echo "DEV first boot: installing mariadb-server + memcached..."
|
|
apt-get update -qq
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
|
mariadb-server memcached
|
|
apt-get clean
|
|
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
|
|
fi
|
|
mkdir -p /run/mysqld && chown mysql:mysql /run/mysqld
|
|
nohup mysqld --user=mysql &>/dev/null &
|
|
if [ ! -f "/home/$user/mysql_creds" ]; then
|
|
sleep 10
|
|
mysql_user=$(openssl rand -hex 7)
|
|
mysql_password=$(openssl rand -hex 12)
|
|
mysql_db="devdb_$(openssl rand -hex 3)"
|
|
mysql -e "CREATE DATABASE $mysql_db;"
|
|
mysql -e "CREATE USER '$mysql_user'@'localhost' IDENTIFIED BY '$mysql_password';"
|
|
mysql -e "GRANT ALL PRIVILEGES ON *.* TO '$mysql_user'@'localhost' WITH GRANT OPTION;"
|
|
mysql -e "FLUSH PRIVILEGES;"
|
|
{
|
|
echo "MySQL User: $mysql_user"
|
|
echo "MySQL Password: $mysql_password"
|
|
echo "MySQL Database: $mysql_db"
|
|
} > "/home/$user/mysql_creds"
|
|
cat "/home/$user/mysql_creds"
|
|
fi
|
|
/usr/bin/memcached -d -u "$user"
|
|
fi
|
|
|
|
## ---- user crontab ----
|
|
if [ ! -f "/home/$user/crontab" ]; then
|
|
{
|
|
echo "# User crontab for $user"
|
|
echo "# Add your cron jobs here"
|
|
} > "/home/$user/crontab"
|
|
chown "$user:$user" "/home/$user/crontab"
|
|
fi
|
|
crontab -u "$user" "/home/$user/crontab"
|
|
service cron start >/dev/null 2>&1 || /usr/sbin/cron
|
|
|
|
## ---- LSCache plugin (background, non-fatal) ----
|
|
( /scripts/install-lscache-wp.sh "$user" >>/var/log/lscache-install.log 2>&1 || true ) &
|
|
|
|
## ---- start OLS in foreground with crash-guard ----
|
|
## openlitespeed -n = no-daemon + supervisor. Trap forwards SIGTERM cleanly.
|
|
OLS_PID=""
|
|
trap '[ -n "$OLS_PID" ] && kill -TERM "$OLS_PID" 2>/dev/null; wait "$OLS_PID" 2>/dev/null || true' TERM INT
|
|
|
|
/usr/local/lsws/bin/openlitespeed -n &
|
|
OLS_PID=$!
|
|
|
|
## Stream OLS + customer logs to PID-1 stdout so `docker logs` works.
|
|
touch /usr/local/lsws/logs/error.log /usr/local/lsws/logs/access.log
|
|
touch "/home/$user/logs/apache/error_log" "/home/$user/logs/apache/access_log"
|
|
touch "/home/$user/logs/php-fpm/error.log"
|
|
chown "$user:$user" "/home/$user/logs/apache/error_log" \
|
|
"/home/$user/logs/apache/access_log" \
|
|
"/home/$user/logs/php-fpm/error.log"
|
|
tail -F /usr/local/lsws/logs/error.log \
|
|
/usr/local/lsws/logs/access.log \
|
|
"/home/$user/logs/apache/error_log" \
|
|
"/home/$user/logs/apache/access_log" \
|
|
"/home/$user/logs/php-fpm/error.log" 2>/dev/null &
|
|
|
|
wait "$OLS_PID"
|