Harden Web/PWA image and gate publishes on web CalVer bumps #250

Closed
opened 2026-06-03 11:09:40 +00:00 by steve · 0 comments
Owner

Follow up the Web/PWA container publish path by moving the runtime image itself
onto Docker Hardened Images Caddy, keeping the web package version on CalVer,
and making automatic image publishes run when the web package manifest changes
or when the web Dockerfile changes.

Problem

The current docker/web/Dockerfile copies the Caddy binary from the upstream
caddy:2.11.3-alpine image. Registry scanners are reporting vulnerabilities in
that layer. The current publish workflow also auto-runs for a broad set of web
package, script, and Docker inputs, which means publishing is coupled to source
changes instead of an explicit release/version bump. The web package version is
still 0.0.1, so the versioned image tags do not yet communicate a useful web
release date.

Goal

Publish the Web/PWA image from a hardened Caddy source image, use YYYY.M.D
CalVer in packages/web/package.json, and treat that manifest version bump as
the automatic publish trigger while keeping manual workflow dispatch available.

Scope

  • Replace the Web/PWA runtime image in docker/web/Dockerfile with Docker
    Hardened Images Caddy instead of the current distroless final stage.
  • Update packages/web/package.json from 0.0.1 to CalVer in YYYY.M.D
    format.
  • Narrow .forgejo/workflows/publish-web.yml so automatic publishes run when
    packages/web/package.json or docker/web/Dockerfile changes on main,
    while preserving manual dispatch.
  • Keep the web and release-management specs current with the hardened runtime
    and manifest-driven release semantics.

Non-goals

  • Do not broaden this work into hardening the repo's general CI image or other
    unrelated Docker images.
  • Do not change the Web/PWA runtime behavior beyond the image source, version
    metadata, and publish trigger semantics.
  • Do not add a new same-day CalVer increment policy in this change.

Acceptance Criteria

  • docker/web/Dockerfile no longer relies on the upstream Alpine Caddy image or
    the distroless final stage, and instead uses Docker Hardened Images Caddy for
    the Web/PWA runtime image while staying compatible with the existing
    linux/amd64 and linux/arm64 publish matrix.
  • packages/web/package.json uses YYYY.M.D CalVer and that value continues
    to drive the versioned Docker tags and OCI image metadata.
  • .forgejo/workflows/publish-web.yml auto-runs on main when
    packages/web/package.json or docker/web/Dockerfile changes, while still
    supporting manual dispatch.
  • The workflow still publishes the short SHA, raw version, v<version>, and
    latest tags.
  • The relevant web and release-management specs describe the hardened Caddy
    source and the manifest-gated publish model.

Implementation Notes

  • Preferred hardened runtime reference: dhi.io/caddy:2 unless a more specific
    compatible stream is confirmed during implementation.
  • The publish workflow should continue reading the version from
    packages/web/package.json so the manifest remains the single release source
    of truth.
  • Automatic publishes still treat packages/web/package.json as the web release
    source of truth for version tags, but Dockerfile-only image fixes should also
    trigger the publish workflow on main. Keep that distinction explicit in the
    specs.

Suggested Files or Specs To Inspect

  • docker/web/Dockerfile
  • packages/web/package.json
  • .forgejo/workflows/publish-web.yml
  • spec/src/20-packages/web/index.md
  • packages/web/spec.md
  • spec/src/80-maintenance/release-management.md

Validation Commands

  • docker manifest inspect dhi.io/caddy:2
  • docker buildx build --platform linux/amd64 --file docker/web/Dockerfile --build-arg LAPIS_BUILD_COMMIT=<sha> --build-arg LAPIS_WEB_VERSION=<version> --tag lapisnotes/web:test --load .
  • docker run --rm --read-only --cap-drop=ALL --security-opt no-new-privileges -p 8080:8080 lapisnotes/web:test
  • curl http://localhost:8080/healthz
  • pnpm check:all
  • make spec-lint
  • mdbook build spec

Follow-up Tasks

Implementation Summary

Moved the Web/PWA runtime to dhi.io/caddy:2, kept DHI and Docker Hub auth in publish-web, preserved CalVer tags and Dockerfile-triggered publishes, and scoped the Docker build install to the web dependency closure.

Reopen Reason

Follow-up: docker/web/Dockerfile still uses a distroless final stage, but the
runtime image itself should also move to Docker Hardened Images Caddy.

