#!/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" mkdir -p "/home/$user/logs/litespeed" 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} | memSoft=${LSAPI_MEM_SOFT}M memHard=${LSAPI_MEM_HARD}M | 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 ## ---- 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" ## ---- 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 already in the image (apt-installed ## in the Dockerfile). Just start them. 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/litespeed/error.log" "/home/$user/logs/litespeed/access.log" tail -F /usr/local/lsws/logs/error.log \ /usr/local/lsws/logs/access.log \ "/home/$user/logs/litespeed/error.log" \ "/home/$user/logs/litespeed/access.log" 2>/dev/null & wait "$OLS_PID"