Repository navigation
Image hardening - #30
Open
KushagarGoel1 wants to merge 4 commits into
Open
KushagarGoel1 wants to merge 4 commits into
KushagarGoel1 wants to merge 4 commits into
Conversation
Build and run the server image on Docker Hardened Images: dhi.io/rust to build, dhi.io/debian-base (debian-13) to run. The runtime has no shell and no package manager, so: - curl and ca-certificates are no longer installed: TLS roots are compiled into the binary (rustls with webpki-roots). - The Docker HEALTHCHECK is gone; the platform probes /healthz and /readyz over HTTP, which answer 503 until the server is ready. - The server runs as the image's nonroot user (uid 65532) instead of a streamgres user made with useradd (uid 10001). The binary is root-owned; only /var/lib/streamgres is writable. /var/lib/xyne-sync is dropped. - BASE_REGISTRY is replaced by whole-image BUILD_IMAGE and RUNTIME_IMAGE arguments, since DHI image names differ from the official ones. CI logs in to dhi.io (pulls need an account), and publishing now builds, scans with Trivy (failing on fixable critical or high findings), then pushes with an SBOM and provenance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dhi.io refuses anonymous pulls, so every build would need a Docker account. Google's distroless gives the same runtime properties (no shell, no package manager, nonroot uid 65532) from a public registry: run on gcr.io/distroless/cc-debian13:nonroot, built on rust:1.89-trixie so both stages share Debian 13's glibc. The dhi.io login steps are dropped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
santhoshJus
approved these changes
Oct 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hardens the server image, as part of the image hardening checklist (streamgres was listed on
debian:bookworm-slim). It follows the same approach as jamsocket/y-sweet#435: Google's distroless runtime, which needs no registry login.Changes
rust:1.89-trixieto build,gcr.io/distroless/cc-debian13:nonrootto run. Both are Debian 13, so the binary runs on the glibc it was linked against. The runtime has no shell, no package manager and no coreutils.libc,libmandlibgcc_s, whichccprovides, and TLS is rustls with its roots compiled in (webpki-roots).HEALTHCHECK: there's no shell to run one, and Kubernetes ignores it anyway. Readiness and liveness come from HTTP probes on/healthzand/readyz, which return 503 until the feed is past its first snapshot. The CI end-to-end job still waits on/healthwith curl from the runner.nonroot(uid 65532) instead of astreamgresuser created withuseradd(uid 10001). The binary is root-owned and read-only to the server; only/var/lib/streamgres(the plan file) is writable. The leftover/var/lib/xyne-syncis dropped.BASE_REGISTRYis replaced by whole-imageBUILD_IMAGEandRUNTIME_IMAGE, because the two stages now come from different registries.docs/deploy.mdis updated to match.Results (local build; CVEs counted with a one-off Trivy 0.58.1 scan, not part of CI)
mainstreamgres(10001)65532:65532exec: "sh": not found)The image starts and fails only on missing config (
STREAMGRES_PG_DSN … must name the database), as expected. No Rust code changes.Before merging
securityContext.runAsUser, ownership of a plan-file volume; usefsGroup: 65532). If the root filesystem is read-only, mount an emptyDir at/tmpfor heap profiles when Pyroscope is on. Confirm the deployment has HTTP readiness and liveness probes.🤖 Generated with Claude Code