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>
121 lines
4.0 KiB
Bash
121 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
## entrypoint-shared-ols.sh — PID 1 for the shared-ols tier.
|
|
##
|
|
## One OpenLiteSpeed container fronting MANY tenants' detached cac-lsphp
|
|
## sidecars (the OLS analogue of the shared-httpd container). Webserver ONLY —
|
|
## it runs NO PHP locally (render-shared-ols-config.sh strips the stock local
|
|
## lsphp; every site's PHP goes to its own sidecar over LSAPI). HAProxy stays
|
|
## the TLS/WAF/SNI edge and routes OLS-type hostnames here on :443.
|
|
##
|
|
## Reuses cac-litespeed's hard-won DAEMON-MODE supervision (NOT `openlitespeed
|
|
## -n` + wait): OLS self-restarts on QUIC.cloud IP refresh would otherwise exit
|
|
## PID 1 cleanly and tear the container down. See entrypoint-litespeed.sh and
|
|
## feedback_ols_quiccloud_restart_kills_container.
|
|
set -euo pipefail
|
|
|
|
: "${environment:=PROD}"
|
|
export CONTAINER_ROLE="shared_ols"
|
|
|
|
LSWS_CONF=/usr/local/lsws/conf
|
|
CERT_DIR="$LSWS_CONF/cert"
|
|
HEALTH_DIR=/usr/local/lsws/shared-ols-health
|
|
export SITES_ROOT="${SITES_ROOT:-$LSWS_CONF/shared-sites}"
|
|
export LSCACHE_ROOT="${LSCACHE_ROOT:-/var/lscache}"
|
|
export CERT_FILE="$CERT_DIR/shared-ols.crt"
|
|
export KEY_FILE="$CERT_DIR/shared-ols.key"
|
|
|
|
mkdir -p "$SITES_ROOT" "$LSCACHE_ROOT" "$CERT_DIR" "$HEALTH_DIR/html"
|
|
|
|
## ---- self-signed cert for the :443 listener (HAProxy verifies none) ----
|
|
if [ ! -f "$CERT_FILE" ]; then
|
|
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
|
|
-keyout "$KEY_FILE" -out "$CERT_FILE" -subj "/CN=shared-ols" 2>/dev/null
|
|
fi
|
|
|
|
## ---- health vhost (catch-all): valid server with zero customer sites +
|
|
## answers HAProxy health checks that hit by IP / unknown Host with a 200 ----
|
|
cat > "$HEALTH_DIR/vhconf.conf" <<'EOF'
|
|
docRoot $VH_ROOT/html
|
|
enableScript 0
|
|
context / {
|
|
allowBrowse 1
|
|
location $DOC_ROOT/
|
|
}
|
|
EOF
|
|
printf 'ok\n' > "$HEALTH_DIR/html/healthz"
|
|
printf 'shared-ols\n' > "$HEALTH_DIR/html/index.html"
|
|
|
|
## ---- assemble httpd_config.conf from the panel's per-site files ----
|
|
/scripts/render-shared-ols-config.sh
|
|
|
|
chown -R lsadm:nogroup "$LSWS_CONF" "$HEALTH_DIR" 2>/dev/null || true
|
|
|
|
## ---- stream OLS logs to PID-1 stdout (follows across restarts) ----
|
|
mkdir -p /usr/local/lsws/logs
|
|
touch /usr/local/lsws/logs/error.log /usr/local/lsws/logs/access.log
|
|
tail -F /usr/local/lsws/logs/error.log /usr/local/lsws/logs/access.log 2>/dev/null &
|
|
|
|
## ---- .htaccess watcher (required; spec 5.3). Background; the panel monitors
|
|
## that it stays alive (its death silently stops rewrite changes applying). ----
|
|
/scripts/ols-htaccess-watcher.sh &
|
|
WATCHER_PID=$!
|
|
|
|
## ---- supervise OLS in DAEMON mode (verbatim model from entrypoint-litespeed.sh) ----
|
|
STOP_REQUESTED=0
|
|
term_handler() {
|
|
STOP_REQUESTED=1
|
|
kill "$WATCHER_PID" 2>/dev/null || true
|
|
/usr/local/lsws/bin/lswsctrl stop >/dev/null 2>&1 || true
|
|
}
|
|
trap term_handler TERM INT
|
|
|
|
ols_running() { /usr/local/lsws/bin/lswsctrl status 2>/dev/null | grep -qi 'running with pid'; }
|
|
|
|
MAX_STARTS=5
|
|
WINDOW=60
|
|
starts=""
|
|
|
|
start_ols() {
|
|
/usr/local/lsws/bin/lswsctrl start >/dev/null 2>&1 || true
|
|
for _ in $(seq 1 20); do
|
|
ols_running && return 0
|
|
sleep 0.5
|
|
done
|
|
return 1
|
|
}
|
|
|
|
if ! start_ols; then
|
|
echo "entrypoint-shared-ols: OLS failed to start (not running after 10s)." >&2
|
|
exit 1
|
|
fi
|
|
echo "entrypoint-shared-ols: OLS started in daemon mode — $(/usr/local/lsws/bin/lswsctrl status 2>/dev/null || true)"
|
|
|
|
while true; do
|
|
if ols_running; then
|
|
sleep 3
|
|
continue
|
|
fi
|
|
sleep 2
|
|
if [ "$STOP_REQUESTED" -eq 0 ] && ols_running; then
|
|
continue
|
|
fi
|
|
if [ "$STOP_REQUESTED" -eq 1 ]; then
|
|
echo "entrypoint-shared-ols: SIGTERM received, OLS stopped — exiting."
|
|
exit 0
|
|
fi
|
|
now=$(date +%s)
|
|
starts="$starts $now"
|
|
pruned=""
|
|
for t in $starts; do
|
|
[ $((now - t)) -lt "$WINDOW" ] && pruned="$pruned $t"
|
|
done
|
|
starts="$pruned"
|
|
n=$(echo $starts | wc -w)
|
|
echo "entrypoint-shared-ols: OLS not running — relaunching (attempt $n/$MAX_STARTS within ${WINDOW}s)." >&2
|
|
if [ "$n" -ge "$MAX_STARTS" ]; then
|
|
echo "entrypoint-shared-ols: OLS crash-looping — bailing for Docker restart policy / monitor." >&2
|
|
exit 1
|
|
fi
|
|
start_ols || true
|
|
done
|