No description
  • Dockerfile 100%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Maël Gramain 4270de58b6
All checks were successful
lint / hadolint (push) Successful in 16s
lint / build (push) Successful in 1m44s
release / build (push) Successful in 1m45s
release / sign (push) Successful in 18s
fix: get the whole boot sequence working under PSS restricted
The conf.d permission fix only got the entrypoint past its first write. Two
further walls, both found by running this image as uid 65534 with
--cap-drop ALL --security-opt no-new-privileges, which approximates the
cluster's PSS restricted floor:

1. "su: must be suid to work properly". The entrypoint runs four commands
   through `su -c "..." -s /bin/sh nobody`, and /bin/busybox is 0755 in the
   upstream image -- busybox su refuses to run at all when it is not setuid,
   whatever the target user. It is switching to the user we already are, so
   the wrapper is dropped and the command runs directly. (An earlier note in
   kube-charts claimed busybox tolerated this same-uid switch; it does not.)

2. "s6-svscan: fatal: unable to open .s6-svscan/lock: Permission denied",
   then the same class of failure for nginx and php-fpm. s6-svscan writes a
   lock and a supervise/ dir per service under /etc/s6, nginx writes
   /var/run/nginx.pid plus its compiled-in temp paths under /var/lib/nginx,
   and both services log under /var/log -- all root- or nginx-owned (uid
   100) and unwritable by 65534. Ownership handed to 65534, which is the only
   user anything in this image runs as under PSS restricted.

Verified end to end against a throwaway Postgres: composer install,
cache:clear and assets:install all complete, s6 comes up, and the container
answers 200 on /api/info -- the same path the chart's liveness probe uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 01:03:43 +02:00
.forgejo/workflows ci: pin the rotated cosign public key 2026-08-21 21:28:52 +02:00
Dockerfile fix: get the whole boot sequence working under PSS restricted 2026-08-22 01:03:43 +02:00
README.md ci: stop using a COSIGN_PASSWORD secret 2026-08-21 05:20:40 +02:00

wallabag-image

A custom wallabag/wallabag image with a single permission fix so it runs under Kubernetes Pod Security Standards restricted (forced non-root, no extra capabilities).

Why

The stock image's entrypoint unconditionally writes a generated PHP ini file into /etc/php81/conf.d/ on every boot, but that directory ships 755 root:root — no group-write bit. Under PSS restricted the container runs as uid/gid 65534 (nobody), so that write fails and the entrypoint (set -e) crash-loops the pod. Full root-cause writeup: kube-charts/docs/wallabag-custom-image.md (in the sibling kube-charts repo). This repo is just the fix, verified to work — see the Dockerfile for the two-line change.

Build locally

docker build -t wallabag-image:local .
# or pin a specific upstream version:
docker build --build-arg WALLABAG_VERSION=2.6.14 -t wallabag-image:local .

Verify the fix (should print WRITE_OK, matching what the entrypoint does on every boot):

docker run --rm -u 65534:65534 wallabag-image:local sh -c \
  'envsubst < /etc/wallabag/php-wallabag.template.ini > /etc/php81/conf.d/50_wallabag.ini && echo WRITE_OK'

The same command against stock wallabag/wallabag:2.6.14 fails with Permission denied.

Release

Pushing a git tag (e.g. v2.6.14-1) triggers .forgejo/workflows/release.yml, which builds, pushes to git.gnous.eu/gnouseu/wallabag, and cosign-signs the pushed digest per kube-charts/docs/image-signing.md.

The build is daemonless (kaniko): the shared Forgejo Actions runner does not mount the host docker socket into job containers, so there is no daemon to build against. kaniko's image ships no node, which means no JavaScript action (actions/checkout included) can run in that job -- it clones the source itself, pinned to the tagged commit.

Requires these Actions secrets on the repo or the gnouseu org: GNOUS_REGISTRY_USERNAME, GNOUS_REGISTRY_PASSWORD, COSIGN_PRIVATE_KEY.

There is no COSIGN_PASSWORD: the gnous CI key has no password. cosign still wraps such a key in an ENCRYPTED SIGSTORE PRIVATE KEY envelope, so the workflow sets COSIGN_PASSWORD to an empty string inline — undefined is not equivalent, cosign would prompt and fail on the missing tty.

Consumer

Once an image is pushed here, kube-charts' values/wallabag/values.yaml gets its image.repository/image.tag updated to point at git.gnous.eu/gnouseu/wallabag. That update, and un-pausing the wallabag migration, is a kube-charts-side follow-up — not part of this repo.