Skip to content

feat: allow overriding the deploy base image per runtime (FIPS / hardened bases) #5002

Description

@brentshulman-silkline

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 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:

  1. node on PATH at the runtime's major version.
  2. The DEFAULT_PACKAGES: busybox, ca-certificates, dumb-init (the entrypoint), git, openssl.
  3. A node user, because the final stage runs USER node.
  4. glibc, for native modules built in the build stage.
  5. image.pkgs, and the extensions that emit apt-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 patch the BASE_IMAGE constant (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 inside FROM base and can't change what base is.
  • 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions