Skip to content
Unified Defense StackUnified Defense Stack

bundle.uds.hcl

bundle.uds.hcl is the source definition for a UDS CLI Next bundle. It declares the bundle identity and the Zarf packages that become part of the bundle artifact or are deployed directly in development mode.

The file must be named exactly bundle.uds.hcl. It is distinct from defaults.uds.hcl, which supplies bundle-level default variables, and config.uds.hcl, which supplies consumer-owned deploy-time settings.

The top-level blocks identify the bundle and declare its packages.

Block or attributeTypeRequiredDescription
udsblockYesDeclares the bundle API version.
metadatablockYesDeclares the bundle name and optional descriptive metadata.
localsblockNoDefines reusable HCL expressions.
packageblockAt least oneDeclares a Zarf package included in the bundle. Every package block is included.

Minimal definition:

bundle.uds.hcl
uds {
bundle_api_version = "uds.dev/v1alpha1"
}
metadata {
name = "my-bundle"
}
package "app" {
source = "oci://registry.example.com/my-org/app:1.0.0"
signature_verification {
verify = false
}
}

verify = false is an explicit package signature bypass for local development. For a trusted create workflow, configure public_key or keyless.

The uds block has one supported attribute:

AttributeTypeRequiredValid value
bundle_api_versionstringYesExactly "uds.dev/v1alpha1"

The field is required even when the bundle is deployed directly from its definition. Other API versions are rejected as unsupported.

The metadata block identifies the bundle and provides its descriptive information.

AttributeTypeRequiredDescription
namestringYesBundle name. It identifies the bundle in command output and artifact metadata.
descriptionstringNoHuman-readable description. Defaults to an empty string.
versionstringNoBundle version. Defaults to an empty string and is used when naming versioned artifacts.

Bundle validation requires name to be non-empty. The parser requires the attribute to be present, and description and version must be strings when present. The current schema does not apply additional format validation to those two optional fields.

Use locals for values shared by metadata and package expressions. Local values are evaluated in dependency order, so one local can reference another with local.<name>:

locals {
registry = "ghcr.io/my-org"
version = "1.0.0"
app_source = "oci://${local.registry}/app:${local.version}"
}
metadata {
name = "my-app"
version = local.version
}
package "app" {
source = local.app_source
signature_verification { verify = false }
}

The built-in sys.arch value contains the effective target architecture. It can be used to select a local package archive:

package "app" {
source = "./packages/app-${sys.arch}.tar.zst"
signature_verification { verify = false }
}

Local names must be unique. References to an undefined local and cyclic local dependencies fail during parsing. The file(path) function is also available in a file-backed bundle definition. Relative paths are resolved from the directory containing bundle.uds.hcl; absolute paths are used as-is. The function returns regular UTF-8 file contents.

The package label is the package identifier used in dependency references and bundle output.

Attribute or blockTypeRequiredDefaultDescription
<id>labelYesNoneMust be unique. It cannot contain / or \\, and cannot be . or ...
sourcestringYesNoneOCI reference or local Zarf package source.
namespacestringNoEmptyNamespace override for the Zarf package.
depends_onlist of package referencesNoEmptyPackages that must deploy before this package.
values_fileslist of stringsNoEmptyPackage values files, resolved relative to the bundle definition directory.
optional_componentslist of stringsNoEmptyOptional Zarf components to include or exclude.
signature_verificationblockRequired for bundle createNonePackage signature policy applied when the package enters the bundle.

Sources can be OCI package references or local Zarf package paths:

package "remote" {
source = "oci://registry.example.com/my-org/remote:1.0.0"
signature_verification { verify = false }
}
package "local" {
source = "./packages/local-${sys.arch}.tar.zst"
signature_verification { verify = false }
}

Relative local paths are resolved from the directory containing bundle.uds.hcl. A local source must be a Zarf package directory or a .tar.zst package archive.

Dependencies use static package references, not quoted strings:

depends_on = [package.database, package.platform]

Each element must be exactly a package.<id> traversal. A dependency must refer to a package declared in the same bundle and cannot refer to its own package. Independent packages can be deployed in parallel, subject to the configured concurrency limit.

List package values files in the order they should be applied:

values_files = [
"values/base.yaml",
"values/staging.yaml",
]

Relative paths are resolved from the directory containing bundle.uds.hcl. Source-directory operations must be able to read the files. During bundle creation, the files are stored in the artifact under values/<package-id>/, and artifact deployments use those embedded copies. These are Zarf package values files. During deployment, Go templates can read deploy-time variables through .vars. Deploy-time variables and their precedence are configured in config.uds.hcl.

When the list is empty, the package’s required and default Zarf components are selected. Listing a component selects it alongside required components. Prefix a component with - to explicitly exclude it:

optional_components = [
"metrics",
"-debug-shell",
]

Component names must not be empty or repeated. Component selection is not a deploy-time bundle variable.

Each package passed to uds bundle create must declare its signature posture. Verification is enabled by default when verify is omitted. Configure exactly one verification method when enabled, or use verify = false without a method for an explicit bypass.

Attribute or blockTypeRequiredDescription
verifybooleanNoDefaults to true. Set to false to skip package signature verification. It cannot be combined with public_key or keyless.
public_keystringOne method when verifyingPublic key contents. Use file("keys/package-signer.pub") to load a key file.
keylessblockOne method when verifyingKeyless certificate and issuer constraints.

Keyless verification supports the following fields:

AttributeTypeRequiredDescription
certificate_identitystringOne identityExact certificate identity.
certificate_identity_regexpstringOne identityRegular expression for certificate identities.
certificate_oidc_issuerstringOne issuerExact OIDC issuer.
certificate_oidc_issuer_regexpstringOne issuerRegular expression for OIDC issuers.
trusted_rootstringNoSigstore trusted-root JSON contents. The embedded Sigstore root is used when omitted.
insecure_ignore_tlogbooleanNoDefaults to false. Disables transparency-log verification.
insecure_ignore_sctbooleanNoDefaults to false. Disables certificate SCT verification.
use_signed_timestampsbooleanNoDefaults to false. Enables signed-timestamp verification when applicable.

Use exactly one identity form and exactly one issuer form. Regular expressions must compile. The insecure options reduce verification protections and should be reserved for an intentional, documented trust decision.

Example keyless package policy:

package "app" {
source = "oci://registry.example.com/my-org/app:1.0.0"
signature_verification {
keyless {
certificate_identity_regexp = "https://github\\.com/my-org/.*/.github/workflows/release\\.yml@refs/heads/main"
certificate_oidc_issuer = "https://token.actions.githubusercontent.com"
}
}
}

Direct development deployment attempts package verification and warns instead of stopping when the policy would fail bundle create. Artifact deployment does not reverify contained package signatures. Bundle artifact signing and verification are separate controls.