Skip to content

This is the multi-page printable view of this section. .

Return to the regular view of this page.

Reference

Exact contracts for the Pigsty-compatible Inventory and Farrow command line.
  • Configuration — discovery, accepted variables, defaults, disks, shares, naming, and drift.
  • CLI — commands, important flags, output modes, and exit codes.
  • Images — signed catalogs, aliases, cache layout, pulls, imports, and pruning.
  • Image Pipeline — candidate validation and offline normalization.

Farrow exposes no supported Go library API. Packages under internal/ are implementation details.

1 - Configuration

The Pigsty-compatible Inventory fields Farrow reads, their defaults, and node-level drift behavior.

Discovery

Configuration lookup order is explicit -f, then farrow.yml, farrow.yaml, pigsty.yml, and pigsty.yaml in the current directory. Every name uses the same Pigsty-compatible YAML Inventory format.

The retired top-level version:/nodes: format is rejected with migration guidance.

For plan, up, reload, and recreate, absence of a file falls back to the applied spec when a deployment exists. validate has no fallback. A configuration must be a regular non-symlink file no larger than 4 MiB.

What Farrow reads

Farrow reads host IPs, nodename, admin_ip, pg_cluster, pg_seq, node_admin_username, node_admin_uid, and the documented vm_* variables. admin_ip is read from all.vars; it selects the control node, or the first managed host is used. All nodes must resolve the same login username. For the default dba user, an explicit node_admin_uid must be 88.

Everything else is opaque and cannot create drift. This means unconsumed fields such as pg_role, pg_version, repo_*, and node_packages, not all possible pg_* or node_* names.

Inside this namespace validation is strict: unknown vm_* names, wrong types, Jinja expressions, invalid addresses, and conflicting sibling-group values are errors.

VM variables

Variable Default Meaning
vm_skip false do not virtualize this real/external host
vm_image u24 image alias
vm_arch native deployment-wide Guest architecture: native, amd64, or arm64
vm_cpu 2 vCPU count
vm_mem 4096 MiB integer, or a size such as 8GiB
vm_disk 64 root disk GiB
vm_disks [{path: /data}] extra disks
vm_alias [] guest /etc/hosts, SSH-config, and optional host aliases
vm_shares [] QEMU 9p host-directory shares

An empty host entry is a complete VM. A deployment contains 1–20 managed hosts; vm_cpu accepts 1–256 and memory must be at least 512 MiB.

vm_arch is stricter than ordinary per-host VM fields: when present it must resolve to one value on every managed host, so define it once in all.vars. Changing it is a deployment-envelope change and requires whole-deployment recreation. Linux setup installs only the native emulator; a foreign architecture also needs its matching qemu-system-* binary and firmware.

Data disks

vm_disks:
  - path: /data
    size: 128
    fs: xfs
    persistent: false

path is the disk identity and mount point. fs is xfs or ext4. persistent: true survives normal destroy. Use vm_disks: [] for no extra disk.

Shares

vm_shares:
  - host: /absolute/owned/source
    guest: /src
    readonly: true

Shares must be real, caller-owned, non-overlapping directories. They are for trusted development files, not PostgreSQL data.

Names and addresses

Node name order: nodename, then <pg_cluster>-<pg_seq>, then node-<last-octet>. Names must be unique.

All managed hosts must be in one RFC1918 /24: .1 is the host, .2.8 are reserved, and nodes use .9.254.

Drift

Farrow hashes each resolved node. Added hosts are created by up; selected existing stopped nodes are started; running peers stay untouched. Changed VM definitions require per-node recreate; removed hosts are reported but never destroyed. Deployment architecture, user, or subnet changes require whole-deployment recreation. Changing a field used to derive a node name appears as a missing old node plus a new node, so prefer stable explicit nodename values.

2 - CLI

Farrow commands, important flags, structured output, and exit codes.
farrow [--json|--yaml] [--verbose] <command> [flags] [node...]

The installed binary is the authoritative reference for its own version. Every visible command includes its operational boundary and copyable examples:

farrow --help
farrow setup --help
farrow image pull --help

In text mode, bare farrow and namespaces such as farrow image display contextual help and exit successfully. In JSON/YAML mode a bare namespace is a structured usage error; explicit --help always renders human help.

Commands

Area Commands
Prepare setup, init, validate, doctor
Lifecycle plan, up, start, stop/halt, restart, reload, recreate, status, destroy
Access ssh, exec, logs, provision, ssh-config, ss, hosts
Images image list/info/pull/import/sync/prune/reset-manifest
Host network network status/install/uninstall
Misc version, completion

