Repository navigation
feat: allow overriding the deploy base image per runtime (FIPS / hardened bases) #5002
Description
Is your feature request related to a problem? Please describe.
We self-host Trigger.dev inside a FedRAMP boundary. FedRAMP (NIST SC-13) requires the task runtime to use a FIPS-validated cryptographic module. Stock Node statically links OpenSSL and can't run in FIPS mode, so this has to be a property of the base image (e.g. Chainguard node-fips).
The deploy image base can't be changed today:
- The base and build images are hard-pinned per runtime in
BASE_IMAGEandBUILD_IMAGE. - The base is read from that map at one point, and the runtime stage is always
FROM base AS final. - Build extensions can add to the base stage with
image.instructions/image.pkgs, but they can't replace it.
The only option today is to yarn patch the BASE_IMAGE constant in the CLI. That has to be redone on every CLI release.
Describe the solution you'd like to see
An opt-in override in trigger.config.ts, next to build.extensions:
export default defineConfig({
runtime: "node-26",
build: {
image: {
base: "cgr.dev/acme/node-fips:26@sha256:…", // runtime (final) stage
buildBase: "cgr.dev/acme/node-fips:26-dev@sha256:…", // optional; defaults to BUILD_IMAGE
},
},
});Also accept the same values from build-time env vars, e.g. TRIGGER_BUILD_BASE_IMAGE / TRIGGER_BUILD_BUILD_IMAGE (with the same precedence as the TRIGGER_BUILD_SKIP_APT_SNAPSHOT escape hatch proposed in #4558). Then a platform team can set the base once in CI for every project instead of in each project's config.
In generateContainerfile: baseImage: env.TRIGGER_BUILD_BASE_IMAGE ?? config.build.image?.base ?? BASE_IMAGE[runtime], and the same pattern for BUILD_IMAGE. Nothing changes when neither is set.
The override has to live on the CLI side. The Containerfile is generated and built during trigger deploy, and the supervisor only runs the digest it's given, so the webapp and Helm chart have nothing to hook into.
Document the contract the generated Containerfile already relies on, plus a "you own this image" caveat:
nodeonPATHat the runtime's major version.- The
DEFAULT_PACKAGES:busybox,ca-certificates,dumb-init(the entrypoint),git,openssl. - A
nodeuser, because the final stage runsUSER node. - glibc, for native modules built in the build stage.
image.pkgs, and the extensions that emitapt-get(aptGet,playwright, …), assume Debian. When a custom base is set, the CLI should either reject them with a clear error or leave package installation to the image owner.
Describe alternate solutions
yarn patchtheBASE_IMAGEconstant (what we do today). It works, but every CLI bump needs re-validation, and the digest bumps need their own automation.- Rebase or rewrite the image after push. Doesn't work: finalize records the digest before anything could change it.
- Swap the base with
image.instructions. Doesn't work: instructions run insideFROM baseand can't change whatbaseis. - Let users supply the whole Containerfile (raised as an alternative in feat: Allow injecting ca cert in project #1210). This is far more surface area than a base override, and it would break whenever the generated stages change.
Additional information
- Related: feat: Allow injecting ca cert in project #1210 (needed a CA-cert injection hook, worked around by patching CLI internals), feat(deployments): install deployed image base packages from a pinned Debian snapshot #4558 / feat: publish deploy base images to DockerHub #4581 / feat(cli): build deployment images on prebuilt base images #4602 / feat(base-images): immutable per-publish image tags #4607 (introduced the pinned prebuilt bases this would override), bug: Native build server fails with Docker Hub rate limit (429) when pulling base images #2911 (Docker Hub rate limits pulling base images).
- No existing issue covers this. We searched for base image, custom image, Containerfile, FIPS, hardened and Chainguard.
- Possible follow-up (not part of this request): an instance-level policy, set through webapp env / Helm values, that pins or allow-lists the base images deploys to that instance may use, enforced when the deploy is created. That would make "every task image on this instance is FIPS" provable from the server side, not only by CI convention.
- This applies to any regulated self-hoster (FedRAMP, DoD IL, HIPAA/PCI hardening, internal golden images), not just FIPS.
- Happy to contribute the PR. It looks like one config field plus a two-line fallback in
buildImage.ts, plus docs.
Activity
brentshulman-silkline commentedon Oct 5, 2026
Draft implementation in #5003:
build.image.base/buildBaseconfig,TRIGGER_BUILD_BASE_IMAGE/TRIGGER_BUILD_BUILD_IMAGEenv overrides, tests and docs. The PR description lists two open design questions.brentshulman-silkline commentedon Oct 5, 2026
Alternative approach in #5004 / #5005: an instance-level
DEPLOY_BASE_IMAGESwebapp setting in place of per-project config, so Cloud users never see it. Happy to go with whichever shape you prefer and close the other.