Skip to content

Latest commit

 

History

History
638 lines (501 loc) · 26.4 KB

methods.rst

File metadata and controls

638 lines (501 loc) · 26.4 KB

Configuration

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

Git target paths

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/filetransfer
targetPath: 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.

Dynamic Configuration Reload

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.yaml

Changes 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`.

Private configuration downloads

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.yaml

Provide 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.

Remote configuration and environment variables

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

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.

Method selection
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: true

A 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 sha256

Compare 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_hosts

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

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

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

Set 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.

Ansible

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.

Raw

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

The 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`.

PodmanAutoUpdate

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

Systemd

SystemdTarget 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.

File Transfer

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

The 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.

Kube Play

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

Workload labels

FetchIt 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=fetchit
  • fetchit.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.

Manifest example

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

Quadlet Method

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

Replace 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.

Optional Podman networks

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 backend
targetConfigs:
- 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=fetchit

Use 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.

HTTP image and disconnected ZIP archive downloads

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.

Encrypted Kube manifests

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.

Cleanup, rollback, and method identity

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.

Git mirrors and service status

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.