Skip to main content

Bundler CLI

bundler.sh ships in the install kit. It builds an offline bundle on a connected host and loads it into your registry on a host that has no internet access.

Its only input is the release-manifest.yaml inside the kit. No access to our source is needed, so you can build your own bundle from any published release.

For the procedure rather than the reference, see Prepare the artifacts.

Which commands need internet access

This is the table an isolated site actually needs. The pipeline is split on internet access, not on environment.

CommandInternetTalks to
validateRequiredParses the manifest, resolves tooling, then fetches one image manifest to confirm registry access
assembleRequiredSource registry: images and charts
assemble-chartsRequiredSource registry: charts only
assemble-imagesRequiredSource registry: images only
verify-assemblyRequiredSource registry for signature artifacts, plus Sigstore trust material
create-packageRequiredInherits assemble and verify-assembly
packageNoneLocal tar
verify-packageNoneLocal extract and checksum comparison
mirrorNoneDestination registry, over your local network
retargetNoneLocal files
applyNoneDestination registry. This is mirror plus retarget
cleanup, version, helpNoneLocal

Split the pipeline at the tarball, not earlier. create-package cannot run on an isolated host: it fails in preflight with no route to the source registry.

Commands

CommandWhat it does
validatePreflight. The manifest exists and its schema is sane, every image and chart is digest-pinned, the tooling resolves, and the source registry is readable. Fetches one image manifest, so a bad host, missing login, TLS mismatch or unpublished digest fails here rather than partway through a multi-gigabyte download
assembleCreates the bundle directory, pulls every image and chart, extracts each chart's production values file, copies in the manifest and itself. Fails if the directory exists
assemble-chartsThe charts half. What the registry install method uses, since the cluster pulls its own images
assemble-imagesThe images half. Separable so a failed multi-hour pull can be retried without re-fetching charts
verify-assemblyKeyless signature verification of every pinned image and chart, then writes SHA256SUMS and prints the bundle fingerprint. Reports every failure and refuses to continue on any
packageTars the bundle directory into a tarball beside it, never inside
verify-packageUnpacks to a temporary directory and re-checks SHA256SUMS
create-packageassemble, verify-assembly, package, verify-package, in order
mirrorVerifies the bundle against SHA256SUMS, then pushes every image to your registry
retargetRewrites the registry host in the bundle's own values files, in place, and updates the affected SHA256SUMS entries so the bundle stays self-consistent
applymirror then retarget. The usual customer step
cleanupRemoves every directory and archive the bundler created
versionThe bundler's version, stamped at release
helpUsage

Every command runs validate first, so any of them is safe to invoke on its own.

Options

OptionEffect
--arch amd64 or --arch arm64Single-architecture bundle, roughly half the size. Loses SBOM attestations. See below
-o <file>A different tarball name
-r <registry>Destination registry for mirror, retarget and apply
--dangerously-skip-cosign-verifyDrops signature verification and its tooling requirement. The bundle is annotated as unverified

The --arch trade-off

A single-architecture bundle extracts one manifest out of each multi-architecture index, which changes every image digest by definition.

DefaultWith --arch
Image signaturesVerifyVerify. Each per-architecture manifest is signed individually
SBOM attestationsVerifyLost. They hang off the index, which is what is left behind
Digests match the manifestYesNo
Tarball and directory namemultiarchNamed after the architecture, so substitute it everywhere

If your acceptance process checks attestations, or your nodes are mixed, or you are not certain what they run: take the default. A missing architecture fails when the kubelet tries to pull, on an isolated cluster, after the transfer.

Environment variables

VariablePurpose
MIKEFARAH_YQ_PATHPath to the Go yq, when the one on PATH is the Python one
BUNDLE_TLS_VERIFY=falseDisables TLS verification on the pull side
MIRROR_TLS_VERIFY=falseDisables TLS verification on the push side, for a plain-HTTP registry

The two TLS variables are the only places in the whole install where verification can be disabled. Prefer a certificate from your internal CA. See Hardening.

Credentials, and the three stores

Three tools, three credential stores. You log in to two of them.

ToolStoreLogin needed
skopeoThe containers storeYes, both source and destination
helmHELM_REGISTRY_CONFIGYes, source only
cosignThe Docker configNo. The bundler lends it the one skopeo holds

If you see the bundler say it is reusing skopeo's credential for cosign, that is the expected path and not a warning.

Behavior worth knowing

assemble refuses to write into an existing directorySo a stale bundle cannot be silently mixed with a new one
retarget takes no file argumentsRewriting arbitrary paths handed in on a command line is not something an isolated install should be able to ask for
retarget verifies integrity before editing, never afterThat order is what stops a checksum update from re-blessing a bundle that arrived altered
retarget is idempotentRunning apply twice is safe
mirror runs before retarget inside applySo a registry failure leaves your values files untouched
Mirroring is additiveNew tags land beside old ones, so a running install keeps working and a rollback still has its images
An egress proxy is fine for the bundlerProvided the host can reach the registry and Sigstore. Unlike the relay, these are ordinary CLI tools that honour proxy variables

Bundle contents

gen0sec-cerebellum-<arch>-<version>/
├── oci/ every image, as an OCI layout
├── charts/ installable chart archives
├── values/ each chart's production values, retargeted by `apply`
├── release-manifest.yaml the digests this bundle was built from
├── bundler.sh a copy
└── SHA256SUMS over every file above

assemble extracts each chart's values file as values/<chart>-values-onprem.yaml. There is no bare values-onprem.yaml in the bundle root, which is why the install commands name the file in full.

The bundle does not carry the install kit's scripts/ or examples/. Those cross the air gap inside the kit directory. See Install kit contents.