The YAML configuration file defines git targets and the methods to use, how frequently to check the repository, and various configuration values that relate to that method.
A target is a unique value that holds methods. Mutiple git targets (targetConfigs) can be defined. Methods that can be configured include Raw, Systemd, Quadlet, Kube, Ansible, FileTransfer, Prune, and ConfigReload.
Examples of all methods are located in the FetchIt repository
A trailing / in targetPath is optional. For example, both configurations
below select the same Git directory and use the same method ownership identity:
targetPath: examples/filetransfertargetPath: examples/filetransfer/FetchIt removes trailing slashes before selecting Git changes and computing method identities. Multiple trailing slashes are also accepted. Existing configurations without a trailing slash continue to work. This does not change absolute-path validation or normalize interior path components.
targetPath selects a path inside the Git repository. It is distinct from
destinationDirectory and Quadlet's hostHome, hostConfigHome, and
hostRuntimeDir, which refer to the host filesystem. The trailing-slash
normalization applies to targetPath; tracked host destinations must still
be canonical absolute paths without symlink components.
FileTransfer preserves directories below targetPath. Adding a trailing slash
does not change the destination layout. Use glob to select a single file.
For a complete Git-hosted root that configures several methods and updates itself, see :doc:`root_configuration`.
There are a few ways currently to trigger FetchIt to reload its targets without requiring a restart. The first is to pass the environment variable $FETCHIT_CONFIG_URL to the podman run command running the FetchIt image. The second is to include a ConfigReload. If neither of these exist, a restart of the FetchIt pod is required to reload targetConfigs. The following fields are required with the ConfigReload method:
configReload:
schedule: "*/5 * * * *"
configURL: https://raw.githubusercontent.com/containers/fetchit/main/examples/config-reload.yamlChanges pushed to the ConfigURL will trigger a reloading of FetchIt target configs. It's recommended to include the ConfigReload in the FetchIt config to enable updates to target configs without requiring a restart.
The configuration above will pull in the file from the repository and reload the FetchIt config. The YAML above demonstrates the minimal required objects to start FetchIt. Once FetchIt is running, the full configuration file that is stored in git will be used.
For opt-in cleanup when a method leaves configuration, and recovery after a failed Git apply, see :doc:`lifecycle`.
Keep credentials out of public repositories. Scheduled remote configuration
updates use the top-level gitAuth credentials, which also apply to Git targets:
gitAuth:
envSecret: GH_PAT
configReload:
schedule: "*/5 * * * *"
configURL: https://raw.githubusercontent.com/example/private/main/config.yamlProvide GH_PAT to the engine as an environment secret using the launch example
below. Alternatively, top-level gitAuth.pat or gitAuth.username and
gitAuth.password supply credentials; protect the local configuration file.
Do not put credentials only inside configReload. Bootstrap with a local
config containing the authentication settings: the initial URL download before
configuration is loaded does not have those credentials available.
Set FETCHIT_CONFIG_URL to supply a remote configuration URL. An existing local
/opt/mount/config.yaml takes priority on initial startup. Use configReload
for scheduled updates, and mount a writable configuration directory for atomic
replacement. See :doc:`running` for validation, backups, and failure behavior.
The current engine does not load YAML directly from FETCHIT_CONFIG; use the
configuration file or URL instead.
Methods manage containers, host services, and files. The examples below show the
configuration keys used inside targetConfigs. For the features documented
here, build engine and helper images from commit 4e7964a or a descendant,
until a release containing them is published. See :doc:`documentation` for
revision-pinned builds and :doc:`release_notes` for unreleased changes.
| Configuration key | Use it for | Removal behavior |
|---|---|---|
raw |
Podman container definitions in JSON/YAML | Optional owned-container cleanup |
kube |
Podman kube play manifests, optionally encrypted with SOPS | Optional owned-Pod cleanup |
quadlet |
Complete host-managed Podman/systemd bundles | Optional cleanup using the host bundle journal |
systemd |
Authored host .service files |
Optional tracked-service cleanup |
filetransfer |
Copy files and nested directories into an existing host directory | Optional tracked-file cleanup |
ansible |
Host configuration through playbooks | No automatic undo of playbook changes |
cleanupOnRemoval defaults to false. Deleting a method entry or its entire
Git target from configuration retains its resources unless cleanup was enabled
before that change. The method sections
and :doc:`lifecycle` explain ownership, migration, and recovery requirements.
Trailing slashes in targetPath are optional; the Git target paths section
above explains normalization and FileTransfer's flat destination layout.
See :doc:`samples` for runnable applications, amd64/arm64 images, ports, and archive-loading instructions.
All methods are defined within specific targetConfiguration sections. These sections are demonstrated below. For private repositories, a PAT token or a username/password combination is required.
An example of using a PAT token is shown below.
gitAuth:
pat: CHANGEME
targetConfigs:
- url: https://github.com/containers/fetchit
branch: main
raw:
- name: raw-ex
targetPath: examples/raw
schedule: "*/5 * * * *"
pullImage: trueA SSH key can also be used for the cloning of a repository. An example of using an SSH key is shown below.
NOTE: The key must be defined within your git provider to be able to be used for pulling.
mkdir -p ~/.fetchit/.ssh
cp -rp ~/.ssh/id_rsa ~/.fetchit/.ssh/id_rsa
chmod 0700 ~/.fetchit/.ssh
chmod 0600 ~/.fetchit/.ssh/id_rsa
ssh-keyscan -t ed25519 github.com > /tmp/github.keys
ssh-keygen -lf /tmp/github.keys -E sha256Compare the printed SHA256 fingerprint with GitHub's published SSH fingerprints through a trusted channel. Only after they match, install the verified key:
install -m 0600 /tmp/github.keys ~/.fetchit/.ssh/known_hostsMount the directory at /opt/mount/.ssh (normally
as part of the ~/.fetchit:/opt/mount directory mount). An unknown or changed
host key fails authentication; do not disable host key checking. For a nonstandard
port, use ssh://git@host:2222/path/repo.git and a matching [host]:2222
known-hosts entry. Set sshKeyFile to the private key filename, including an
Ed25519 key if desired. The SSH key is used for both clone and later fetches.
The configuration file to use the key is shown below.
gitAuth:
ssh: true
sshKeyFile: id_rsa
targetConfigs:
- url: git@github.com:containers/fetchit
raw:
- name: raw-ex
targetPath: examples/raw
schedule: "*/5 * * * *"
pullImage: trueAn example of using username/password is shown below.
gitAuth:
username: bob
password: bobpassword
targetConfigs:
- url: https://github.com/containers/fetchit
branch: main
raw:
- name: raw-ex
targetPath: examples/raw
schedule: "*/5 * * * *"
pullImage: truePodman secrets can also be used but FetchIt must be started with the secret defined as an environment variable. This variable is defined as --secret GH_PAT,type=env in the podman run command.
export GH_PAT_TOKEN=CHANGEME
podman secret create --env GH_PAT GH_PAT_TOKEN
podman run -d --name fetchit \
-v fetchit-volume:/opt \
-v "$HOME/.fetchit:/opt/mount" \
-v "/run/user/$(id -u)/podman/podman.sock:/run/podman/podman.sock" \
--secret GH_PAT,type=env --security-opt label=disable \
quay.io/fetchit/fetchit:latestSet gitAuth.envSecret: GH_PAT in the configuration so the engine reads this
secret. Create it in the same rootful/rootless Podman store used to launch FetchIt.
The AnsibleTarget method allows for an Ansible playbook to be run on the host. A container is created containing the Ansible playbook, and the container will run the playbook. This playbook can be used to install software, configure the host, or perform other tasks. In the examples directory, there is an Ansible playbook that is used to install zsh.
targetConfigs:
- url: https://github.com/containers/fetchit
branch: main
ansible:
- name: ans-ex
targetPath: examples/ansible
sshDirectory: /root/.ssh
schedule: "*/5 * * * *"The field sshDirectory is unique for this method. This directory should contain the private key used to connect to the host and the public key should be copied into the .ssh/authorized_keys file to allow for connectivity. The .ssh directory should be owned by root.
Write idempotent playbooks so retrying a revision is safe. Removing the method does not reverse its changes, and apply rollback is unsupported for Ansible. Recover through a reviewed compensating playbook or restore the host manually; reverting Git alone does not undo packages, users, or external state.
The RawTarget method will launch containers based upon their definition in a JSON file. This method is the equivalent of using the podman run command on the host. Multiple JSON files can be defined within a directory.
targetConfigs:
- url: https://github.com/containers/fetchit
branch: main
raw:
- name: raw-ex
targetPath: examples/raw
schedule: "*/5 * * * *"
pullImage: trueThe pullImage field is useful if a container image uses the latest tag. This will ensure that the method will attempt to pull the container image every time.
A Raw JSON file can contain the following fields.
{
"Image":"quay.io/fetchit/fetchit-sample-app:latest",
"Name": "colors1",
"Env": {"APP_COLOR": "pink", "tree": "trunk"},
"Mounts": "",
"Volumes": "",
"Ports": [{
"host_ip": "",
"container_port": 8080,
"host_port": 8080,
"range": 0,
"protocol": ""}]
}Volume and host mounts can be provided in the JSON file. Named mounts can opt
into missing-volume creation with create: true. See :doc:`volumes` for raw
and kube examples, creation flags, mount paths, and persistence behavior.
The sample HTTP image supports amd64 and arm64 and runs as user 1001 and listens on container port 8080 without capability overrides.
APP_COLOR and tree illustrate environment propagation; Apache does not
change its welcome-page color based on these values. See :doc:`samples`.
If this method is present in the config file, podman-auto-update.service & podman-auto-update.timer will be enabled on the host. Podman auto-update will look for image updates with all podman-generated unit files that include the auto-update label, according to the timer schedule. Can configure for root, non-root, or both.
podmanAutoUpdate:
root: true
user: trueSystemdTarget is a method that will place, enable, and restart systemd unit files.
targetConfigs:
- url: https://github.com/containers/fetchit
branch: main
systemd:
- name: sysd-ex
targetPath: examples/systemd
root: true
enable: true
schedule: "*/5 * * * *"Systemd also accepts cleanupOnRemoval: true to track deployed service files
and stop, disable, and remove its owned services when the method is removed.
The default is false. Rootless tracked deployments require the host user's
HOME and XDG_RUNTIME_DIR in FetchIt's environment. See :doc:`lifecycle`
for prerequisites, existing-file migration, and recovery.
The File Transfer method will copy files from the container to the host. This method is useful for transferring files from the container to the host to be used by the container either at start up or during runtime.
targetConfigs:
- url: https://github.com/containers/fetchit
filetransfer:
- name: ft-ex
targetPath: examples/filetransfer
destinationDirectory: /tmp/ft
schedule: "*/5 * * * *"
branch: mainThe destinationDirectory field is the directory on the host where files and
nested directories below targetPath will be copied. Source directory
structure is preserved, while glob can still select a single file. Set
cleanupOnRemoval: true to track individual copied files and remove them when
the method leaves configuration. The default is false. Tracked deployments
require an existing, absolute destination directory, create missing parent
directories for tracked files, and refuse to overwrite untracked files. See
:doc:`lifecycle` for setup and recovery.
During Git reconciliation, deletion removes the old destination filename, and
rename removes the old filename before installing the new one. Filenames with
spaces are passed as command arguments. These file-level changes are separate
from removing an entire method from configuration: that requires prior opt-in
with cleanupOnRemoval. With tracking enabled, local edits or file replacements
block destructive operations until the ownership conflict is resolved.
The KubeTarget method will launch a container based upon a Kubernetes pod manifest. This is useful for launching containers to run the same way as they would in a Kubernetes environment.
To attach the played Pods to existing Podman networks, configure networks
on the Kube method, alongside targetPath and schedule. This is FetchIt
configuration, not a field to add to the Kubernetes Pod manifest. See
:ref:`method-podman-networks` for configuration, host scope, and verification.
The same network setting applies to ordinary and SOPS-encrypted Kube methods.
targetConfigs:
- url: https://github.com/containers/fetchit
kube:
- name: kube-ex
targetPath: examples/kube
schedule: "*/5 * * * *"
branch: mainFetchIt automatically adds the following labels to newly created or recreated Pods and to the Pod templates of Deployments, DaemonSets, and Jobs. Podman 5 propagates these labels to the resulting Pods and workload containers, including init containers:
fetchit.containers.io/managed-by=fetchitfetchit.containers.io/owner=<32-character hexadecimal identity>
The owner identity is the first 16 bytes of a SHA-256 digest of the JSON array containing the configured repository URL, branch, method name, and target path, in that order. It is stable across FetchIt restarts and commit changes. Changing one of those configuration fields changes the identity. The label contains no literal repository URL or credentials; it is an identifier, not a security token.
Existing application labels and controller selectors are preserved. FetchIt replaces values for its two reserved label keys. Labels are added in memory, including after authenticated SOPS decryption; repository manifests are unchanged. Secrets, ConfigMaps, and volumes do not receive these labels. For named PVC creation and mounting, including opt-in generated declarations, see :doc:`volumes`.
Use labels to find workloads managed by FetchIt:
podman pod ps --filter label=fetchit.containers.io/managed-by=fetchit
podman ps -a --filter label=fetchit.containers.io/managed-by=fetchit
# Replace POD with a Pod name shown by the first command.
owner_id=$(podman pod inspect POD --format '{{ index .Labels "fetchit.containers.io/owner" }}')
podman ps -a --filter "label=fetchit.containers.io/owner=$owner_id"This is an Unreleased feature; older images do not add these labels. Existing workloads acquire labels on their next successful recreation by FetchIt. Kube startup reconciliation may replay the saved applied revision and recreate workloads; labels are added during that recreation.
Ordinary Git reconciliation retains its existing name-based replacement/deletion behavior, including for unlabeled workloads. Opt-in removal of a configuration method uses ownership labels; see :doc:`lifecycle` for that separate policy. Use unique resource names and avoid sharing workload names between methods or with manually created workloads. Labels are editable metadata and are not a security boundary against other users of the Podman socket.
An example Kube play YAML file will look similiar to the following. This will launch a container as well as the coresponding ConfigMap.
apiVersion: v1
kind: ConfigMap
metadata:
name: env
data:
APP_COLOR: red
tree: trunk
---
apiVersion: v1
kind: Pod
metadata:
name: colors_pod
spec:
containers:
- name: colors-kubeplay
image: quay.io/fetchit/fetchit-sample-app:latest
ports:
- containerPort: 8080
hostPort: 7080
envFrom:
- configMapRef:
name: env
optional: falseThe quadlet method deploys a complete Git bundle into the host's Quadlet
search path, where the host Podman generator creates systemd services. Use Podman
5.7 or newer within major version 5, cgroup v2, and a running systemd manager.
Prefer rootless operation when workloads do not require root-owned host resources:
targetConfigs:
- name: quadlet-example
url: https://github.com/containers/fetchit.git
branch: main
quadlet:
- name: web
targetPath: examples/quadlet/units/
schedule: "*/1 * * * *"
root: false
hostHome: /home/operator
hostConfigHome: /home/operator/.config
hostRuntimeDir: /run/user/1234
start: true
restart: true
cleanupOnRemoval: trueReplace the host paths with the actual socket user's paths. For this rootless
example, change the bundled container's [Install] target to
WantedBy=default.target in your repository. It writes a message to a named
volume and does not publish an HTTP port. Select the complete units directory.
start defaults to false; set it to true to start services after deployment.
restart defaults to false; setting it to true implies start and restarts
workload services when the bundle changes. Cleanup defaults to false and must
be enabled before removing the method entry or its entire Git target.
See :doc:`quadlet` for rootful setup, validated host paths, bundle limits, image pinning, activation, and precise resource-retention rules. See :doc:`lifecycle` for removal receipts, retries, and rollback. Rootful helpers have host-wide administrative access; rootless helpers still administer the user's resources. Use trusted repositories and reviewed helper images in either scope.
Raw and Kube methods accept networks, a list of existing Podman network names
or IDs. Omit it or use [] to retain Podman's existing defaults. FetchIt does
not create or delete these networks; create them on the same rootful or rootless
Podman instance that FetchIt uses before deploying:
podman network create frontend
podman network create backendtargetConfigs:
- url: https://github.com/example/workloads
branch: main
raw:
- name: web
targetPath: raw
networks: [frontend, backend]
schedule: '*/1 * * * *'
kube:
- name: pods
targetPath: kube
networks: [backend]
schedule: '*/1 * * * *'The Raw list applies to all containers from that method. A Raw JSON/YAML file can
override it with Networks: [frontend]; an explicit Networks: [] opts that
container back into defaults. Kube passes the method's list to Podman kube play
for all pods in its manifest. These are Podman networks, not Kubernetes Services
or NetworkPolicies. Network creation, IPs, aliases, and routing remain managed by
Podman. A named network list replaces implicit default-network attachment;
include the default network explicitly if needed. Configured networks are inspected before workload teardown. Missing networks
fail before removing existing containers or pods. A network disappearing after
this check, or another Podman runtime failure, can still interrupt redeployment. Network options are not applied
to file-transfer or other helper containers.
Rootful and rootless networks are separate. If FetchIt uses the rootful socket,
create and inspect networks with sudo podman. If it uses a user's socket,
run these commands as that same host user. A network created in your personal
rootless store is unavailable to a rootful FetchIt deployment.
After deployment, inspect the selected network and the played Pods:
podman network inspect backend
podman pod ps
podman ps --filter label=fetchit.containers.io/managed-by=fetchitUse sudo for the rootful case. Check the network inspection output for the
expected attached workloads. Network attachment does not automatically publish
ports: use the manifest's hostPort where host access is required, as in the
Kube sample. Podman handles the runtime network; FetchIt does not implement
Kubernetes cluster networking or NetworkPolicy enforcement.
Quadlet networking is configured in the authored units, such as
Network=web.network with a bundled web.network definition. The Raw/Kube
networks option does not configure Quadlet or legacy Systemd units.
Changing a network setting in FetchIt's config alone does not redeploy an unchanged Git manifest. Commit a change to the workload file to apply the new attachments; existing workloads keep their current attachments until recreated.
Image URLs and disconnected ZIP archive URLs fetched over HTTP must return HTTP 200 after redirects. Other status codes fail the attempt before the response is written to a local image or archive file. Image error responses are never imported into Podman. The error includes the HTTP status code; check the source URL, access permissions, and server availability before the next scheduled attempt. Image failures are logged at error level. Failed archive refreshes stop reconciliation for that attempt rather than applying cached repository content.
Incomplete transfers and invalid ZIP archives return errors. Temporary download
files are removed on failure, allowing retries. Existing local files are retained
on HTTP status failures. ZIP paths escaping the extraction directory and ZIP
symlinks are rejected. Legacy entries such as ../fetchit/file remain supported
when their normalized paths resolve inside the destination fetchit directory.
Archive extraction is not transactional: a filesystem or
entry-read error during extraction can leave some extracted files behind.
Kube methods can opt into authenticated SOPS decryption using a read-only age key file. All changed manifests are prepared before teardown. See :doc:`sops` for a complete encrypted Secret/Pod example, configuration, key rotation, deletion, limits, and recovery. Ordinary Kube methods retain their current behavior.
Raw, Kube, Quadlet, FileTransfer, and Systemd support cleanupOnRemoval.
Resources are retained when a method entry or its entire Git target leaves
configuration unless the flag was enabled beforehand. See :doc:`lifecycle` for
migration, ownership, retries, and retained resources.
Git targets may set rollback: true only when all their methods are Raw, Kube,
or Quadlet. A mixed target containing FileTransfer, Systemd, Ansible, or another
unsupported method is rejected, rather than partially rolled back. Rollback
defaults to false; trackBadCommits requires rollback. Configuration examples
and recovery limits are in :doc:`lifecycle`.
Preserve the FetchIt volume and host journals across upgrades: they store applied Git baselines, pending cleanup receipts, and file/service ownership needed to retry safely. Deleting them loses that recovery information; FetchIt does not reconstruct ownership by deleting unknown host resources.
Raw and Kube workloads carry ownership labels. Changing containers to
containers/ retains the same normalized identity. The workload-label section
above documents discovery commands and reserved keys.
Targets can configure ordered fallbackURLs while retaining url as their
primary identity. See :doc:`mirrors` for trusted mirror configuration, Git history
checks, and authentication. SSH setup is documented above; verify host keys
rather than disabling verification.
Set FETCHIT_STATUS_ADDR to expose optional /healthz and /status HTTP
endpoints. For a native process, use FETCHIT_STATUS_ADDR=127.0.0.1:8080.
For containers, publish the port only on host loopback as shown in :doc:`status`.
The endpoints have no authentication; remote exposure requires an authenticated
TLS proxy and firewall policy. FetchIt does not enforce those controls or reject
public binds itself. Neither endpoint is enabled by default.