Run the pod as non-root with a read-only filesystem

Part of the same security-hardening pass as the last three commits.
Neither the Dockerfile nor the chart's Deployment set any securityContext
at all, so the container ran as root by default — scratch has no
/etc/passwd for a USER directive to resolve against, so nobody had set one.

Dockerfile now ends with USER 65532:65532 (numeric, since scratch has no
user database; 65532 is the common "nonroot" convention, distroless's own
uid). The chart's Deployment adds a matching pod-level securityContext
(runAsNonRoot, runAsUser/runAsGroup: 65532, seccompProfile: RuntimeDefault)
plus per-container hardening (allowPrivilegeEscalation: false,
capabilities dropped, readOnlyRootFilesystem: true) on both the app
container and the wait-for-postgres init container — neither writes
anything to disk, so the root filesystem can stay read-only.

Verified with helm-lint and a manual `helm template` render of both the
terdut-server and terdut-demo charts. Not yet verified: an actual pod
starting with these in place — readOnlyRootFilesystem is exactly where a
non-obvious write (a temp file, a cache dir) would surface as a crash
rather than a lint error, so that needs a real rollout to confirm.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Niklas Ye
2026-10-07 22:16:06 +02:00
parent f15db0e20a
commit 92959cac38
2 changed files with 32 additions and 0 deletions
+6
View File
@@ -24,4 +24,10 @@ FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /terdut /terdut
EXPOSE 8080
# Numeric, not a name: scratch has no /etc/passwd for one to resolve against,
# and Docker's USER accepts a bare UID:GID without it. 65532 is the common
# "nonroot" convention (distroless's own uid), chosen so the chart's pod
# securityContext (runAsNonRoot, runAsUser: 65532) matches what the image
# already runs as rather than fighting it.
USER 65532:65532
ENTRYPOINT ["/terdut"]