This is the multi-page printable view of this section. .
Farrow documentation
-
1: Start
- 1.1: Installation
- 1.2: Tutorial
- 1.3: Operations
- 1.4: Troubleshooting
-
2: Reference
- 2.1: Configuration
- 2.2: CLI
- 2.3: Images
- 2.4: Image Pipeline
-
3: About Farrow
- 3.1: Design
- 3.2: Status
- 3.3: Engineering
Farrow turns one Pigsty-compatible Inventory into fixed-IP QEMU virtual
machines. It manages one deployment per Unix user; state lives under
~/.farrow, so lifecycle and SSH commands work from any directory.
Choose the shortest path for your task:
- Start — install, first lab, daily changes, and troubleshooting.
- Reference — exact Inventory fields, commands, flags, output, and exit codes.
- About — simplified design, native validation, limits, and release gates.
New users should follow the tutorial. The complete normal
path is farrow setup, farrow up, then farrow status.
Farrow is pre-1.0. Current source behavior, native validation, packaging, release, and publication are separate gates. Read Status before depending on a development build.
1 - Start
Use these pages in order:
- Installation — build the current source and check the host.
- Tutorial — boot one node, expand to four, and use Pigsty.
- Operations — start, stop, change, inspect, and destroy nodes.
- Troubleshooting — short symptom-to-fix runbooks.
1.1 - Installation
Supported path today
Build from the current checkout:
There is no published v1 package yet. Do not substitute an unofficial binary
for the matching farrow and farrow-hosts-helper build.
The source build requires Go 1.27.x. macOS also needs an existing Homebrew
installation; Farrow can install QEMU through Homebrew but never bootstraps
Homebrew itself. The current compiled image repository is the development host
https://m0/farrow; use FARROW_REPO or --repo when another reachable mirror
is required.
Host requirements and dated evidence
Native HVF/KVM is the normal path. Farrow never retries an arbitrary native
failure under emulation. TCG is selected only for an explicit foreign
vm_arch, or for the catalogued stock EL8 arm64/Apple-Silicon incompatibility.
TCG is compatibility evidence, never performance evidence.
| Host | Last recorded evidence (2026-08-27) |
|---|---|
| macOS arm64 | verified with HVF, QEMU 11.1, and socket_vmnet |
| Ubuntu 26.04 amd64 | verified with KVM, QEMU 10.2.1, and NetworkManager |
| Rocky Linux 8.10 arm64 guest on macOS arm64 | verified with automatic TCG and full readiness |
| other Debian/Fedora/EL9 amd64 | implemented; repeat native validation before relying on it |
| macOS amd64, Linux arm64 | cross-built and unit-tested, not currently native-verified |
macOS needs Homebrew. Linux needs systemd plus either NetworkManager or
systemd-networkd. farrow setup installs missing supported packages through
Homebrew, APT, or DNF.
What setup changes
Run a dry plan first if desired:
Setup may install QEMU dependencies, prepare the host fixed-IP network, and install the narrow root-owned hosts publisher. It prints each mutation and the reason for sudo before applying anything.
In automation use --yes. Non-interactive sudo works with either a cached
credential or a suitable NOPASSWD policy; every privileged command still uses
an exact absolute argv.
Setup is idempotent. A healthy repeat reuses the network and installed helper. Source tests and this dated native matrix are separate: rebuilding a newer working tree does not silently refresh the rows above.
1.2 - Tutorial
1. Create the lab
With no existing file, setup writes farrow.yml for one node:
up downloads and verifies the image, creates the disks and cloud-init seed,
starts QEMU, and waits for the guest readiness record.
2. Verify the node
The default node has 2 vCPU, 4 GiB memory, a 64 GiB root disk, and a 128 GiB
XFS disk at /data.
farrow status also reports the effective Guest architecture and accelerator.
The default EL9/EL10 path is native HVF/KVM. On Apple Silicon, vm_image: el8
automatically selects same-architecture TCG for the stock 64K-granule kernel.
To run an amd64 Guest explicitly, set deployment-wide vm_arch: amd64; this
uses single-threaded TCG and is intentionally much slower. EL7 is available
only as a deprecated, native Linux/amd64 BIOS/KVM Guest.
3. Expand to four nodes
Add three host entries below the same hosts: mapping:
Then converge:
Only the new nodes are created. meta keeps its process and uptime. The
control node received the deployment key on its first boot, so it can SSH to
the new nodes immediately:
4. Use the same file with Pigsty
If Pigsty already generated pigsty.yml, skip the example file and run Farrow
in that checkout:
Farrow reads the documented VM fields plus native fields for naming,
control-node selection, and the login identity. Unconsumed settings such as
pg_role, pg_version, repo_*, and node_packages do not produce VM
drift; pg_cluster/pg_seq and the node-admin fields are consumed.
5. Stop or remove it
Normal destroy preserves the verified image cache, deployment keys, and
persistent disks. Use --delete-persistent or --purge only when intended.
1.3 - Operations
Inspect and access
Applied state is under ~/.farrow; these commands work from any directory.
Status includes the persisted Guest architecture and accelerator, so TCG is
never an invisible fallback.
plan, up, reload, and recreate prefer -f, then a discovered
Inventory, then the applied spec when no file exists. validate always needs
a file.
Stop and start
restart uses applied state. reload reads the Inventory again.
Change the deployment
Inventory changes fall into three visible fields:
| Field | Meaning | Action |
|---|---|---|
create |
desired node has no state | farrow up |
recreate |
VM definition changed | farrow recreate <node> --force |
missing |
stateful node left the file | restore it, or destroy it explicitly |
Deleting YAML never deletes a VM. Unconsumed Pigsty changes produce
action:none; native naming and node-admin fields are consumed even though
they do not begin with vm_.
Destroy
--delete-persistent and --purge are valid only for whole-deployment
destroy, not with node selectors. --purge removes persistent disks, keys,
and deployment state; images remain cached. Host network removal is separate
and refuses while a VM is attached:
Images
Images are signed-catalog entries and SHA-256 checked before use. Current
images are testing, except EOL EL7 which is deprecated, so starts print the
corresponding warning.
1.4 - Troubleshooting
Start read-only:
No configuration found
For the first deployment, run plan, up, or validate beside
farrow.yml/pigsty.yml, or pass -f /path/to/file. Once state exists,
plan, up, reload, and recreate can fall back to its applied spec.
Status, start, stop, SSH, and destroy always use applied state. If status
prints the same message, the selected FARROW_HOME has no applied state.
Setup needs sudo
The line before the prompt names the exact host mutation. Farrow attaches an
interactive terminal directly to sudo when the privileged step begins.
Automation needs an existing credential or a suitable NOPASSWD policy, then
passes --yes.
Native acceleration or compatibility runtime is unavailable
Native paths require HVF on macOS or KVM on Linux. TCG is selected only for an
explicit foreign vm_arch or a built-in image/host compatibility rule; an
arbitrary native failure never falls back. Homebrew QEMU contains both system
emulators. Linux setup installs only the native family, so a foreign Guest also
requires its matching qemu-system-* binary and firmware.
plan, up, and recreate validate the selected emulator and firmware before
any destructive mutation. Performance results from TCG are not meaningful.
Network is partial or invalid
Do not delete host files by hand. Review the owned cleanup plan:
Apply it with --yes only when it names Farrow-owned paths. Linux bridge
smoke failures now trigger automatic manifest-bounded rollback; an explicit
automatic rollback failed message means manual inspection is required.
Linux bridge helper fails
Debian/Ubuntu uses root:<caller-accessible-group> 4750; the caller does not
have to belong to kvm when /dev/kvm access comes from a desktop ACL.
Plan reports recreate or missing
recreate needs farrow recreate <node> --force. missing is only a report:
restore the host entry or run farrow destroy <node> --force.
SSH fails
Check farrow status, farrow ssh-config, and the serial log. Farrow’s own
SSH uses a loopback management port; direct Ansible traffic uses the fixed IP.
Catalog or image verification fails
The current binary embeds active and standby Catalog public keys. Unknown
signers, version rollback/equivocation, artifact size/SHA mismatch, and unsafe
qcow2 structure are distinct integrity failures. Use a correctly signed
repository or farrow image import --sha256 ...; do not copy bytes directly
into ~/.farrow/images.
A command was killed
Run farrow status. A provably live or dead runtime is converged from its
recorded identity; an ambiguous process remains blocked. Do not kill an
unknown PID based only on a state file.
If a recorded QEMU process still exists but its QMP socket is absent, preserve
the evidence and inspect serial/QEMU logs before using stop to converge it.
Do not delete runtime sockets or state files by hand.
For a bug report include the exact command and exit code, farrow version,
the three JSON reports above, host OS/architecture, and QEMU version.
2 - Reference
- 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.
2.1 - Configuration
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
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
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.2 - CLI
The installed binary is the authoritative reference for its own version. Every visible command includes its operational boundary and copyable examples:
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.
2.3 - Images
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.
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 |
For a pull, Farrow:
- refreshes
catalog.jsonand its adjacent.minisigfrom--repo, thenFARROW_REPO, then the compiled default repository; - verifies the signature with an embedded active or standby public key;
- selects the Catalog’s default release; standalone
image pulluses the native architecture, while lifecycle resolution honorsvm_arch; - reuses a local file only after size, SHA-256, and qcow2 checks pass;
- 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.
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.
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.
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
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.
2.4 - Image Pipeline
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, runqemu-img check, and emit an explicitly unpublishable evidence bundle. Guest credentials are not changed.offline: additionally use libguestfsvirt-customize --no-networkandvirt-caton the staged copy. It rejects unrelated UID/GID 88 occupants, normalizes the lockeddba/adminidentity, disables password/root SSH, removes keys/history/host identity/cloud-init cache, restores targeted SELinux labels, and reads back a deterministic marker.
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.
3 - About Farrow
- Design explains why Farrow has one Inventory, one deployment, and one fixed-IP network.
- Status separates implemented behavior, native validation, and remaining release gates.
- Engineering defines source, generated-output, package, image-pipeline, and evidence boundaries.
3.1 - Design
One useful abstraction
Farrow boots one Pigsty Inventory as one local QEMU deployment. It deliberately has no project marker, project registry, lease model, provider layer, or second configuration format.
State lives under ~/.farrow for one Unix user. The product assumes one active
Pigsty deployment per computer; this is not a root-enforced cross-user
singleton.
Node-level convergence
Farrow extracts only the documented VM and Pigsty-native fields, computes
per-node hashes, and keeps applied state plus process identity. Additions are
incremental. Changes require an
explicit per-node recreate. up also starts selected existing stopped nodes;
already-running peers remain untouched. Absence never authorizes deletion.
Runtime selection
Guest architecture is deployment-wide desired state. Omitted/native follows
the host; explicit amd64 or arm64 selects that Catalog artifact exactly.
Native HVF/KVM remains the default. A foreign architecture or one catalogued
image/host incompatibility selects a fixed TCG profile; there is no user
accelerator argument and no arbitrary failure fallback.
The effective architecture and accelerator are persisted in each QEMU
invocation and exposed by status. Before destructive recreate, Farrow proves
the selected QEMU binary and version, network backend, image bytes, boot mode,
and firmware. A later binary changing runtime policy cannot mix new nodes with
old invocations: runtime drift requires whole-deployment recreation.
Two NICs, one fixed subnet
The management NIC supplies DHCP, DNS, egress, and loopback SSH. The fixed-IP NIC supplies host/peer/Ansible traffic. macOS uses socket_vmnet. Linux follows active NetworkManager; otherwise it uses systemd-networkd and connects through the distribution bridge helper. Inactive networkd is started only after an activation-safety scan proves existing units cannot claim a real host link.
On Debian, the helper is temporarily and reversibly scoped to a group the caller actually belongs to. A real unprivileged QEMU bridge smoke must pass before setup accepts the network; failure triggers manifest-bounded rollback.
Safety boundary
QEMU and all guest artifacts run as the caller. Root is limited to host network setup and the optional hosts publisher. Destruction requires matching ownership, containment, node identity, QMP/process identity, and an allowlist of artifacts. Ambiguity stops the operation.
Review conclusion
The pivot away from projects and leases is correct for a one-lab product and greatly reduces cognitive and state complexity. Native review was still essential: the first implementation had cross-layer gaps in control-node keys, sudo policy, Debian helper access, NetworkManager verification, runtime preflight, result messages, and failed-install cleanup. Those paths were fixed and replayed on macOS and Linux before this documentation was simplified. A later adversarial review also caught destructive preflight ordering and signed Catalog-baseline upgrade bugs before EL7/EL8 compatibility was committed.
3.2 - Status
Farrow is pre-1.0. Source tests, dated native replays, packages, release, CI, and the public site are separate gates.
Last recorded native replay — 2026-08-27
This matrix belongs to the exact checkpoint exercised that day. Later source or documentation edits do not inherit native proof without another replay.
| Host | Path | Result |
|---|---|---|
| macOS 26.6.2 arm64 | HVF, QEMU 11.1, socket_vmnet | one node and additive four nodes passed |
Ubuntu 26.04 amd64 (mx) |
KVM, QEMU 10.2.1, NetworkManager | setup, one node, additive four nodes, and uninstall passed |
Both hosts passed fixed IP, SSH readiness, default CPU/memory/root/data disk, cloud-init, stop/start, cross-directory commands, unchanged control-node boot ID during scale-out, control-to-peer SSH, ignored unconsumed Pigsty changes, absence-never-destroys, and explicit destroy.
Linux additionally proved valid NOPASSWD automation, caller-accessible Debian helper policy, unprivileged bridge smoke, refusal to uninstall with four tap members, and exact restoration after destroy.
Interactive host-network and hosts commands now invoke sudo themselves; an
external sudo -v is optional. Darwin cleanup can reconstruct an uninstall-
only ownership plan from byte-identical interface evidence, the exact launchd
plist, and installed binary digests when network.json is missing.
On 2026-08-28 the post-calibration tree passed unit, race, vet, staticcheck, govulncheck, all four cross-builds, the simulated image-pipeline boundary, license verification, and GoReleaser configuration validation. An isolated local GoReleaser snapshot also built and verified all four archives, both DEB/RPM architectures, SPDX documents, checksums, dependencies, modes, and archive/package parity. Nothing was published, and those results do not extend this native matrix.
EL7/EL8 compatibility — 2026-08-28
Commit 7c666c7 restored EL7/EL8 after two independent Claude Code Opus 5 max
adversarial reviews. The first review blocked on destructive runtime preflight
ordering and signed-Catalog baseline migration; both were fixed, regression
tested, and the second review returned PASS with no required fixes.
Catalog 2026082801 is signed and active on the development repository: 9
families, 17 image artifacts, and 19 SHA-verified repository payloads including
the two socket_vmnet archives. A clean client accepted the public signature and
exact embedded digest.
An isolated macOS arm64 lifecycle replay booted Rocky Linux 8.10 arm64 with the
built-in TCG compatibility rule, passed stop/start and readiness in 44.2 seconds,
and verified NetworkManager, fixed IP/no-route/no-DNS, dba UID/GID 88, and the
generation/spec marker. EL7 bytes, qcow2 structure, BIOS layout, and 4K XFS root
are verified; the current native Linux/amd64 Farrow lifecycle replay remains
open.
Still open
- EL9 + NetworkManager + firewalld native replay;
- current systemd-networkd replay;
- host reboot persistence;
- macOS amd64 and Linux arm64 native runs;
- EL7 through the current native Linux/amd64 lifecycle;
- current 9p share replay;
- a complete current Pigsty
configure → farrow up → install.ymlrun; - published Homebrew/DEB/RPM consumption and release CI.
Current images remain testing, except EOL EL7 which is deprecated. Active
and standby Catalog public keys are embedded, but the repository must move off
the development host and private-key custody/rotation plus release custody must
be formalized before 1.0.
3.3 - Engineering
Repository boundary
The Farrow source repository contains code, tests, build/package definitions, legal notices, and a short landing README. This site is the authoritative home for user, design, operator, and release documentation. Raw review transcripts, historical scratch inventories, demo directories, generated binaries, and release output trees are not source inputs and must not be committed.
Generated output is disposable:
bin/— development builds;dist/and.goreleaser-*— release/snapshot staging;- root
farrow,farrow-hosts-helper, andcatalogsignbinaries; - Hugo
public/andresources/.
Build and source gates
make check combines these gates. A source gate is not native VM evidence;
macOS HVF, Linux KVM/networking, package consumption, release publication, and
the public render remain separate gates.
Release and package contract
Release tooling under packaging/, .goreleaser.yaml, and .github/workflows
is source, even though its generated directories are not. Archives and Linux
packages contain the matching binaries plus LICENSE, the minimal source
README, build metadata, and exact upstream license bytes reconstructed from the
module versions pinned by go.mod. Those generated license texts live under
licenses/ in archives and are not tracked as source. Detailed documentation
stays on this versioned site rather than being copied into every binary payload.
Never infer publication from a successful build. Commit, tag, archive/package, signature/attestation, upload, CI, and public consumption are distinct gates.
Image normalization
packaging/image-pipeline/ accepts an explicit local qcow2 source; it never
downloads or uploads. It copies and hashes the source, forces qcow2 parsing,
rejects backing/external/encrypted/unknown features, runs qemu-img check, and
can perform a no-network offline Guest mutation in an explicit QEMU sandbox.
UID/GID 88 collisions are rejected rather than rewritten ambiguously.
Catalog bytes are exported with:
The exporter is atomic and no-clobber. Catalog signing and application release signing use separate keys and trust domains.
Evidence policy
Historical M0–M4 notes were useful during implementation but are not product documentation. Their durable conclusions are condensed into Design and Status. A later source edit inherits no native proof; every status claim names its date, host, path, and remaining gates.