Follow up the Web/PWA container publish path by moving the runtime image itself onto Docker Hardened Images Caddy, keeping the web package version on CalVer, and making automatic image publishes run when the web package manifest changes or when the web Dockerfile changes. ## Problem The current `docker/web/Dockerfile` copies the Caddy binary from the upstream `caddy:2.11.3-alpine` image. Registry scanners are reporting vulnerabilities in that layer. The current publish workflow also auto-runs for a broad set of web package, script, and Docker inputs, which means publishing is coupled to source changes instead of an explicit release/version bump. The web package version is still `0.0.1`, so the versioned image tags do not yet communicate a useful web release date. ## Goal Publish the Web/PWA image from a hardened Caddy source image, use `YYYY.M.D` CalVer in `packages/web/package.json`, and treat that manifest version bump as the automatic publish trigger while keeping manual workflow dispatch available. ## Scope - Replace the Web/PWA runtime image in `docker/web/Dockerfile` with Docker Hardened Images Caddy instead of the current distroless final stage. - Update `packages/web/package.json` from `0.0.1` to CalVer in `YYYY.M.D` format. - Narrow `.forgejo/workflows/publish-web.yml` so automatic publishes run when `packages/web/package.json` or `docker/web/Dockerfile` changes on `main`, while preserving manual dispatch. - Keep the web and release-management specs current with the hardened runtime and manifest-driven release semantics. ## Non-goals - Do not broaden this work into hardening the repo's general CI image or other unrelated Docker images. - Do not change the Web/PWA runtime behavior beyond the image source, version metadata, and publish trigger semantics. - Do not add a new same-day CalVer increment policy in this change. ## Acceptance Criteria - `docker/web/Dockerfile` no longer relies on the upstream Alpine Caddy image or the distroless final stage, and instead uses Docker Hardened Images Caddy for the Web/PWA runtime image while staying compatible with the existing `linux/amd64` and `linux/arm64` publish matrix. - `packages/web/package.json` uses `YYYY.M.D` CalVer and that value continues to drive the versioned Docker tags and OCI image metadata. - `.forgejo/workflows/publish-web.yml` auto-runs on `main` when `packages/web/package.json` or `docker/web/Dockerfile` changes, while still supporting manual dispatch. - The workflow still publishes the short SHA, raw version, `v<version>`, and `latest` tags. - The relevant web and release-management specs describe the hardened Caddy source and the manifest-gated publish model. ## Implementation Notes - Preferred hardened runtime reference: `dhi.io/caddy:2` unless a more specific compatible stream is confirmed during implementation. - The publish workflow should continue reading the version from `packages/web/package.json` so the manifest remains the single release source of truth. - Automatic publishes still treat `packages/web/package.json` as the web release source of truth for version tags, but Dockerfile-only image fixes should also trigger the publish workflow on `main`. Keep that distinction explicit in the specs. ## Suggested Files or Specs To Inspect - `docker/web/Dockerfile` - `packages/web/package.json` - `.forgejo/workflows/publish-web.yml` - `spec/src/20-packages/web/index.md` - `packages/web/spec.md` - `spec/src/80-maintenance/release-management.md` ## Validation Commands - `docker manifest inspect dhi.io/caddy:2` - `docker buildx build --platform linux/amd64 --file docker/web/Dockerfile --build-arg LAPIS_BUILD_COMMIT=<sha> --build-arg LAPIS_WEB_VERSION=<version> --tag lapisnotes/web:test --load .` - `docker run --rm --read-only --cap-drop=ALL --security-opt no-new-privileges -p 8080:8080 lapisnotes/web:test` - `curl http://localhost:8080/healthz` - `pnpm check:all` - `make spec-lint` - `mdbook build spec` ## Related Issues - Follow-up to #248 — [Add Web/PWA image health endpoint and app tags](../closed/248-add-web-pwa-image-health-endpoint-and-app-tags.md) ## Follow-up Tasks ## Implementation Summary Moved the Web/PWA runtime to dhi.io/caddy:2, kept DHI and Docker Hub auth in publish-web, preserved CalVer tags and Dockerfile-triggered publishes, and scoped the Docker build install to the web dependency closure. ## Reopen Reason Follow-up: `docker/web/Dockerfile` still uses a distroless final stage, but the runtime image itself should also move to Docker Hardened Images Caddy. <!-- backlog:task_id=TASK-WEB-PWA-IMAGE-CALVER-HARDENING source_spec=spec/src/20-packages/web/index.md related_issue=248 -->
steve 2026-06-03 11:09:40 +00:00
steve referenced this issue from a commit 2026-06-03 11:22:25 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lapis-notes/lapis#250
No description provided.