Releases: 6RUN0/docker-freeunit-php
Releases · 6RUN0/docker-freeunit-php
Release list
v0.0.8
Added
.trivyignorelisting the HIGH/CRITICAL CVEs in the Debian trixie base and the
sury PHP / image-codec stack that have no upstream fix (none are in FreeUnit's
own.debpackages, and none are resolvable by theapt full-upgradethe build
already runs), somake scanand the CI scan surface only new, actionable
findings instead of a permanent unfixable backlog.
Changed
- Bumped the bundled FreeUnit
.debrelease to1.35.6-build4and recomputed the
FREEUNIT_SHA256SUMS_SHA256trust anchor. Upstream re-published the same
1.35.6-1package under a new release tag, so the bundled FreeUnit and PHP
versions are unchanged — this is a rebuild-only refresh.
v0.0.7
Changed
- Bumped the bundled FreeUnit
.debrelease to1.35.6-build3and recomputed the
FREEUNIT_SHA256SUMS_SHA256trust anchor. Upstream re-published the same
1.35.6-1package under a new release tag, so the bundled FreeUnit and PHP
versions are unchanged — this is a rebuild-only refresh.
v0.0.6
Changed
- FreeUnit rebrand (breaking for downstream images). Upstream renamed its
Debian packages and on-disk identity fromunit*tofreeunit*, and the image
follows suit: the daemon isfreeunitd/freeunitd-debug, the state dir
/var/lib/freeunit, the control socket/var/run/control.freeunit.sock, the log
/var/log/freeunit.log, and the default application user/groupfreeunit(was
unit). Downstream images must move anyconfig.jsonuser/groupkeys and
any custom launch command fromunit/unitdtofreeunit/freeunitd; the
reusable entrypoint library keeps its function names andUNIT_*/APPLICATION_*
variable identifiers, so hooks that only call the documented API are unaffected. - Bumped the bundled FreeUnit
.debrelease to1.35.6-build2(1.35.6-1) and
recomputed theFREEUNIT_SHA256SUMS_SHA256trust anchor. - The brand identity is single-sourced as Dockerfile
ARGs mirroring the upstream
packaging vocabulary (BRAND,RUNTIME,RUNDIR,BRAND_TITLE,HOMEPAGE,
DOCS_URL). They default tofreeunit//var/runand the build now asserts the
installed binary's compiled paths matchRUNTIME/RUNDIR, so a future upstream
identity change fails the build instead of shipping an image whose entrypoint
manages paths the daemon does not use. - The default launch command moved out of the Dockerfile
CMDinto the entrypoint,
and theHEALTHCHECKis now a script (/docker-healthcheck.sh), so the binary
name and control-socket path stay single-sourced fromdocker-entrypoint-common.sh
instead of being duplicated in an exec-form instruction that cannot expand a
build ARG.
v0.0.5
Added
examples/grew into a capability-coverage set:dev(a live-mounted
development loop writing to a persistent state volume as the unprivileged app
user),routing(multiple apps behind path routes, static-asset serving, and a
per-app PHPmemory_limit), andweb-app(HTTPS from an entrypoint-generated
self-signed certificate, with an HTTP-to-HTTPS redirect), alongside the existing
basicandcron-hook. Each example is a self-contained subdirectory with its
own README.make test-examples: an examples gate that statically lints every example's
compose file for the capability-hardening block (cap_drop,no-new-privileges,
SETUID,SETGID), then builds, runs, and asserts each example end to end
against the just-built image.make help: a self-documenting target list parsed from the##-prefixed
comment annotations on the targets themselves.
Changed
- The
cron-hookexample fires its task every second using supercronic's
seven-field (seconds) crontab syntax, so the example and its test no longer wait
out a full minute for a tick. - CI asserts the PHP build matrix is in sync across
ci.yml,release.yml,
security-scan.yml, andcheck-upstream.yml's completeness gate against the
Makefile'sPHP_VERSIONS, failing the lint job on any drift. release.ymlguards each Dockerfile-ARG extraction, failing loudly rather than
pushing a malformed tag if an ARG line format ever drifts.- Repository hygiene: added
.gitattributes, tightened.editorconfig, and
ignored thedocs/superpowers/working notes.
Fixed
- Documentation: corrected the deb.sury.org pin priority described in
CLAUDE.md
(990, not 1001 — below 1000 so a compromised mirror cannot force a downgrade) and
the stale crontab field-count comments in the examples test, aligning the docs
with the shippedDockerfileand crontab.
v0.0.4
Added
- Extensible entrypoint hook system: a child image adds a launch mode by dropping
ahandle_<command>hook into/docker-entrypoint-hook.d/(sourced and
ownership-vetted as root before any privilege drop), and the entrypoint became a
thin dispatcher over a reusable core library (docker-entrypoint-common.sh) of
logging, daemon lifecycle, config appliers, privilege drop, and user
provisioning. Downstream images inherit every base robustness/security fix
without overwriting/docker-entrypoint.sh. examples/cron-hook/: an example of the hook system — one image runs in two
roles, the Unit web server and a long-livedsupercroniccron runner, selected
per container by the command (supercronicis pinned and SHA256-verified).test/entrypoint-lib.shgained checks for the hook dispatch contract
(dispatch_handler), theexec_as_userprivilege drop,setup_userid
validation and idempotency, thedir_has_contentempty/non-empty boundary, and
newline-less / non-numeric pidfiles. The host-side CLI parser and image build
shared by both test drivers were extracted intotest/lib.sh.
Changed
apply_confignow warns when more than one*.jsonis present in
/docker-entrypoint.d, sincePUT /configreplaces the whole configuration and
only the lexically-last file survives.wait_for_control_socketbounds each probe withcurl --max-time, and
run_entrypoint_scriptsnow reports which user script failed.examples/reorganised so each example is a self-contained subdirectory
(examples/basic/,examples/cron-hook/) with an indexREADME.md.- CI pins ShellCheck to the version used locally — the runner's bundled one
flagged false positives on the library's optional-argument and
trap/dispatch-invoked functions — and now lints each example'sREADME.md.
Fixed
- A child-hook
handle_<cmd>that exits non-zero no longer aborts the entrypoint
silently underset -ebefore its diagnostic. Dispatch moved into
dispatch_handler, which reports both a non-zero exit and a return-without-exec
with an actionable message. stop_unitno longer skipskill -TERMwhen the pidfile has no trailing
newline (readreturns non-zero at EOF even after assigning the value). The new
read_pidhelper decouples the value fromread's exit status and ignores a
non-numeric pid, so a corrupt pidfile cannot become a broad kill.dir_has_contenttreats an existing-but-unreadable directory as an error rather
than "empty", so a transientEACCESon the state dir cannot trigger a
re-initialisation over a populated state.
Security
exec_as_usernow passessetpriv --no-new-privs, so a child-image hook's
privilege drop is irreversible inside the image even if the operator omits
--security-opt=no-new-privileges.- The first-run failure wipe (
find … -delete) gained-xdev, so it stops at
filesystem boundaries and never deletes through a host volume bind-mounted
inside/var/lib/unit. apply_certificatesvalidates the bundle name to[A-Za-z0-9._-], so a crafted
*.pemfilename cannot retarget the control-APIPUTat another endpoint.
v0.0.3
Added
- Supply-chain attestations on release:
release.ymlnow generates an SPDX SBOM
for each pushed image and records keyless (OIDC) build-provenance and SBOM
attestations, pushed to GHCR as OCI referrers of the image manifest. Verify a
pulled image with
gh attestation verify oci://ghcr.io/6run0/freeunit-php@<digest> --owner 6RUN0. .github/workflows/check-upstream.yml: a weekly (and manually dispatchable)
job that watches the FreeUnit package repo for a new release and opens a bump
PR — it recomputes the pinnedFREEUNIT_SHA256SUMS_SHA256trust anchor and
refuses to bump unless every matrixed PHP line ships a module.debin the new
SHA256SUMS..github/dependabot.yml: weekly grouped bump PRs for the SHA-pinned GitHub
Actions.- CI lint job gained workflow and markdown gates: actionlint, zizmor (workflow
security audit), and rumdl. - The CI trivy scan now emits SARIF and uploads it to GitHub code scanning, so
CVEs surface in the Security tab and are tracked over time. .github/workflows/security-scan.yml: a weekly (and manually dispatchable)
trivy re-scan of the published GHCR images per PHP line, so CVEs disclosed
after a release surface without a new push.examples/: a self-contained, security-hardened deployment — a small
Dockerfilebakes the app and its Unit config onto the published base image
(config copied into/docker-entrypoint.d, no bind mounts), run with cap-drop
andno-new-privilegeshardening, with a worker that drops to theunituser.
Changed
- CI build+smoke matrix now runs through Buildx with a per-PHP GitHub Actions
layer cache (type=gha), so repeat runs reuse the apt/download layers instead
of rebuilding from scratch; the trivy scan reuses the 8.4 image rather than its
own build. - The smoke test now runs the container under the documented hardening
(--cap-drop=ALL …), so a regression that breaks cap-dropped startup (such as
a non-root-owned state directory) is caught in CI; the*.pemupload it already
asserts exercises the affected certs store.
Fixed
- The container aborted on startup under the README's own hardening recipe
(--cap-drop=ALL …):/var/lib/unitwas owned byunit:unit, so the root
unitdmaster — stripped ofCAP_DAC_OVERRIDEby the dropped capabilities —
could not create itscerts/andscripts/stores (mkdir … EACCES) and
failed to store the configuration. The state directory is now kept root-owned
(the master is root by design), so cap-dropped startup works; the per-app
worker still drops tounitvia the Unit config.
v0.0.2
Added
test/smoke.shgained a--buildflag (with--php X.Y) so a single
invocation covers the whole build -> run -> assert pipeline; the PHP line is
taken from--php, else parsed from the image ref'sphpX.Ytag, else the
Dockerfile ARG default. Without--buildthe script still tests a prebuilt
image, somake testand the CI build+smoke step are unchanged.
Fixed
rootfs/docker-entrypoint.sh: stop the post-configuration daemon with an
explicitifinstead of the[ -f pid ] && kill … || trueone-liner, fixing
a ShellCheck SC2015 failure on the CI runner's shellcheck and stating the
intent more clearly.test/smoke.sh: poll the Unit control socket when verifying the uploaded
certificate, fixing an intermittent CI failure where the controller had not
finished restarting after initial configuration before the single probe ran.