- build-push.yaml: Build-and-Push, Build-FPM-Images, Build-Shared-httpd
and Build-Shared-OLS probe https://192.168.1.40 and :5000 with the
pinned pkg-cache CA (5 s timeouts). When the cache answers they pass
PKG_CACHE and configure the BuildKit Docker Hub mirror (ca=). When it
doesn't, they build from upstream exactly as before and emit a warning.
Fallback measured from the runner bridge: refused <1 s, silent drop 10 s.
- scripts/host/pkgcache-host-repos.sh: apply/revert/status for WHP hosts.
Each rewritten repo uses baseurl=<cache> <origin> as the real fallback;
mirrorlist/metalink stay commented because measured dnf ignores baseurl
when they are present. Keeps gpgcheck=1 / repo_gpgcheck=1 and backs up
every file. Tested on 192.168.1.148, including cache-down and
silent-drop fallback.
- docs: runner firewall rule (applied), measured fallback results.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Security review follow-up for the opt-in PKG_CACHE path:
- PKG_CACHE must be https:// (http is refused). The cache's certificate
comes from a name-constrained internal CA (keys/pkg-cache/ca.crt, valid
only for 192.168.1.40 / pkg-cache.*). The CA is trusted only by the
rewritten repos (dnf sslcacert bundle, apt per-host CaInfo) and only
for the duration of the RUN.
- epel-release / remi-release are no longer installed straight from a
URL. release-install downloads them over HTTPS, checks the package name,
imports the signing keys committed in keys/pkg-cache/ and requires
`rpm -K` "signatures OK", then installs with localpkg_gpgcheck=1. This
applies with and without the cache.
- Rewritten repos get gpgcheck=1. Remi and AlmaLinux also get
repo_gpgcheck=1, since both sign repomd.xml. EPEL does not publish a
repomd signature, so it relies on end-to-end HTTPS.
- restore also deletes files it created and any new repo/apt file that
still references the cache, then fails the build if a reference remains
under /etc/yum.repos.d, /etc/dnf or /etc/apt.
- docs: trust model, replay risk, proposed openssl/httpd/ImageMagick
minimum-version gates, TLS registry mirror (BuildKit ca= / dockerd
certs.d, no insecure-registries).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds scripts/pkg-cache-repos.sh and wires it into Dockerfile,
Dockerfile.fpm, Dockerfile.shared-httpd and Dockerfile.shared-ols. With
--build-arg PKG_CACHE=http://192.168.1.40 (CT130 pkg-cache), dnf/apt go
through the LAN cache. That cache fetches from the Remi/EPEL/AlmaLinux/
Ubuntu/LiteSpeed origins over HTTPS, with fallback tiers and
stale-on-error. Without the arg the script is a no-op and builds are
unchanged.
- rpm: each baseurl becomes "<cache>/<prefix>/... <origin>/...", so dnf
fails over to the origin if the cache dies mid-build
- every RUN restores the original repo files before it ends, so no
shipped layer carries the LAN address
- EPEL/Remi release RPMs come from the cache when it is set
- the php.net version gates are untouched
Dockerfile.litespeed/.lsphp are not wired yet (see docs/pkg-cache.md).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For when a PHP security release is out and the LiteSpeed apt repo lags
(2026-10-21: php2shell CVE-2026-109618/-109619 fixed in 8.2.35/8.3.36/
8.4.27/8.5.12, LiteSpeed still on 8.2.34/8.3.35/8.4.26/8.5.11).
Dockerfile.lsphp / Dockerfile.litespeed gain an `lsphp-src` stage that is
idle unless PHP_SRC_VERSION is set; normal builds are unchanged (measured:
module list, file manifest, ldd, ini and dpkg identical to the published
images).
When set (lsphp-src-build.sh):
- tarball sha256 (php.net releases JSON) + OpenPGP signature against the
committed php.net keyring, signer pinned per branch
- configure flags replayed from the packaged lsphp's own Configure Command
- LiteSpeed's php-litespeed-8.3 SAPI (what the packages actually compile,
measured) instead of php-src's sapi/litespeed; sha256-pinned and checked
against the packaged binary's LSAPI_* names
- packaged compiled-in ini defaults reproduced (session.save_path on 8.2/
8.3) and gated (`php -n` diff)
- ABI gate (lsphp-abi-gate.sh, pahole) before reusing LiteSpeed's packaged
PECL .so files; regression-tested in Shell-Checks
lsphp-src-overlay.sh swaps only php-src-owned files (decided by dpkg) and
fails the build unless extensions, versions, effective ini and feature
lines match the packaged lsphp under both CLI and litespeed SAPIs.
CI: lsphp-source-emergency.yaml (workflow_dispatch only). build-push.yaml
refuses to overwrite a newer php.net image with an older packaged one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two judgement calls arising from the pipefail/SIGPIPE fix, reasoned through
and written up rather than decided silently:
1. Boot posture when 'lsphp -i' genuinely fails. Recommendation is fail-open
plus a machine-detectable degraded marker and one probe retry, NOT
fail-closed: a transient fork() failure during this fleet's backup windows
produces the identical empty-LSPHP_INFO signature, so fail-closed would
refuse to boot healthy sites under host pressure. Includes the caution
that degraded must not map onto Docker 'unhealthy', or a watchdog would
restart-loop a serving site over something restarts cannot fix.
Corrects a premise the fix rested on: the two entrypoints were NOT already
consistent — entrypoint-litespeed.sh fails open silently, with no warning.
2. Whether the new static check should gate releases. Recommendation is to
hard-gate, but only after back-testing the job against trunk and recent
tags to bound false positives.
Recommendations only; no implementation.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>