Repository navigation
feat(events-processor): harden the production Dockerfile onto the Wolfi bases - #811
Merged
Merged
Conversation
Replaces the rust:1.85 -> golang:1.25 -> debian:13-slim chain with the lago-packages bases, matching what lago-gotenberg, lago-license and lago-oauth-proxy already run. The debian:13-slim runtime shipped apt, a full shell userland and ran as root. events-processor-base is glibc + libgcc + ca-certificates-bundle + tzdata and nothing else, with run-as 65532 baked into the image config. Both bases already exist and are published; no lago-packages change is needed. Two things worth calling out beyond the base swap: CGO stays on. expression-go binds to libexpression_go.so through `#cgo LDFLAGS: -lexpression_go`, so this cannot become a static build. The .so is staged on the linker path in the go stage (not just the runtime stage) because -lexpression_go resolves at link time, and events-processor-base carries glibc and libgcc for it at runtime. lago-expression is pinned by commit, not by tag. The old `git clone --tags` + `git checkout v0.2.0` trusted a ref that can be repointed and dragged every branch and tag along to do it; this fetches the single pinned commit (62 objects) and is what `v0.2.0` resolved to. Verified: the pinned shallow fetch works against GitHub, the workspace builds `--package expression-go` clean on rust 1.98 (what Wolfi's `rust` provide currently resolves to, vs the 1.85 pinned before), and events-processor's modules pass `go mod verify`. Not verified locally: no container runtime on hand for a full image build. The branch build in CI is the real check, and staging-eu-1 is where it gets booted.
IxDay
marked this pull request as draft
September 30, 2026 15:30
IxDay
force-pushed
the
feat/events-processor-wolfi-hardened
branch
from
September 30, 2026 15:30
2e8f228 to
69e6260
Compare
IxDay
marked this pull request as ready for review
October 8, 2026 08:07
koikonom
approved these changes
Oct 8, 2026
IxDay
added a commit
that referenced
this pull request
Oct 8, 2026
#811 hardened the production events-processor/Dockerfile onto the Wolfi/apko bases, which is the only reason Dockerfile.staging existed — staging needed a Wolfi build while prod was still on Debian. With both on Wolfi the two files were near-duplicates, and the production one is strictly better: immutable base pins, a sha-pinned LAGO_EXPRESSION_REF instead of a repointable tag, a single-commit fetch instead of `git clone --tags`, go mod verify, explicit CGO_ENABLED=1, and OCI labels. The staging build keeps its distinct role via build-args in lago-deploy#3611: the bases are overridden to `:latest` so staging still rides the daily lago-packages CVE rebuild, while production stays reproducible on a pinned base. Requires lago-deploy#3611 to merge first — it repoints the staging workflow at events-processor/Dockerfile. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
IxDay
added a commit
that referenced
this pull request
Oct 8, 2026
#811 hardened the production events-processor/Dockerfile onto the Wolfi/apko bases, which is the only reason Dockerfile.staging existed — staging needed a Wolfi build while prod was still on Debian. With both on Wolfi the two files were near-duplicates, and the production one is strictly better: immutable base pins, a sha-pinned LAGO_EXPRESSION_REF instead of a repointable tag, a single-commit fetch instead of `git clone --tags`, go mod verify, explicit CGO_ENABLED=1, and OCI labels. The staging build keeps its distinct role via build-args in lago-deploy#3611: the bases are overridden to `:latest` so staging still rides the daily lago-packages CVE rebuild, while production stays reproducible on a pinned base. Requires lago-deploy#3611 to merge first — it repoints the staging workflow at events-processor/Dockerfile. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
What this is for
Dockerfile.staginghardened the staging build path and deliberately left./Dockerfilealone. That means the production events-processor — what prod-us-1 and prod-eu-1 actually run — is stilldebian:13-slimrunning as root. This PR closes that.rust:1.85ghcr.io/getlago/events-processor-buildgolang:1.25ghcr.io/getlago/events-processor-builddebian:13-slim+apt-get install ca-certificatesghcr.io/getlago/events-processor-baseResult, built from this branch (
lago-events-processor:sha-2e8f228): 30.6MB vs 74.7MB, and the image config carriesUser: 65532instead of root.Relationship to
Dockerfile.stagingThe two would be near-duplicates, which is how they drift. Once this lands,
Dockerfile.stagingand lago-deploy'sbuild-events-processor-staging-image.ymlshould collapse back onto the single production Dockerfile. I have deliberately not done that here — deleting the staging path before its bake completes would remove the safety net this whole sequence exists to provide. Happy to fold it into this PR or leave it as a follow-up, whichever you prefer.Where it differs from
Dockerfile.stagingNot just a copy — three fixes worth keeping whichever file survives:
Dockerfile.stagingdoesgit clone --tags …+git checkout v0.2.0: a ref that can be repointed, and it drags every branch and tag down to do it. This fetches the single pinned commita22ab02— 62 objects.:latest. A base bump becomes a reviewable diff instead of a silent change under a floating tag.go mod verifyalongsidego mod download.Two things worth a reviewer's attention
CGO stays enabled — this cannot be a static build.
expression-gobinds tolibexpression_go.sovia#cgo LDFLAGS: -lexpression_go. The.sois staged onto the linker path in the go stage as well as the runtime stage, because-lexpression_goresolves at link time, not just at load time. That is why the runtime base carriesglibcandlibgcc.Pre-existing version skew, preserved.
go.modrequiresexpression-go v0.1.4while the Dockerfile builds the cdylib fromv0.2.0. That predates this PR and is left exactly as-is — flagging it because it is load-bearing and easy to "tidy" into a breakage.Verification
amd64+arm64User: 65532,Entrypoint: /app/event_processors,WorkingDir: /app--package expression-goclean on rust 1.98 — what Wolfi'srustprovide resolves to, vs the1.85pinned before, which was the main toolchain riskgo mod download && go mod verify→all modules verified