Commands using applied state work from any directory. Configuration selection is command-scoped; -f is deliberately not a global flag:

Commands Desired-state source
setup [template] explicit -f, otherwise discovery, otherwise generate meta; template and -f are exclusive
init [template] generate a new inventory; read no desired state
validate explicit -f, then discovery; never applied state
plan, up, reload, recreate explicit -f, then discovery, then the applied resolved specification
other lifecycle/access commands no desired-state inventory; use applied or marker-owned state as applicable

Important flags

Flag Meaning
--json, --yaml machine-readable stdout; progress remains on stderr
--verbose bounded diagnostics on stderr
--yes apply a displayed host/setup plan
--force skip the interactive destroy/recreate confirmation; required without a terminal
--no-wait return after QMP/process identity without guest readiness
--delete-persistent during whole destroy, also delete retained data disks; invalid with node selectors
--purge whole-deployment disposal: delete disks, keys, and deployment state; keep images

If a failing command has not already emitted a richer typed result, structured mode writes one object containing error and message before returning the documented non-zero exit code. Existing typed failure results are never followed by a second JSON/YAML document.

plan is read-only and returns success even when its action is recreate or blocked-removal; automation must inspect the action and create, recreate, and missing fields. up creates additions and starts selected stopped nodes, but returns a conflict instead of applying destructive drift.

status reports the persisted guest_arch and accelerator for each node. TCG selection is therefore explicit in both text and structured output.

SSH passthrough and completion

farrow ssh [node] [--] [command ...] opens a session or runs an optional command. farrow exec [node] [--] <command ...> requires a command and passes through its exit status. Presentation flags before -- belong to Farrow; arguments after -- belong to OpenSSH or the remote program.

Load farrow completion bash|zsh|fish|powershell for command and scoped-flag completion. It also provides templates, image aliases, closed flag choices, and best-effort node names from the desired or applied specification.

Exit codes

Code Meaning
0 success
1 runtime failure
2 usage or invalid configuration
3 missing host capability
4 state conflict or explicit convergence required
5 partial multi-node completion
6 resource conflict
7 integrity or ownership failure

ssh and exec pass through the remote program’s exit code, except SSH’s reserved transport-failure code 255, which Farrow maps to runtime failure 1.

3 - Images

Signed catalogs, built-in aliases, repository selection, local cache verification, imports, and pruning.

Farrow uses a signed static-file Catalog plus immutable qcow2 artifacts. A Catalog update does not require a new Farrow binary, but the binary decides which signing keys and image safety rules are trusted.

Warning

EL7 is deprecated; every other built-in image is currently testing, not supported. The warning printed by up is intentional: a successful pull is an integrity result, not a production-support promise.

Aliases and pull order

The embedded Catalog contains 9 families and 17 artifacts: el7 is amd64-only; el8, el9, el10, d12, d13, u22, u24, and u26 have amd64 and arm64 artifacts. u24 is the VM default.

Alias Distribution Architectures Boot Status
el7 CentOS Linux 7.9 / 2211 amd64 BIOS deprecated
el8 Rocky Linux 8.10 amd64, arm64 UEFI testing
el9, el10 Rocky Linux amd64, arm64 UEFI testing
d12, d13 Debian amd64, arm64 UEFI testing
u22, u24, u26 Ubuntu amd64, arm64 UEFI testing
farrow image list
farrow image info u24
farrow image pull u24

For a pull, Farrow:

  1. refreshes catalog.json and its adjacent .minisig from --repo, then FARROW_REPO, then the compiled default repository;
  2. verifies the signature with an embedded active or standby public key;
  3. selects the Catalog’s default release; standalone image pull uses the native architecture, while lifecycle resolution honors vm_arch;
  4. reuses a local file only after size, SHA-256, and qcow2 checks pass;
  5. otherwise downloads the repository artifact, with the Catalog’s immutable HTTPS upstream URL as fallback.

The current compiled default is the development repository https://m0/farrow; no public image service is claimed yet. An explicit repository failure is fatal, while an unreachable compiled default falls back to the embedded Catalog.

Runtime policy

Matching architectures use native HVF/KVM except one catalogued incompatibility: the stock EL8 arm64 64K-granule kernel cannot run through Apple HVF, so Apple Silicon uses visible same-architecture TCG automatically. Explicit foreign vm_arch also uses TCG. amd64-on-arm64 uses a single translation thread to preserve x86 memory ordering. TCG results are not performance evidence.

