pkg-cache: Debian/NodeSource/Go/EL9 modes; wire cac-litespeed + cac-lsphp; docs #36

Merged
jknapp merged 3 commits from ci/pkg-cache-more-upstreams into trunk 2026-10-22 14:35:52 +00:00
9 changed files with 398 additions and 30 deletions

No files matched your search

+120 -2
View File
@@ -321,6 +321,10 @@ jobs:
Build-LiteSpeed-Images:
runs-on: ubuntu-latest
# One place for the OLS base tag: digest lookup and build-args both read it.
# OLS_VERSION pinned to 1.8.4 (see the build step); Dockerfile default differs.
env:
OLS_VERSION: "1.8.4"
strategy:
# One PHP version failing (e.g. an EOL stream) must not cancel the
# security builds of the others.
@@ -335,10 +339,63 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
# Base image pinned by DIGEST, looked up directly at Docker Hub (never via
# the pkg-cache mirror), so the mirror can only serve content-addressed
# blobs that BuildKit verifies. If the lookup fails this job does NOT use
# the mirror and pulls the tag straight from Docker Hub. docs/pkg-cache.md.
- name: Resolve base image digest (Docker Hub, direct)
id: base
env:
BASE_TAG: litespeedtech/openlitespeed:${{ env.OLS_VERSION }}-lsphp${{ matrix.phpver }}
run: |
set -uo pipefail
if ref=$(.gitea/scripts/resolve-base-image.sh "$BASE_TAG") && [[ "$ref" =~ ^[a-z0-9][a-z0-9._/-]*@sha256:[0-9a-f]{64}$ ]]; then
echo "base-image: ${BASE_TAG} -> ${ref} (digest from registry-1.docker.io)"
echo "image=${ref}" >> "$GITHUB_OUTPUT"
echo "pinned=true" >> "$GITHUB_OUTPUT"
else
echo "::warning::base image ${BASE_TAG}: Docker Hub digest lookup failed - pulling the tag directly from Docker Hub, pkg-cache registry mirror NOT used"
echo "image=${BASE_TAG}" >> "$GITHUB_OUTPUT"
echo "pinned=false" >> "$GITHUB_OUTPUT"
fi
# Internal package cache (CT130 pkg-cache, docs/pkg-cache.md). Used ONLY if
# it answers over TLS with our pinned CA; otherwise (down, unreachable,
# bad/expired cert) this job builds from the upstream repos and Docker Hub
# exactly as before. The repo cache and the registry mirror are probed
# separately so either can fail back on its own.
- name: Probe package cache
id: pkgcache
# The registry mirror is only used for a digest-pinned base image.
env:
BASE_PINNED: ${{ steps.base.outputs.pinned }}
run: |
url=""; mirror=""
if curl -fsS --max-time 5 --cacert keys/pkg-cache/ca.crt -o /dev/null https://192.168.1.40/; then url="https://192.168.1.40"; fi
if [ "$BASE_PINNED" = true ] && curl -fsS --max-time 5 --cacert keys/pkg-cache/ca.crt -o /dev/null https://192.168.1.40:5000/v2/; then mirror="192.168.1.40:5000"; fi
echo "pkg-cache: repos=${url:-<unreachable: upstream>} registry-mirror=${mirror:-<not used: Docker Hub direct>}"
[ -n "$url" ] || echo "::warning::pkg-cache unreachable - building from upstream repositories"
echo "url=${url}" >> "$GITHUB_OUTPUT"
echo "mirror=${mirror}" >> "$GITHUB_OUTPUT"
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# BuildKit (docker-container driver) ignores dockerd's registry-mirrors,
# so the mirror is configured on the builder; BuildKit itself still falls
# back to Docker Hub if the mirror stops answering mid-run.
- name: Set up Docker Buildx (Docker Hub via pkg-cache mirror)
if: steps.pkgcache.outputs.mirror != ''
uses: docker/setup-buildx-action@v3
with:
buildkitd-config-inline: |
[registry."docker.io"]
mirrors = ["192.168.1.40:5000"]
[registry."192.168.1.40:5000"]
ca = ["${{ github.workspace }}/keys/pkg-cache/ca.crt"]
- name: Set up Docker Buildx
if: steps.pkgcache.outputs.mirror == ''
uses: docker/setup-buildx-action@v3
# Per-run cache-bust value. Each job's buildx builder is created fresh by
@@ -409,7 +466,9 @@ jobs:
push: true
build-args: |
PHPVER=${{ matrix.phpver }}
OLS_VERSION=1.8.4
OLS_VERSION=${{ env.OLS_VERSION }}
BASE_IMAGE=${{ steps.base.outputs.image }}
PKG_CACHE=${{ steps.pkgcache.outputs.url }}
CACHE_BUST=${{ steps.bust.outputs.value }}
EXPECT_LSPHP_PKG=${{ steps.lsphp.outputs.pkg }}
EXPECT_PHP_VERSION=${{ steps.lsphp.outputs.php }}
@@ -423,6 +482,10 @@ jobs:
Build-LSPHP-Images:
runs-on: ubuntu-latest
# One place for the OLS base tag: digest lookup and build-args both read it.
# OLS_VERSION pinned to 1.8.4 (see the build step); Dockerfile default differs.
env:
OLS_VERSION: "1.8.4"
strategy:
# One PHP version failing (e.g. an EOL stream) must not cancel the
# security builds of the others.
@@ -437,10 +500,63 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
# Base image pinned by DIGEST, looked up directly at Docker Hub (never via
# the pkg-cache mirror), so the mirror can only serve content-addressed
# blobs that BuildKit verifies. If the lookup fails this job does NOT use
# the mirror and pulls the tag straight from Docker Hub. docs/pkg-cache.md.
- name: Resolve base image digest (Docker Hub, direct)
id: base
env:
BASE_TAG: litespeedtech/openlitespeed:${{ env.OLS_VERSION }}-lsphp${{ matrix.phpver }}
run: |
set -uo pipefail
if ref=$(.gitea/scripts/resolve-base-image.sh "$BASE_TAG") && [[ "$ref" =~ ^[a-z0-9][a-z0-9._/-]*@sha256:[0-9a-f]{64}$ ]]; then
echo "base-image: ${BASE_TAG} -> ${ref} (digest from registry-1.docker.io)"
echo "image=${ref}" >> "$GITHUB_OUTPUT"
echo "pinned=true" >> "$GITHUB_OUTPUT"
else
echo "::warning::base image ${BASE_TAG}: Docker Hub digest lookup failed - pulling the tag directly from Docker Hub, pkg-cache registry mirror NOT used"
echo "image=${BASE_TAG}" >> "$GITHUB_OUTPUT"
echo "pinned=false" >> "$GITHUB_OUTPUT"
fi
# Internal package cache (CT130 pkg-cache, docs/pkg-cache.md). Used ONLY if
# it answers over TLS with our pinned CA; otherwise (down, unreachable,
# bad/expired cert) this job builds from the upstream repos and Docker Hub
# exactly as before. The repo cache and the registry mirror are probed
# separately so either can fail back on its own.
- name: Probe package cache
id: pkgcache
# The registry mirror is only used for a digest-pinned base image.
env:
BASE_PINNED: ${{ steps.base.outputs.pinned }}
run: |
url=""; mirror=""
if curl -fsS --max-time 5 --cacert keys/pkg-cache/ca.crt -o /dev/null https://192.168.1.40/; then url="https://192.168.1.40"; fi
if [ "$BASE_PINNED" = true ] && curl -fsS --max-time 5 --cacert keys/pkg-cache/ca.crt -o /dev/null https://192.168.1.40:5000/v2/; then mirror="192.168.1.40:5000"; fi
echo "pkg-cache: repos=${url:-<unreachable: upstream>} registry-mirror=${mirror:-<not used: Docker Hub direct>}"
[ -n "$url" ] || echo "::warning::pkg-cache unreachable - building from upstream repositories"
echo "url=${url}" >> "$GITHUB_OUTPUT"
echo "mirror=${mirror}" >> "$GITHUB_OUTPUT"
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# BuildKit (docker-container driver) ignores dockerd's registry-mirrors,
# so the mirror is configured on the builder; BuildKit itself still falls
# back to Docker Hub if the mirror stops answering mid-run.
- name: Set up Docker Buildx (Docker Hub via pkg-cache mirror)
if: steps.pkgcache.outputs.mirror != ''
uses: docker/setup-buildx-action@v3
with:
buildkitd-config-inline: |
[registry."docker.io"]
mirrors = ["192.168.1.40:5000"]
[registry."192.168.1.40:5000"]
ca = ["${{ github.workspace }}/keys/pkg-cache/ca.crt"]
- name: Set up Docker Buildx
if: steps.pkgcache.outputs.mirror == ''
uses: docker/setup-buildx-action@v3
# Per-run cache-bust value. Each job's buildx builder is created fresh by
@@ -511,7 +627,9 @@ jobs:
push: true
build-args: |
PHPVER=${{ matrix.phpver }}
OLS_VERSION=1.8.4
OLS_VERSION=${{ env.OLS_VERSION }}
BASE_IMAGE=${{ steps.base.outputs.image }}
PKG_CACHE=${{ steps.pkgcache.outputs.url }}
CACHE_BUST=${{ steps.bust.outputs.value }}
EXPECT_LSPHP_PKG=${{ steps.lsphp.outputs.pkg }}
EXPECT_PHP_VERSION=${{ steps.lsphp.outputs.php }}
+18 -3
View File
@@ -22,12 +22,18 @@
## after FROM for any RUN steps that need it.
ARG OLS_VERSION=1.8.5
ARG PHPVER=83
## CI passes BASE_IMAGE=litespeedtech/openlitespeed@sha256:<digest> of the
## ${OLS_VERSION}-lsphp${PHPVER} tag, resolved DIRECTLY from Docker Hub in the same
## run (.gitea/scripts/resolve-base-image.sh), so the pkg-cache registry mirror can
## only serve content-addressed blobs. Local builds use the tag. Every stage below
## (incl. the emergency lsphp-src stage) starts from this one image.
ARG BASE_IMAGE=litespeedtech/openlitespeed:${OLS_VERSION}-lsphp${PHPVER}
## ---- EMERGENCY ONLY: lsphp compiled from php.net source ----------------------
## Idle unless PHP_SRC_VERSION is set (then /lsphp-src-out stays empty and the
## overlay step below is a no-op). Same stage as Dockerfile.lsphp — see there and
## docs/lsphp-source-emergency.md.
FROM litespeedtech/openlitespeed:${OLS_VERSION}-lsphp${PHPVER} AS lsphp-src
FROM ${BASE_IMAGE} AS lsphp-src
ARG PHPVER=83
ARG CACHE_BUST=
ARG EXPECT_LSPHP_PKG=
@@ -42,7 +48,7 @@ RUN --mount=type=bind,source=scripts,target=/mnt/scripts \
fi; \
PHPVER="${PHPVER}" bash /mnt/scripts/lsphp-src-build.sh
FROM litespeedtech/openlitespeed:${OLS_VERSION}-lsphp${PHPVER}
FROM ${BASE_IMAGE}
ARG PHPVER=83
ENV PHPVER=${PHPVER}
@@ -80,11 +86,20 @@ ENV PHPVER=${PHPVER}
ARG CACHE_BUST=
ARG EXPECT_LSPHP_PKG=
ARG EXPECT_PHP_VERSION=
## OPTIONAL internal package cache, e.g. --build-arg PKG_CACHE=https://192.168.1.40
## (CT130 pkg-cache, https only). Unset = upstream repositories (Ubuntu +
## rpms.litespeedtech.com). Repo files are restored at the end of the RUN, so no
## layer keeps the cache address. See scripts/pkg-cache-repos.sh.
ARG PKG_CACHE=
COPY ./scripts/pkg-cache-repos.sh /usr/local/sbin/pkg-cache-repos.sh
COPY ./keys/pkg-cache/ /usr/local/share/pkg-cache/
COPY ./scripts/lsphp-apt-upgrade.sh /usr/local/sbin/lsphp-apt-upgrade.sh
RUN /usr/local/sbin/lsphp-apt-upgrade.sh "${PHPVER}" \
RUN /usr/local/sbin/pkg-cache-repos.sh apt && \
/usr/local/sbin/lsphp-apt-upgrade.sh "${PHPVER}" \
gettext-base sudo cron \
ca-certificates curl wget \
lsphp${PHPVER}-ldap && \
/usr/local/sbin/pkg-cache-repos.sh restore && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
+27 -3
View File
@@ -21,6 +21,12 @@
ARG OLS_VERSION=1.8.4
ARG PHPVER=83
## CI passes BASE_IMAGE=litespeedtech/openlitespeed@sha256:<digest> of the
## ${OLS_VERSION}-lsphp${PHPVER} tag, resolved DIRECTLY from Docker Hub in the same
## run (.gitea/scripts/resolve-base-image.sh), so the pkg-cache registry mirror can
## only serve content-addressed blobs. Local builds use the tag. Every stage below
## (incl. the emergency lsphp-src stage) starts from this one image.
ARG BASE_IMAGE=litespeedtech/openlitespeed:${OLS_VERSION}-lsphp${PHPVER}
## ---- stage 0 (EMERGENCY ONLY): lsphp compiled from php.net source -----------
## Idle unless PHP_SRC_VERSION is set: lsphp-src-build.sh then exits at once and
@@ -30,7 +36,7 @@ ARG PHPVER=83
## — CI: .gitea/workflows/lsphp-source-emergency.yaml; runbook:
## docs/lsphp-source-emergency.md. The tarball is sha256- AND OpenPGP-verified
## against keys/php-src/; configure flags are replayed from the packaged lsphp.
FROM litespeedtech/openlitespeed:${OLS_VERSION}-lsphp${PHPVER} AS lsphp-src
FROM ${BASE_IMAGE} AS lsphp-src
ARG PHPVER=83
ARG CACHE_BUST=
ARG EXPECT_LSPHP_PKG=
@@ -77,7 +83,7 @@ RUN --mount=type=bind,source=scripts,target=/mnt/scripts \
## Separate stage on purpose: the compiler + headers (~400MB) stay out of the
## shipped image, which gains only the ~40KB .so. Costs ~1-2 min of CI per PHP
## version; both stages share the same base layer, so no extra pull.
FROM litespeedtech/openlitespeed:${OLS_VERSION}-lsphp${PHPVER} AS ext-build
FROM ${BASE_IMAGE} AS ext-build
ARG PHPVER=83
## Toolchain layer, deliberately BEFORE the source COPY so editing the extension
@@ -94,11 +100,20 @@ ARG PHPVER=83
ARG CACHE_BUST=
ARG EXPECT_LSPHP_PKG=
ARG EXPECT_PHP_VERSION=
## OPTIONAL internal package cache, e.g. --build-arg PKG_CACHE=https://192.168.1.40
## (CT130 pkg-cache, https only). Unset = upstream repositories (Ubuntu +
## rpms.litespeedtech.com). Repo files are restored at the end of the RUN, so no
## layer keeps the cache address. See scripts/pkg-cache-repos.sh.
ARG PKG_CACHE=
COPY ./scripts/pkg-cache-repos.sh /usr/local/sbin/pkg-cache-repos.sh
COPY ./keys/pkg-cache/ /usr/local/share/pkg-cache/
COPY ./scripts/lsphp-apt-upgrade.sh /usr/local/sbin/lsphp-apt-upgrade.sh
RUN set -e; \
/usr/local/sbin/pkg-cache-repos.sh apt; \
/usr/local/sbin/lsphp-apt-upgrade.sh --no-os-upgrade "${PHPVER}" \
build-essential autoconf pkg-config \
lsphp${PHPVER}-dev; \
/usr/local/sbin/pkg-cache-repos.sh restore; \
RTV=$(dpkg-query -W -f='${Version}' lsphp${PHPVER}); \
DEVV=$(dpkg-query -W -f='${Version}' lsphp${PHPVER}-dev); \
if [ "$RTV" != "$DEVV" ]; then \
@@ -168,7 +183,7 @@ RUN set -e; \
cp modules/cac_path_parity.so /build-out/
## ---- stage 2: the shipped sidecar image ------------------------------------
FROM litespeedtech/openlitespeed:${OLS_VERSION}-lsphp${PHPVER}
FROM ${BASE_IMAGE}
ARG PHPVER=83
ENV PHPVER=${PHPVER}
@@ -196,10 +211,18 @@ ENV PHPVER=${PHPVER}
ARG CACHE_BUST=
ARG EXPECT_LSPHP_PKG=
ARG EXPECT_PHP_VERSION=
## OPTIONAL internal package cache, e.g. --build-arg PKG_CACHE=https://192.168.1.40
## (CT130 pkg-cache, https only). Unset = upstream repositories (Ubuntu +
## rpms.litespeedtech.com). Repo files are restored at the end of the RUN, so no
## layer keeps the cache address. See scripts/pkg-cache-repos.sh.
ARG PKG_CACHE=
COPY ./scripts/pkg-cache-repos.sh /usr/local/sbin/pkg-cache-repos.sh
COPY ./keys/pkg-cache/ /usr/local/share/pkg-cache/
COPY --from=ext-build /build-out/lsphp.version /etc/cac-lsphp-build.version
COPY ./scripts/lsphp-apt-upgrade.sh /usr/local/sbin/lsphp-apt-upgrade.sh
RUN set -e; \
V=$(cat /etc/cac-lsphp-build.version); \
/usr/local/sbin/pkg-cache-repos.sh apt; \
if ! /usr/local/sbin/lsphp-apt-upgrade.sh "${PHPVER}" \
ca-certificates \
lsphp${PHPVER}="$V" lsphp${PHPVER}-common="$V" lsphp${PHPVER}-ldap="$V"; then \
@@ -211,6 +234,7 @@ RUN set -e; \
echo " build (CI) / rebuild with --no-cache (local)." >&2; \
exit 1; \
fi; \
/usr/local/sbin/pkg-cache-repos.sh restore; \
apt-get clean; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
RTV=$(dpkg-query -W -f='${Version}' lsphp${PHPVER}); \
+43 -5
View File
@@ -21,6 +21,10 @@ On that day a build without the cache spent **1031 s** in its first dnf step. Th
| `https://192.168.1.40/ubuntu/` | `https://archive.ubuntu.com/ubuntu`, `https://us.archive.ubuntu.com/ubuntu` |
| `https://192.168.1.40/ubuntu-security/` | `https://security.ubuntu.com/ubuntu`, `https://archive.ubuntu.com/ubuntu` |
| `https://192.168.1.40/litespeed/` | `https://rpms.litespeedtech.com`, then `http://rpms.litespeedtech.com` |
| `https://192.168.1.40/nodesource/` | `https://rpm.nodesource.com` (origin only; RPMs signed, repomd not) — added 2026-10-22 |
| `https://192.168.1.40/debian/` | `https://deb.debian.org/debian` (CDN origin; princeton was 6 h behind on trixie-updates) — added 2026-10-22 |
| `https://192.168.1.40/debian-security/` | `https://security.debian.org/debian-security`, `https://deb.debian.org/debian-security` — added 2026-10-22 |
| `https://192.168.1.40/goproxy/` | `https://proxy.golang.org` (Go module proxy; `/sumdb/` is 404 there, so `go` checks sum.golang.org directly) — added 2026-10-22 |
| `192.168.1.40:5000` (TLS, pkg-cache CA) | Docker Hub pull-through cache (`registry-1.docker.io`) |
Plain `http://192.168.1.40/` answers **403** to LAN clients.
@@ -32,6 +36,7 @@ Cache rules:
- apt `dists/`, except `by-hash/`
- `*-latest*.rpm` and `remi-release-N.rpm`
- `RPM-GPG-KEY*`
- Go proxy `/@v/list` and `/@latest`
- directory listings
- **Packages** (`*.rpm`, `*.deb`, hash-named repodata, `by-hash/`) are cached for 30 days and evicted after 60 days unused. Total size is capped at 110 GB, with 15 GB kept free.
- On a connect error, timeout or 5xx, the request falls through to the next tier. Only the **last** tier may answer from a stale copy, so the order is primary, then fallback, then stale.
@@ -65,6 +70,18 @@ docker buildx build --build-arg PKG_CACHE=https://192.168.1.40 --build-arg PHPVE
- Requires `rpm -K` to report `digests signatures OK`.
- Installs with `--setopt=localpkg_gpgcheck=1`.
**`nodesource MAJOR`** (added 2026-10-22) replaces `curl https://rpm.nodesource.com/setup_N.x | bash`:
- writes `/etc/yum.repos.d/nodesource-nodejs.repo` with the ORIGIN baseurl, `gpgcheck=1` and `gpgkey=file:///usr/local/share/pkg-cache/RPM-GPG-KEY-nodesource` (key committed in `keys/pkg-cache/`);
- with `PKG_CACHE` it is then rewritten like the other repos; `restore` puts the origin version back, so the shipped image keeps a normal NodeSource repo.
**`go-env`** (added 2026-10-22): `eval "$(pkg-cache-repos.sh go-env)"` inside the RUN that runs `go mod download`/`go build`. Prints `GOPROXY=<cache>/goproxy|https://proxy.golang.org|direct` (`|` = fall through on ANY error) and `SSL_CERT_FILE=<state>/ca-bundle.pem`; nothing without `PKG_CACHE`. Modules stay verified by `go.sum` + sum.golang.org. End the RUN with `restore` (removes the bundle).
**EL9**: `release-install epel|remi` picks the EL major from `rpm -E %rhel` (9 or 10); `RPM-GPG-KEY-EPEL-9` is committed.
**Debian** (`apt` mode): `deb.debian.org/debian`, `deb.debian.org/debian-security` and `security.debian.org` (classic and deb822 `.sources`) are rewritten to `<cache>/debian/` and `<cache>/debian-security/`.
**Not proxied, on purpose:** PyPI and the npm registry. Our pip/npm installs are not hash-locked (`pip install -r` without `--require-hashes`, `npm install -g pm2@latest`), so the client would trust whatever the cache served — a compromised cache would mean code execution in shipped images. Proxy them only after the installs are hash-pinned. GitHub-release downloads are likewise left direct.
**`restore`**:
- Puts rewritten files back.
- Deletes files the script created.
@@ -75,9 +92,31 @@ Every RUN that rewrites ends with `restore`, so no shipped layer carries the LAN
`PKG_CACHE` must start with `https://`. `http://` is refused.
`Dockerfile.litespeed` and `Dockerfile.lsphp` are **not wired yet**. Two things are needed first:
- the multi-stage `lsphp-apt-upgrade.sh` flow needs a `PKG_CACHE` ARG in each stage;
- its madison check must accept the cache URL. It currently requires `*rpms.litespeedtech.com*`, and via the cache madison shows `https://192.168.1.40/litespeed/debian`.
`Dockerfile.litespeed` and `Dockerfile.lsphp` are wired since 2026-10-22 (normal apt path; the php.net EMERGENCY stage `lsphp-src` stays on upstream). `lsphp-apt-upgrade.sh`'s madison gate accepts `<PKG_CACHE>/litespeed/` only when `PKG_CACHE` is set.
## Repositories wired (2026-10-22)
The script and `keys/pkg-cache/` are **canonical here**; every other repo carries byte-identical copies (`sha256sum scripts/pkg-cache-repos.sh` to compare). Change it here first, then sync. Same for `.gitea/scripts/resolve-base-image.sh`.
| Repo | Image(s) | Bases | Through the cache | Base digest-pinned |
|---|---|---|---|---|
| cloud-apache-container | cac, cac-fpm, shared-httpd (almalinux/10-base); shared-ols, cac-litespeed, cac-lsphp (litespeedtech/openlitespeed) | Docker Hub | AlmaLinux/EPEL/Remi (rpm); Ubuntu + LiteSpeed (apt) | yes, all 6 jobs |
| cloud-node-container | cnoc:node18..26 | almalinux/10-base | AlmaLinux/EPEL + NodeSource (`nodesource N`) | yes |
| cloud-memcached-container | cmc | almalinux/9-base | AlmaLinux 9 + EPEL 9 | yes |
| cloud-haproxy-container | chc | almalinux/9-base | AlmaLinux 9 + EPEL 9 (inotify-tools GitHub tarball direct) | yes |
| whp-default-container | whp-default | httpd:alpine | nothing to install (mirror only) | yes |
| versitygw-container | versitygw | ubuntu:latest | Ubuntu (versitygw .deb from GitHub direct) | yes |
| haproxy-manager-base | haproxy-manager-base, coraza-spoa | repo.anhonesthost.net python:3.12-slim / golang:1.25 (not Docker Hub: no mirror); gcr.io distroless | Debian (apt) + Go modules (`go-env`); pip direct | n/a; `mirror-base-image.yaml` now copies Docker Hub images by the digest resolved directly from Docker Hub |
| cpanel-importer | cpanel-importer | almalinux:10-minimal | AlmaLinux/EPEL/Remi — **PR #1 open, not merged** (pending rebase onto the PHP 8.5 work) | in the PR |
Not image builds (nothing to wire): kb-anhonesthost, anhonesthost-blog, dao-mail-signup, renovate-runner. ols-mail-client builds images in CI only for scanning/smoke tests (never pushed), its bases are already digest-pinned, and they install no OS packages.
## Adding a new upstream
1. On CT130: back up, then add the prefix to `UPSTREAMS` in `/usr/local/sbin/pkgcache-gen-nginx` (origin first; add a mirror tier only if you measured it is as fresh as the origin). If its mutable metadata isn't covered by `META_RE`, extend it there AND in `/usr/local/sbin/pkgcache-refresh`. Add the prefix to the `location = /` text in `/etc/nginx/pkgcache/server-common.conf`.
2. `pkgcache-gen-nginx > /etc/nginx/sites-available/pkgcache && nginx -t && systemctl reload nginx` (`pct exec` has no /usr/local/sbin in PATH: use full paths). Verify old and new prefixes with `curl --cacert keys/pkg-cache/ca.crt https://192.168.1.40/<prefix>/...` (look at `X-Cache-Status`/`X-Pkgcache-Tier`). CT130 has no egress filter, so no firewall change is needed for new origins.
3. Only proxy upstreams whose content the CLIENT verifies end to end (GPG-signed packages/metadata, Go sumdb, content digests). Commit any signing key under `keys/pkg-cache/` with its fingerprint and provenance in the README.
4. Teach `scripts/pkg-cache-repos.sh` the rewrite (keep the origin as a fallback where the client supports it), test through the cache from a runner-network host, then sync the copies.
## Trust model
@@ -174,8 +213,7 @@ Hub, direct)"**:
- Log lines to look for: `base-image: almalinux/10-base:latest -> almalinux/10-base@sha256:...`
and `pkg-cache: repos=https://192.168.1.40 registry-mirror=192.168.1.40:5000`.
Applied to: Build-and-Push, Build-FPM-Images, Build-Shared-httpd, Build-Shared-OLS
(`litespeedtech/openlitespeed:${OLS_VERSION}-lsphp${PHPVER}`) here, and cloud-node-container.
Applied to every job here (Build-and-Push, FPM, Shared-httpd, Shared-OLS, LiteSpeed, LSPHP) and to every other repo with a Docker Hub base (see "Repositories wired").
The script is canonical here (`.gitea/scripts/resolve-base-image.sh`); other repos
carry byte-identical copies.
+12
View File
@@ -18,3 +18,15 @@ RPM-GPG-KEY-remi2024 Remi's RPM repository 2024 CF1D F005 7CE8 5DFF 5B2F 2A37
Remi rotates keys (remi2025, ...): when remi-release starts being
signed by a new key, `release-install remi` fails loudly - add the
new key here (and to pkg-cache-repos.sh).
RPM-GPG-KEY-EPEL-9 Fedora (epel9) FF8A D134 4597 106E CE81 3B91 8A38 72BF 3228 467C
fetched 2026-10-22 over HTTPS from dl.fedoraproject.org and
mirror.math.princeton.edu (identical); used by `release-install epel`
on EL9 images (cloud-memcached-container, cloud-haproxy-container).
RPM-GPG-KEY-nodesource Nodesource Operations <operations@nodesource.com>
242B 8138 31AF 0956 2B6C 46F7 6B88 DA4E 3AF2 8A14 (rsa4096, 2023-12-22)
fetched 2026-10-22 over HTTPS from
https://rpm.nodesource.com/gpgkey/ns-operations-public.key (the key
NodeSource's own setup_N.x scripts reference); verified by dnf
gpgcheck against the nodejs RPMs. Not on keys.openpgp.org /
keyserver.ubuntu.com - confirm out of band. Used by
`pkg-cache-repos.sh nodesource MAJOR` (cloud-node-container).
+29
View File
@@ -0,0 +1,29 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGE3mOsBEACsU+XwJWDJVkItBaugXhXIIkb9oe+7aadELuVo0kBmc3HXt/Yp
CJW9hHEiGZ6z2jwgPqyJjZhCvcAWvgzKcvqE+9i0NItV1rzfxrBe2BtUtZmVcuE6
2b+SPfxQ2Hr8llaawRjt8BCFX/ZzM4/1Qk+EzlfTcEcpkMf6wdO7kD6ulBk/tbsW
DHX2lNcxszTf+XP9HXHWJlA2xBfP+Dk4gl4DnO2Y1xR0OSywE/QtvEbN5cY94ieu
n7CBy29AleMhmbnx9pw3NyxcFIAsEZHJoU4ZW9ulAJ/ogttSyAWeacW7eJGW31/Z
39cS+I4KXJgeGRI20RmpqfH0tuT+X5Da59YpjYxkbhSK3HYBVnNPhoJFUc2j5iKy
XLgkapu1xRnEJhw05kr4LCbud0NTvfecqSqa+59kuVc+zWmfTnGTYc0PXZ6Oa3rK
44UOmE6eAT5zd/ToleDO0VesN+EO7CXfRsm7HWGpABF5wNK3vIEF2uRr2VJMvgqS
9eNwhJyOzoca4xFSwCkc6dACGGkV+CqhufdFBhmcAsUotSxe3zmrBjqA0B/nxIvH
DVgOAMnVCe+Lmv8T0mFgqZSJdIUdKjnOLu/GRFhjDKIak4jeMBMTYpVnU+HhMHLq
uDiZkNEvEEGhBQmZuI8J55F/a6UURnxUwT3piyi3Pmr2IFD7ahBxPzOBCQARAQAB
tCdGZWRvcmEgKGVwZWw5KSA8ZXBlbEBmZWRvcmFwcm9qZWN0Lm9yZz6JAk4EEwEI
ADgWIQT/itE0RZcQbs6BO5GKOHK/MihGfAUCYTeY6wIbDwULCQgHAgYVCgkICwIE
FgIDAQIeAQIXgAAKCRCKOHK/MihGfFX/EACBPWv20+ttYu1A5WvtHJPzwbj0U4yF
3zTQpBglQ2UfkRpYdipTlT3Ih6j5h2VmgRPtINCc/ZE28adrWpBoeFIS2YAKOCLC
nZYtHl2nCoLq1U7FSttUGsZ/t8uGCBgnugTfnIYcmlP1jKKA6RJAclK89evDQX5n
R9ZD+Cq3CBMlttvSTCht0qQVlwycedH8iWyYgP/mF0W35BIn7NuuZwWhgR00n/VG
4nbKPOzTWbsP45awcmivdrS74P6mL84WfkghipdmcoyVb1B8ZP4Y/Ke0RXOnLhNe
CfrXXvuW+Pvg2RTfwRDtehGQPAgXbmLmz2ZkV69RGIr54HJv84NDbqZovRTMr7gL
9k3ciCzXCiYQgM8yAyGHV0KEhFSQ1HV7gMnt9UmxbxBE2pGU7vu3CwjYga5DpwU7
w5wu1TmM5KgZtZvuWOTDnqDLf0cKoIbW8FeeCOn24elcj32bnQDuF9DPey1mqcvT
/yEo/Ushyz6CVYxN8DGgcy2M9JOsnmjDx02h6qgWGWDuKgb9jZrvRedpAQCeemEd
fhEs6ihqVxRFl16HxC4EVijybhAL76SsM2nbtIqW1apBQJQpXWtQwwdvgTVpdEtE
r4ArVJYX5LrswnWEQMOelugUG6S3ZjMfcyOa/O0364iY73vyVgaYK+2XtT2usMux
VL469Kj5m13T6w==
=Mjs/
-----END PGP PUBLIC KEY BLOCK-----
+52
View File
@@ -0,0 +1,52 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
oSVkzT/Mwp9zFVQu5w==
=drMP
-----END PGP PUBLIC KEY BLOCK-----
+13 -2
View File
@@ -18,7 +18,8 @@
## Fails LOUDLY — never ships the base image's PHP by accident:
## * `apt-get update --error-on=any`: plain `apt-get update` only WARNS when a
## repo is unreachable and carries on with no/old lists, exit 0.
## * the LiteSpeed repo must be the candidate source for lsphp${PHPVER}.
## * the LiteSpeed repo must be the candidate source for lsphp${PHPVER}
## (rpms.litespeedtech.com, or ${PKG_CACHE}/litespeed/ when PKG_CACHE is set).
## * after upgrading, no lsphp${PHPVER}* package may remain upgradable.
## * if CI passed the version it resolved from the repo index (EXPECT_LSPHP_PKG,
## EXPECT_PHP_VERSION), the installed package / running PHP must match it;
@@ -52,8 +53,18 @@ echo "lsphp-apt-upgrade: base image lsphp${PHPVER}=$(dpkg-query -W -f='${Version
# Read each output into a variable and match in the shell: piping into an
# early-exit reader (grep -q, awk ... exit) under pipefail can SIGPIPE the writer
# and report "missing" for a package that is there (scripts/tests/lsphp-info-probe.test.sh).
# With the internal package cache (PKG_CACHE build-arg, scripts/pkg-cache-repos.sh
# apt) the LiteSpeed source reads ${PKG_CACHE}/litespeed/... instead; that URL is
# accepted ONLY when PKG_CACHE is set, and only under its /litespeed/ path.
MADISON=$(apt-cache madison "lsphp${PHPVER}")
if [[ "$MADISON" != *rpms.litespeedtech.com* ]]; then
LS_REPO_OK=0
if [[ "$MADISON" == *rpms.litespeedtech.com* ]]; then
LS_REPO_OK=1
elif [ -n "${PKG_CACHE:-}" ] && [[ "$MADISON" == *"${PKG_CACHE%/}/litespeed/"* ]]; then
LS_REPO_OK=1
echo "lsphp-apt-upgrade: LiteSpeed repo via package cache ${PKG_CACHE%/}/litespeed/"
fi
if [ "$LS_REPO_OK" != 1 ]; then
apt-cache policy "lsphp${PHPVER}" >&2 || true
die "the LiteSpeed apt repo does not offer lsphp${PHPVER} (repo missing from sources, or its index is empty)."
fi
+84 -15
View File
@@ -4,11 +4,16 @@
## when PKG_CACHE is set; without it the repo files are left alone and builds
## use the upstream repositories as before.
##
## PKG_CACHE=https://192.168.1.40 pkg-cache-repos.sh rpm # AlmaLinux/EPEL/Remi
## PKG_CACHE=https://192.168.1.40 pkg-cache-repos.sh apt # Ubuntu + LiteSpeed
## pkg-cache-repos.sh release-install epel [remi] # GPG-verified release RPMs
## PKG_CACHE=https://192.168.1.40 pkg-cache-repos.sh rpm # AlmaLinux/EPEL/Remi/NodeSource
## PKG_CACHE=https://192.168.1.40 pkg-cache-repos.sh apt # Ubuntu, Debian, LiteSpeed
## pkg-cache-repos.sh release-install epel [remi] # GPG-verified release RPMs (EL9/EL10)
## pkg-cache-repos.sh nodesource MAJOR # NodeSource repo file + pinned key
## eval "$(pkg-cache-repos.sh go-env)" # GOPROXY via the cache (go.sum/sumdb verified)
## pkg-cache-repos.sh restore # undo everything above
##
## CANONICAL copy: cloud-apache-container/scripts/pkg-cache-repos.sh (docs/pkg-cache.md
## there). Other repos carry byte-identical copies - change it there first.
##
## Every RUN that rewrites must `restore` before it ends: it puts rewritten files
## back, deletes files this script created, deletes any NEW repo/apt file that
## still references the cache, then FAILS if any reference is left — so no shipped
@@ -43,7 +48,7 @@
## cache (with the CA), and a build without PKG_CACHE uses upstream sources.
set -euo pipefail
MODE="${1:?usage: pkg-cache-repos.sh rpm|apt|release-install NAME...|restore}"
MODE="${1:?usage: pkg-cache-repos.sh rpm|apt|release-install NAME...|nodesource MAJOR|go-env|restore}"
shift || true
STATE=/var/lib/pkg-cache-repos # saved originals + manifest + created files
SHARE="${PKG_CACHE_SHARE:-/usr/local/share/pkg-cache}" # ca.crt + RPM-GPG-KEY-*
@@ -57,10 +62,22 @@ if [ -n "$C" ]; then
https://*) ;;
*) die "PKG_CACHE must be an https:// URL (plain http is refused), got '$C'" ;;
esac
[[ "$C" =~ ^https://[A-Za-z0-9.-]+(:[0-9]+)?(/[A-Za-z0-9._/-]*)?$ ]] || die "PKG_CACHE has unexpected characters: '$C'"
HOSTPORT="${C#https://}"; HOSTPORT="${HOSTPORT%%/*}"
[ -s "$SHARE/ca.crt" ] || die "PKG_CACHE set but $SHARE/ca.crt (pkg-cache CA) is missing"
fi
# System CA bundle (EL vs Debian/Ubuntu path); the pkg-cache CA is appended to a
# copy in the state dir, never to the system store.
sys_bundle() {
local b
for b in /etc/pki/tls/certs/ca-bundle.crt /etc/ssl/certs/ca-certificates.crt; do
[ -s "$b" ] && { echo "$b"; return 0; }
done
die "no system CA bundle found"
}
make_bundle() { cat "$(sys_bundle)" "$SHARE/ca.crt" > "$STATE/ca-bundle.pem"; }
# Files that may hold repo configuration; restore re-checks all of them.
repo_files() {
find /etc/yum.repos.d /etc/dnf /etc/apt -type f 2>/dev/null | sort || true
@@ -112,18 +129,20 @@ if [ "$MODE" = release-install ]; then
curl_opts=(-fsS --proto '=https' --retry 5 --retry-all-errors --max-time 120)
if [ -n "$C" ]; then
start_session
cat /etc/pki/tls/certs/ca-bundle.crt "$SHARE/ca.crt" > "$STATE/ca-bundle.pem"
make_bundle
curl_opts+=(--cacert "$STATE/ca-bundle.pem")
fi
files=()
el=$(rpm -E '%{?rhel}' 2>/dev/null || true)
case "$el" in 9|10) ;; *) die "release-install supports EL9/EL10 only (rpm -E %rhel = '$el')" ;; esac
for name in "$@"; do
case "$name" in
epel) pkg=epel-release key=RPM-GPG-KEY-EPEL-10
path=/epel/epel-release-latest-10.noarch.rpm
origin=https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm ;;
epel) pkg=epel-release key=RPM-GPG-KEY-EPEL-$el
path=/epel/epel-release-latest-$el.noarch.rpm
origin=https://dl.fedoraproject.org/pub/epel/epel-release-latest-$el.noarch.rpm ;;
remi) pkg=remi-release key=RPM-GPG-KEY-remi2024
path=/remi/enterprise/remi-release-10.rpm
origin=https://rpms.remirepo.net/enterprise/remi-release-10.rpm ;;
path=/remi/enterprise/remi-release-$el.rpm
origin=https://rpms.remirepo.net/enterprise/remi-release-$el.rpm ;;
*) die "unknown release package '$name'" ;;
esac
url="$origin"; [ -n "$C" ] && url="$C$path"
@@ -142,14 +161,14 @@ if [ "$MODE" = release-install ]; then
exit 0
fi
if [ -z "$C" ]; then
if [ -z "$C" ] && [ "$MODE" != nodesource ] && [ "$MODE" != go-env ]; then
echo "pkg-cache-repos($MODE): PKG_CACHE not set - using upstream repositories"
exit 0
fi
rewrite_rpm() {
local f="$1"
grep -q -E '^#? ?baseurl=https?://(repo\.almalinux\.org|download\.example|rpms\.remirepo\.net)/' "$f" || return 0
grep -q -E '^#? ?baseurl=https?://(repo\.almalinux\.org|download\.example|rpms\.remirepo\.net|rpm\.nodesource\.com)/' "$f" || return 0
save "$f"
# Per [section]: a (commented or live) baseurl on a known origin becomes
# "baseurl=<cache>/<prefix>/<path> <origin>/<path>"; that section's
@@ -185,6 +204,8 @@ rewrite_rpm() {
l = rw(l, "^#? ?baseurl=https?://repo\\.almalinux\\.org/almalinux/", "almalinux", "https://repo.almalinux.org/almalinux", 1)
l = rw(l, "^#? ?baseurl=https?://download\\.example/pub/epel/", "epel", "https://dl.fedoraproject.org/pub/epel", 0)
l = rw(l, "^#? ?baseurl=https?://rpms\\.remirepo\\.net/", "remi", "https://rpms.remirepo.net", 1)
# NodeSource signs its RPMs but not repomd.xml (404): gpgcheck only.
l = rw(l, "^#? ?baseurl=https?://rpm\\.nodesource\\.com/", "nodesource", "https://rpm.nodesource.com", 0)
}
buf[++n] = l
}
@@ -194,19 +215,65 @@ rewrite_rpm() {
rewrite_apt() {
local f="$1"
grep -q -E 'https?://([a-z]{2}\.)?(archive|security)\.ubuntu\.com/|https?://rpms\.litespeedtech\.com/' "$f" || return 0
grep -q -E 'https?://([a-z]{2}\.)?(archive|security)\.ubuntu\.com/|https?://rpms\.litespeedtech\.com/|https?://(deb|security)\.debian\.org/' "$f" || return 0
save "$f"
# Debian: debian-security first, and "debian" only as a whole path segment,
# so .../debian-security is never rewritten as /debian/.
sed -i -E \
-e "s%https?://(archive|[a-z]{2}\.archive)\.ubuntu\.com/ubuntu/?%$C/ubuntu/%g" \
-e "s%https?://security\.ubuntu\.com/ubuntu/?%$C/ubuntu-security/%g" \
-e "s%https?://rpms\.litespeedtech\.com/%$C/litespeed/%g" \
-e "s%https?://(deb|security)\.debian\.org/debian-security/?([[:space:]]|\$)%$C/debian-security/\\2%g" \
-e "s%https?://security\.debian\.org/?([[:space:]]|\$)%$C/debian-security/\\1%g" \
-e "s%https?://deb\.debian\.org/debian/?([[:space:]]|\$)%$C/debian/\\1%g" \
"$f"
}
if [ "$MODE" = go-env ]; then
# Prints shell exports for `eval`. Without PKG_CACHE: nothing (Go defaults).
# GOPROXY "a|b" falls through on ANY error, so a dead cache costs one
# failed request, not the build. GOSUMDB stays the default sum.golang.org,
# reached directly: modules are still verified against go.sum + the sumdb.
[ -n "$C" ] || { echo "pkg-cache-repos(go-env): PKG_CACHE not set - default GOPROXY" >&2; exit 0; }
start_session
make_bundle
printf "export GOPROXY='%s/goproxy|https://proxy.golang.org|direct' SSL_CERT_FILE='%s'\n" "$C" "$STATE/ca-bundle.pem"
echo "pkg-cache-repos(go-env): GOPROXY via $C/goproxy (fallback proxy.golang.org)" >&2
exit 0
fi
if [ "$MODE" = nodesource ]; then
# Replaces `curl https://rpm.nodesource.com/setup_N.x | bash` (unverified
# remote script): writes the same nodesource-nodejs repo (origin URL, so the
# shipped image keeps a normal repo file) with gpgcheck=1 and the signing key
# committed in keys/pkg-cache/; with PKG_CACHE it is then rewritten like any
# other repo and `restore` puts the origin version back.
major="${1:?usage: pkg-cache-repos.sh nodesource MAJOR}"
[[ "$major" =~ ^[0-9]{1,3}$ ]] || die "bad Node major '$major'"
key="$SHARE/RPM-GPG-KEY-nodesource"
[ -s "$key" ] || die "missing $key"
rpm --import "$key" || die "cannot import $key"
rm -f /etc/yum.repos.d/nodesource*.repo
f=/etc/yum.repos.d/nodesource-nodejs.repo
printf '%s\n' "[nodesource-nodejs]" \
"name=Node.js Packages for Linux RPM based distros - \$basearch" \
"baseurl=https://rpm.nodesource.com/pub_${major}.x/nodistro/nodejs/\$basearch" \
"priority=9" "enabled=1" "gpgcheck=1" \
"gpgkey=file://$key" "module_hotfixes=1" > "$f"
echo "pkg-cache-repos: wrote $f (Node ${major}.x, key $(basename "$key"))"
if [ -n "$C" ]; then
start_session
make_bundle
rewrite_rpm "$f"
grep -h '^baseurl=' "$f" | sed 's/^/ /'
fi
exit 0
fi
case "$MODE" in
rpm)
start_session
cat /etc/pki/tls/certs/ca-bundle.crt "$SHARE/ca.crt" > "$STATE/ca-bundle.pem"
make_bundle
for f in /etc/yum.repos.d/*.repo; do [ -f "$f" ] && rewrite_rpm "$f"; done
echo "pkg-cache-repos(rpm): repos now via $C:"
grep -h '^baseurl=' /etc/yum.repos.d/*.repo | grep -F "$C/" | sort -u | sed 's/^/ /'
@@ -221,7 +288,9 @@ case "$MODE" in
[ -f "$f" ] && rewrite_apt "$f"
done
echo "pkg-cache-repos(apt): sources now via $C:"
grep -h -E '^(deb|URIs:)' /etc/apt/sources.list /etc/apt/sources.list.d/* 2>/dev/null | grep -F "$C/" | sort -u | sed 's/^/ /'
# (|| true: Debian 13 images have no /etc/apt/sources.list; grep's exit 2
# for the missing file must not fail the build under pipefail)
{ grep -h -E '^(deb|URIs:)' /etc/apt/sources.list /etc/apt/sources.list.d/* 2>/dev/null || true; } | grep -F "$C/" | sort -u | sed 's/^/ /' || true
;;
*) die "unknown mode '$MODE'" ;;
esac