#!/usr/bin/env bash # R01-N22: deploy-time migrations. # # Apply any pending SQL migrations before Apache starts to serve traffic, so # the request path can simply CHECK the schema state and refuse to serve when # something is unexpectedly out of date — no half-applied DDL hazard. # # Failure here aborts the container start (we exit non-zero) so the operator # notices in `docker logs`. Apache otherwise picks up the trailing args # verbatim (CMD `apache2-foreground`). set -euo pipefail APP_ROOT="${APP_ROOT:-/var/www/html}" # R01-N27: session-storage path (defaults match Dockerfile + .env.example). SESSION_PATH="${SESSION_PATH:-/var/www/data/sessions}" # R01-N27: session-file lifetime in minutes. Default 480 (= 8h), matching # `session.gc_maxlifetime` set by `SessionGuard::start()`. Operators may # override via the container env (e.g. tighten on a public deployment). SESSION_GC_MAX_AGE_MINUTES="${SESSION_GC_MAX_AGE_MINUTES:-480}" # R01-N27: how often to sweep, in seconds. Default 3600 (= once per hour). SESSION_GC_INTERVAL_SECONDS="${SESSION_GC_INTERVAL_SECONDS:-3600}" echo "[entrypoint] running deploy-time migrations…" php "${APP_ROOT}/bin/migrate.php" # R01-N27: PHP's built-in session GC fires probabilistically off request # traffic, so a low-traffic deployment keeps stale session files for days # past `gc_maxlifetime`. This backgrounded loop deletes session files # older than $SESSION_GC_MAX_AGE_MINUTES every $SESSION_GC_INTERVAL_SECONDS. # It is a child of this script's PID 1, so a `docker stop` propagates and # tears it down cleanly along with Apache. No new package dependency — only # coreutils' `find`, already present in the php:8.3-apache base image. if [ -d "${SESSION_PATH}" ]; then echo "[entrypoint] starting session GC loop (path=${SESSION_PATH}, max-age=${SESSION_GC_MAX_AGE_MINUTES}m, every ${SESSION_GC_INTERVAL_SECONDS}s)" ( while true; do sleep "${SESSION_GC_INTERVAL_SECONDS}" # `-mmin +N` matches files older than N minutes; `-type f` avoids # touching the directory itself; errors swallowed so a transient # filesystem hiccup does not kill the loop. find "${SESSION_PATH}" -mindepth 1 -type f -mmin +"${SESSION_GC_MAX_AGE_MINUTES}" -delete 2>/dev/null || true done ) & fi echo "[entrypoint] starting: $*" exec "$@"