EL7 is deliberately limited to native Linux/amd64. Linux setup installs only the native QEMU family; foreign architectures require the matching system emulator and UEFI firmware before plan, up, or recreate can proceed.

farrow image pull --repo https://mirror.example/farrow u24
FARROW_REPO=/absolute/local/repository farrow up

Repository URLs may be HTTP or HTTPS because the Catalog signature and image digest remain authoritative; immutable upstream artifact URLs must be HTTPS.

Trust and verification

Current ordinary builds embed both production public verification keys. The private signing keys are external to the source repository. Catalog activation rejects unknown keys, malformed content, equivocation, and versions below the recorded high-water mark unless the operator explicitly allows a downgrade.

Every accepted image must be a size- and SHA-256-matched plain qcow2 with no backing file, external data file, encryption, or unknown incompatible feature. Verified base images become read-only; node root disks are overlays and never modify the base.

farrow image sync https://repo.example/farrow/catalog.json
farrow image sync --allow-downgrade /absolute/repo/catalog.json
farrow image reset-manifest

reset-manifest restores the embedded bootstrap Catalog but keeps the anti-rollback high-water mark.

Local layout and imports

Images live under FARROW_HOME/images (default ~/.farrow/images): family directories contain downloaded artifacts, manifests/ stores Catalog state, and local/ plus local-images.json hold imports. There is no old ~/.farrow/cache or content-addressed sha256/ hierarchy.

farrow image import --sha256 <digest> /path/to/base.qcow2
farrow image import --name local-mybase --boot uefi \
  --source-user ubuntu --sha256 <digest> /path/to/base.qcow2

Named local aliases must begin with local-, so a future signed Catalog cannot shadow them. --boot and --source-user are required with --name; Farrow does not guess the guest bootstrap contract.

Pruning

farrow image prune --dry-run
farrow image prune --yes

Prune lists exact unreferenced images and stale staging files before deletion. An image referenced by applied deployment state is never a candidate. Images remain cached after destroy, including destroy --purge.

The compiled Catalog can be exported byte-for-byte with go run ./tools/catalogexport /absolute/new/catalog.json. A public Catalog at the embedded version must use those exact bytes; same-version different bytes are rejected as equivocation. Release signing and image Catalog signing remain separate trust domains.

4 - Image Pipeline

Validate or offline-normalize an explicit qcow2 candidate without downloading, uploading, or signing it.

packaging/image-pipeline/ accepts one already-downloaded immutable qcow2 and an independently obtained SHA-256. It never downloads, uploads, touches Farrow runtime/network state, reads signing keys, or marks an image supported.

Modes

  • validate: copy/re-hash, force qcow2 inspection, validate the single backing chain, run qemu-img check, and emit an explicitly unpublishable evidence bundle. Guest credentials are not changed.
  • offline: additionally use libguestfs virt-customize --no-network and virt-cat on the staged copy. It rejects unrelated UID/GID 88 occupants, normalizes the locked dba/admin identity, disables password/root SSH, removes keys/history/host identity/cloud-init cache, restores targeted SELinux labels, and reads back a deterministic marker.
SOURCE_DATE_EPOCH=1787486400

./packaging/image-pipeline/build.sh \
  --mode validate \
  --source /absolute/source.qcow2 \
  --expected-sha256 <digest> \
  --output /absolute/new/evidence-directory \
  --name u24 --release 20260801.0.0 --arch amd64 \
  --source-user ubuntu --boot uefi \
  --source-uri https://immutable.example/source.qcow2 \
  --artifact-url 'https://images.example/u24/{sha256}.qcow2' \
  --license NOASSERTION \
  --source-date-epoch "$SOURCE_DATE_EPOCH" \
  --manifest-version 2026082801

Source/output paths must be absolute; source is canonical, regular, non-symlinked, stable while copied, and at most 16 GiB. Output must not exist. The builder uses an exclusive adjacent lock, mode-0700 staging, and one final rename. Failure removes only its guarded staging directory.

Every successful bundle contains the read-only qcow2, recipe, SLSA provenance, SPDX boundary SBOM, manifest-candidate.json (testing), validation evidence, and checksums. Signing is deliberately outside this pipeline. Validate mode is byte-reproducible for fixed inputs/tools; offline mutation must be built twice and compared before release evidence is accepted.