Components
The actual capabilities that Zarf Packages provide are defined within named components.
These components define what dependencies they have along with a declarative definition of how they should be deployed.
Each package can have as many components as the package creator wants but a package isn’t anything without at least one component.
Common Component Fields
There are certain fields that will be common across all component definitions. These fields are:
| Field | Type | Description |
|---|---|---|
name* | string | The name of the component. |
description | string | Message to include during package deploy describing the purpose of this component. |
optional | boolean | Do not install this component unless explicitly requested. Defaults to false, meaning the component is required. |
selector | object | Filter when this component is included during package creation based on architecture or flavor. |
service | object | The Zarf CLI service this component provides, such as the registry, injector, or agent. |
stateAccess | array | Groups of sensitive .State fields this component may access in Go templates (manifests, files, actions with template: true). Valid values: "registryCredentials", "gitCredentials", "agentCerts". |
target | object | Filter when this component is deployed based on OS. |
Actions
| Field | Type | Description |
|---|---|---|
actions | object | Custom commands to run at various stages of a package lifecycle. |
Component actions are explored in the component actions documentation.
Files
| Field | Type | Description |
|---|---|---|
files | array | Files or folders to place on disk during package deployment. |
Files can be:
- Relative paths to either a file or directory (from the
zarf.yamlfile) - A remote URL (http/https)
- Verified using the
checksumfield for data integrity (optional)
- name: on-deploy-with-template-use-of-value optional: true files: # this file will be copied to the target location and the cat, dog, and snake sounds will be replaced with their values # requires the on-deploy-with-dynamic-value and on-deploy-with-multiple-values components - source: test.txt destination: test-templated.txt checksum: sha256:d84fa3f5071b5cee0ffb09989c95b0078f4265ed485b314492a19bab2e3f69f3 enableTemplating: true- name: k3s files: - source: https://github.com/k3s-io/k3s/releases/download/v1.34.3+k3s1/k3s checksum: sha256:f95350e3997165974d1d1406f01aabaf869aed7ca790cc2d83a92a82f26a06c5 destination: /usr/sbin/k3s executable: trueHelm Charts
| Field | Type | Description |
|---|---|---|
charts | array | Helm charts to install during package deploy. |
Charts using the local.path key can be:
- Relative paths to either a file or directory (from the
zarf.yamlfile)
Remote charts can be:
- A Git repository using
git.url, withgit.refselecting the revision andgit.pathselecting the chart directory - An OCI registry using
oci.url(oci://), withoci.refselecting a tag or digest - A Helm repository using
helmRepository.url(http/https), withhelmRepository.nameandhelmRepository.versionselecting the chart
- name: demo-helm-charts charts: # Charts are organized in a list with unique chart names per component - note that a Zarf chart name does not need to match the chart name in a Chart.yaml - name: podinfo-local # `local.path` loads the chart from the local filesystem. local: path: chart namespace: podinfo-from-local-chart valuesFiles: - path: values.yaml # serverSideApply is a new option in Helm 4 # Can be set to true, false, and "auto". Defaults to "auto" which uses SSA on new installs, and automatically selects the previously apply method on upgrade serverSideApply: "true" # Values are used to override the default values in the chart. # This can be overridden by the user at deployment time with the `--set-values` flag. values: - sourcePath: ".podinfo.replicaCount" targetPath: ".replicaCount"
- name: podinfo-oci # `oci.url` and `oci.ref` select a chart from an OCI registry. oci: url: oci://ghcr.io/stefanprodan/charts/podinfo ref: tag: 6.4.0 namespace: podinfo-from-oci valuesFiles: - path: values.yaml
- name: podinfo-git # `git.ref` selects the revision and `git.path` selects the chart directory. git: url: https://github.com/stefanprodan/podinfo.git ref: tag: 6.4.0 path: charts/podinfo namespace: podinfo-from-git valuesFiles: - path: values.yaml
- name: podinfo-repo # `helmRepository.name` selects the upstream chart independently of the Zarf chart name. helmRepository: url: https://stefanprodan.github.io/podinfo version: 6.4.0 name: podinfo namespace: podinfo-from-repo # By default the release name will be the chart name, but you can override this with the `releaseName` key releaseName: cool-release-name valuesFiles: - path: values.yaml images: - name: ghcr.io/stefanprodan/podinfo:6.4.0 # This is the cosign signature for the podinfo image for image signature verification - name: ghcr.io/stefanprodan/podinfo:sha256-57a654ace69ec02ba8973093b6a786faa15640575fbf0dbb603db55aca2ccec8.sig
attachments: readme: readme.mdKubernetes Manifests
| Field | Type | Description |
|---|---|---|
manifests | array | Kubernetes manifests to be included in a generated Helm chart on package deploy. |
Manifests under the files key can be:
- Relative paths to a Kubernetes manifest file (from the
zarf.yamlfile) - Verified using the
url@shasumsyntax for data integrity (optional and only for remote URLs)
Manifests under the kustomize.files key can be:
- Any valid Kustomize reference both local and remote (ie. anything you could do a
kustomize buildon)
- name: httpd-local manifests: - name: simple-httpd-deployment namespace: httpd files: # local manifests are specified relative to the `zarf.yaml` that uses them: - httpd-deployment.yaml # image discovery is supported in all manifests and charts using: # zarf prepare find-images images: - name: httpd:alpine3.18 - name: nginx-remote manifests: - name: simple-nginx-deployment namespace: nginx files: # remote manifests are specified with a URL and you can verify integrity of a manifest # by adding a sha256sum to the end of the URL, separated by an @: - https://k8s.io/examples/application/deployment.yaml@c57f73449b26eae02ca2a549c388807d49ef6d3f2dc040a9bbb1290128d97157 # this sha256 can be discovered using: # zarf prepare sha256sum https://k8s.io/examples/application/deployment.yaml # image discovery is supported in all manifests and charts using: # zarf prepare find-images images: - name: nginx:1.14.2 - name: podinfo-kustomize manifests: - name: simple-podinfo-deployment namespace: podinfo kustomize: files: # kustomizations can be specified relative to the `zarf.yaml` or as remoteBuild resources with the # following syntax: https://github.com/kubernetes-sigs/kustomize/blob/master/examples/remoteBuild.md: - https://github.com/stefanprodan/podinfo/kustomize?ref=6.4.0 # while ?ref= is not a requirement, it is recommended to use a specific commit hash / git tag to # ensure that the kustomization is not changed in a way that breaks your deployment. # image discovery is supported in all manifests and charts using: # zarf prepare find-images images: - name: ghcr.io/stefanprodan/podinfo:6.4.0
attachments: readme: readme.mdContainer Images
| Field | Type | Description |
|---|---|---|
images | array | List of OCI images to include in the package. |
Images can either be discovered manually, or automatically by using zarf dev find-images. The image list is not limited to containers, any OCI image following the Image Manifest specification can be pulled
- name: flux description: Installs the flux CRDs / controllers to use flux-based deployments in the cluster manifests: - name: flux-install namespace: flux-system files: - https://github.com/fluxcd/flux2/releases/download/v2.4.0/install.yaml images: - name: ghcr.io/fluxcd/helm-controller:v1.1.0 - name: ghcr.io/fluxcd/image-automation-controller:v0.39.0 - name: ghcr.io/fluxcd/image-reflector-controller:v0.33.0 - name: ghcr.io/fluxcd/kustomize-controller:v1.4.0 - name: ghcr.io/fluxcd/notification-controller:v1.4.0 - name: ghcr.io/fluxcd/source-controller:v1.4.1Container Image Archives
| Field | Type | Description |
|---|---|---|
imageArchives | array | List of tar archives of images to include in the package. |
Another way to bring OCI images into the package is via archives of OCI layouts. Common ways to create OCI archives are through the docker save and podman save —format=oci-archive commands. The Docker engine version must be >= 25.0.0 as this was the release that the save command became compliant with the OCI layout specification.
An OCI layout can have any number of images, Zarf will pull all images that are listed in the sub-field imageArchives.images. If a listed image is not found in the archive then Zarf will error. In order for Zarf to find an image its descriptor in the OCI-layout index.json must include the annotation “io.containerd.image.name” or “org.opencontainers.image.ref.name”. docker save and podman save will automatically add at least one of these annotations.
Locally-built images that are not pulled from a public registry should be referenced under the reserved .internal top-level domain (for example zarf.internal/my-app:1.0.0). The .internal TLD will never resolve on the public internet, which avoids accidentally pulling an unexpected image if a registry reference is mistyped or rewriting fails. zarf dev lint emits a warning when an image archive image does not use a .internal domain.
- name: image-archive description: "pull in an image from a tar archive" imageArchives: - path: image.tar images: - name: ghcr.io/fluxcd/helm-controller:v1.1.0 - name: ghcr.io/fluxcd/image-automation-controller:v0.39.0Git Repositories
| Field | Type | Description |
|---|---|---|
repositories | array | List of git repositories to include in the package. |
The podinfo-flux example showcases a simple GitOps workflow using Flux and Zarf.
- name: full-repo optional: true repositories: # The following performs a full Git Repo Mirror with `go-git` (internal to Zarf) - url: https://github.com/zarf-dev/zarf-public-test.git # The following performs a full Git Repo Mirror forcing a fallback to host `git` - url: https://dev.azure.com/defenseunicorns/zarf-public-test/_git/zarf-public-test - name: specific-tag optional: true repositories: # The following performs a tag Git Repo Mirror with `go-git` (internal to Zarf) - url: https://github.com/zarf-dev/zarf-public-test.git ref: tag: v0.0.1 # The following performs a tag Git Repo Mirror forcing a fallback to host `git` - url: https://dev.azure.com/defenseunicorns/zarf-public-test/_git/zarf-public-test ref: tag: v0.0.1 - name: specific-branch optional: true repositories: # The following performs a branch Git Repo Mirror with `go-git` (internal to Zarf) - url: https://github.com/zarf-dev/zarf-public-test.git ref: branch: dragons # The following performs a branch Git Repo Mirror forcing a fallback to host `git` - url: https://dev.azure.com/defenseunicorns/zarf-public-test/_git/zarf-public-test ref: branch: dragons - name: specific-hash optional: true repositories: # The following performs a SHA Git Repo Mirror with `go-git` (internal to Zarf) - url: https://github.com/zarf-dev/zarf-public-test.git ref: commit: 01a23218923f24194133b5eb11268cf8d73ff1bb # The following performs a SHA Git Repo Mirror forcing a fallback to host `git` - url: https://dev.azure.com/defenseunicorns/zarf-public-test/_git/zarf-public-test ref: commit: 01a23218923f24194133b5eb11268cf8d73ff1bb
attachments: readme: readme.mdTag-Based Git Repository Clone
Tag-based git repository cloning is the recommended way of cloning a git repository for air-gapped deployments because it wraps meaning around a specific point in git history that can easily be traced back to the online world. Tag-based clones are defined using url for the repository address and ref.tag for the tag, for example url: https://github.com/zarf-dev/zarf.git with ref.tag: v0.15.0.
A tag-based clone only mirrors the tag defined in the Zarf definition. The tag will be applied on the git mirror to a zarf-specific branch name based on the tag name (e.g. the tag v0.1.0 will be pushed to the zarf-ref-v0.1.0 branch). This ensures that this tag will be pushed and received properly by the airgap git server.
- name: specific-tag optional: true repositories: # The following performs a tag Git Repo Mirror with `go-git` (internal to Zarf) - url: https://github.com/zarf-dev/zarf-public-test.git ref: tag: v0.0.1 # The following performs a tag Git Repo Mirror forcing a fallback to host `git` - url: https://dev.azure.com/defenseunicorns/zarf-public-test/_git/zarf-public-test ref: tag: v0.0.1SHA-Based Git Repository Clone
In addition to tags, Zarf also supports cloning and pushing a specific SHA hash from a git repository, but this is not recommended as it is less readable/understandable than tag cloning. Commit SHAs are defined using ref.commit, for example url: https://github.com/zarf-dev/zarf.git with ref.commit: c74e2e9626da0400e0a41e78319b3054c53a5d4e.
A SHA-based clone only mirrors the SHA hash defined in the Zarf definition. The SHA will be applied on the git mirror to a zarf-specific branch name based on the SHA hash (e.g. the SHA c74e2e9626da0400e0a41e78319b3054c53a5d4e will be pushed to the zarf-ref-c74e2e9626da0400e0a41e78319b3054c53a5d4e branch). This ensures that this commit will be pushed and received properly by the airgap git server.
- name: specific-hash optional: true repositories: # The following performs a SHA Git Repo Mirror with `go-git` (internal to Zarf) - url: https://github.com/zarf-dev/zarf-public-test.git ref: commit: 01a23218923f24194133b5eb11268cf8d73ff1bb # The following performs a SHA Git Repo Mirror forcing a fallback to host `git` - url: https://dev.azure.com/defenseunicorns/zarf-public-test/_git/zarf-public-test ref: commit: 01a23218923f24194133b5eb11268cf8d73ff1bb
attachments: readme: readme.mdBranch-Based Git Repository Clone
If you need to clone a specific branch, Zarf also supports providing ref.branch, for example url: https://repo1.dso.mil/big-bang/bigbang.git with ref.branch: release-1.54.x. The branch name used by Zarf on deploy will be the upstream branch name, whereas tags and commits use the zarf-ref-* branch name.
Git Repository Full Clone
Full clones use a repository url without a ref, for example url: https://github.com/stefanprodan/podinfo.git. Full clones will contain all branches and tags in the mirrored repository rather than any one specific tag.
- name: full-repo optional: true repositories: # The following performs a full Git Repo Mirror with `go-git` (internal to Zarf) - url: https://github.com/zarf-dev/zarf-public-test.git # The following performs a full Git Repo Mirror forcing a fallback to host `git` - url: https://dev.azure.com/defenseunicorns/zarf-public-test/_git/zarf-public-testComponent Imports
| Field | Type | Description |
|---|---|---|
import | object | Import a component from another Zarf component config. |
The v1beta1 import key supports two sources for reusable ZarfComponentConfig definitions:
local[].pathreferences a component definition file on the local filesystem.remote[].urlreferences a component published to an OCI registry withzarf component publish.
These fields are lists so you can provide alternative component variants. Zarf selects exactly one source whose variant.flavor and variant.architecture match the package creation target. If zero or multiple components match, package creation fails.
- name: local-import description: Serve a page supplied by this package using a local web-server component import: local: - path: components/web-server.yaml charts: - name: web-server namespace: imports-local values: - sourcePath: .webServers.local targetPath: . - name: remote-import description: Serve a different page using the same component imported from a registry import: remote: - url: oci://ghcr.io/zarf-dev/components/examples/compose/web-server:1.0.0 charts: - name: web-server namespace: imports-remote values: - sourcePath: .webServers.remote targetPath: .
attachments: readme: readme.mdMerge Strategies
When merging components together Zarf will adopt the following strategies depending on the kind of primitive (files, images, manifests) that it is merging:
| Kind | Key(s) | Description |
|---|---|---|
| Component Behavior | name, description, optional, selector | These keys control how Zarf interacts with a given component and will always take the value of the importing package component. They are not inherited from the imported component config’s metadata or variant |
| Component Settings | target.os, service | These keys take the value of the importing component if it is not empty, otherwise they keep the imported value |
| Un’name’d Primitive Arrays | files, imageArchives, repositories, stateAccess | These keys will append the importing component’s array to the end of the imported component’s array |
| Actions | actions | Each lifecycle action list is appended to the imported list. Action defaults are replaced when provided by the importing component |
| Images | images | Images match by a nonempty id first, then by name. Matching images take nonempty fields from the importing component; unmatched images are appended |
| ’name’d Primitive Arrays | charts, manifests | Elements match by name. Matching elements merge their arrays and take nonempty settings from the importing component; unmatched elements are appended. Boolean options are enabled when either component sets them to true |
An importing component can override a chart source’s version or reference, but cannot change its source type, URL, chart name, or path.
Some package level fields from imported components will also be merged with the importing package. These fields will be processed from the first component to the last component in a Zarf package definition.
| Kind | Field(s) | Description |
|---|---|---|
| Un’name’d Primitive Arrays | values.files | The importing package definition’s array will be appended to the end of the arrays from imported component configs. Duplicate paths are collapsed, with the first occurrence retained so the earliest position in the merge order is preserved. |
| Global Behavior | values.schema | Schemas are merged with the importing package’s schema taking precedence, followed by earlier component imports. Nested imports have lower precedence than the component importing them |
Deploying Components
When deploying a Zarf package, components are deployed in the order they are defined in the zarf.yaml.
The zarf.yaml configuration for each component also defines whether the component is optional using optional: true. Components are required by default and are always deployed without any additional user interaction, while optional components are printed out in an interactive prompt asking the user if they wish to deploy the component.
If you already know which components you want to deploy, you can do so without getting prompted by passing the components as a comma-separated list to the --components flag during the deploy command.
# deploy all required components, prompting for optional components$ zarf package deploy ./path/to/package.tar.zst
# deploy all required components, ignoring optional component prompts$ zarf package deploy ./path/to/package.tar.zst --confirm
# deploy all required components plus optional-component-1 and optional-component-2$ zarf package deploy ./path/to/package.tar.zst --components=optional-component-1,optional-component-2