Skip to content

1 - Article

Project articles and long-form technical notes about Barn.

Project articles and long-form technical notes about Barn live in this section. For current product behavior, use the documentation.

2 - Design Notes

Architecture decisions, trade-offs, and implementation boundaries behind Barn.

Barn’s source repository once carried the redesign brief, implementation ADRs, and native evidence beside the code. That material was useful while the product was changing quickly, but many early decisions were later superseded. This section keeps the durable reasoning, rewritten against the current source instead of republishing stale plans.

Start with the product model, then follow the boundaries outward:

  1. Why Barn has no projects — one Inventory, one owner-scoped deployment, and no second source of truth.
  2. Why every node has two NICs — fixed identity for the lab, separate from management egress.
  3. Declarative does not mean destructive — per-node drift with explicit recreate and removal.
  4. A PID is not a virtual machine — QMP identity, process evidence, journals, and bounded recovery.
  5. repo.yaml is intent; catalog.json is evidence — a static image repository whose generated metadata is checked against the actual qcow2 bytes.

Use the documentation for current behavior and the status page for dated verification. These design records explain why those contracts exist; they do not turn a design, build, or local test into release evidence.

These articles retain their original publication dates and were last reviewed against source on 2026-09-26, with names updated for the Barn 0.9.0 candidate on 2026-09-29. Changes specific to an unreleased candidate are marked separately; historical verification keeps its original date and scope.

2.1 - Why Barn Has No Projects

Why Barn replaced per-directory project state with one owner-scoped deployment driven by one Pigsty Inventory.
Note

Renamed 2026-09-29: names now follow the unreleased Barn 0.9.0 candidate. The prior source review was on 2026-09-26: the original publication date is retained; the text below reflects the implementation reviewed on this date. See Status for released versus candidate behavior and dated acceptance evidence.

Barn began with a familiar VM-manager abstraction: a working directory was a project, a hidden marker gave it identity, a registry found projects again, and a host-global lease kept their private networks from colliding. That model can support many independent VM sets. It was also the wrong model for the product Barn was actually becoming.

The target is not a general-purpose hypervisor front end. It is one local, fixed-IP Pigsty lab. The operator already has a complete description of that lab: the Pigsty Inventory. Adding a second VM manifest and a second project identity made every ordinary question harder.

Note

Decision status: current. This record explains the product model. For current filenames, fields, and commands, use the configuration reference.

The old abstraction turned ordinary questions into project-management questions:

  • Which file is authoritative for a node’s name and address?
  • Does moving a directory move the lab or create a new one?
  • What happens when the marker survives but the registry does not?
  • Is a missing directory an abandoned project or an unavailable disk?
  • Which project owns the one host network?

Those are legitimate multi-project questions. Barn chose to stop creating them.

One Inventory is enough

The Inventory handed to Pigsty is also Barn’s desired state. Barn reads a small, documented boundary: host addresses, a few Pigsty-native identity fields, and the vm_* namespace. Validation is strict inside that namespace; the rest of the Inventory stays opaque and passes to Pigsty untouched.

This asymmetric rule matters. A misspelled vm_mem must fail because it would change the machine Barn builds. A new PostgreSQL tuning parameter must not fail merely because the VM layer has never heard of it. The same file can therefore evolve as a Pigsty Inventory without becoming a second Barn format in disguise.

Names follow the same principle. A node uses nodename when present, then a stable Pigsty cluster/sequence derivation, then its address suffix. Barn does not add a parallel vm_name that can disagree with the hostname Pigsty sees.

One owner-scoped state root

Applied state lives under BARN_HOME, normally ~/.barn. There is no marker in the working directory and no per-directory registry. Commands that operate on applied state can run from any directory; commands that propose new desired state discover or receive an Inventory explicitly.

This is an owner-scoped deployment, not a root-enforced machine-wide singleton. Each Unix user has an independent state root. Barn is intended for a trusted development workstation, not hostile-user arbitration on a shared server.

The simplification has practical consequences:

  • moving or renaming the source directory does not move deployment identity;
  • losing the Inventory does not erase the applied state;
  • cleanup follows explicit lifecycle commands; deleting the state directory is not a substitute for stopping VMs or removing managed integrations;
  • image cache, keys, nodes, disks, locks, and deployment state share one inspectable home. Short QMP/pid paths, SSH client integration, and host-global networking have their own managed locations; see Uninstall for complete cleanup.

Configuration absence is not intent

One deployment does not mean the Inventory is disposable. It means Barn can distinguish desired configuration from applied evidence. When a command needs desired state, an existing deployment can supply its applied spec where the command contract allows that fallback. A missing file is never interpreted as a request to remove nodes.

That rule survives every layer of the lifecycle: planning and deletion stay explicit, and recovery preserves ambiguous resources instead of guessing what the user meant.

The trade-off is deliberate

Barn does not support multiple concurrent deployments per user. Projects, registries, and address-level leasing are not hidden future features; they were rejected because they would reintroduce the abstraction the product removed.

If the requirement changes to multi-tenant or multi-host orchestration, that is a different product boundary. For a local Pigsty lab, one Inventory and one deployment make the important things—addresses, ownership, drift, recovery, and cleanup—much easier to explain and prove.

Read next: Why every Barn node has two NICs.

2.2 - Why Every Barn Node Has Two NICs

Why Barn separates management egress from the fixed-address network used by the host, peers, Ansible, and Pigsty.
Note

Renamed 2026-09-29: names now follow the unreleased Barn 0.9.0 candidate. The prior source review was on 2026-09-26: the original publication date is retained; the text below reflects the implementation reviewed on this date. See Status for released versus candidate behavior and dated acceptance evidence.

A Pigsty Inventory names machines by stable addresses. PostgreSQL replication, etcd membership, HAProxy backends, VIPs, monitoring targets, and Ansible all assume that 10.10.10.11 continues to mean the same node. A loopback port forward can expose SSH or PostgreSQL to the host, but it cannot provide that network identity to peers.

This is why Barn does not choose between a convenient NAT mode and an advanced fixed-network mode. Every normal node gets both jobs, on separate interfaces.

One interface should not do two incompatible jobs

Interface Addressing Responsibility
management QEMU user-mode NAT, DHCP DNS, default route, outbound internet, and loopback SSH fallback
private, MAC-matched fixed Inventory address host-to-node, node-to-node, Ansible, Pigsty services, and VIP traffic

Barn matches both virtual interfaces by their deterministic MAC addresses and does not rename them. Guest-visible names are whatever the image’s network stack chooses (commonly eth0 or enp0s4); the MAC and address contract, not the display name, determines each interface’s role.

The management interface is deliberately ordinary. It lets a new cloud image reach package repositories before any application exists, without installing NAT rules or a DHCP service on the host.

The private interface has one deterministic RFC1918 address, no default route, and no DNS. Guest setup checks those properties, but since 0.7 private-network checks are optional: a failure is recorded as a private-network warning and does not prevent readiness when management SSH and guest identity are usable. An operation can therefore succeed with limited fixed-IP connectivity. Before deploying a service that needs this interface, inspect the warnings and test the relevant host/peer connection. Repeat up after correcting the cause.

Note

Decision status: current. The topology is part of Barn’s normal lifecycle, not an optional “private mode.” See the design reference for the current platform boundary.

The Inventory owns the address plan

All managed hosts belong to one canonical RFC1918 /24:

Range Meaning
.1 host side of the private network
.2–.8 reserved boundary, including valid L2 VIP space
.9–.254 fixed node addresses

The guest private interface does not request DHCP: cloud-init receives the exact address already declared in the Inventory. On macOS, vmnet’s configured DHCP range ends at .8; managed node addresses begin at .9. Linux uses a bridge with static guest addresses. The VM address contract therefore does not depend on a lease database, and Ansible uses the same address throughout the deployment.

For generated configuration, setup can choose from a small bounded set when the default subnet is already occupied. An explicitly supplied Inventory is never silently rewritten to escape a collision. The whole lab—host interface, nodes, Pigsty addresses, and aliases—must agree on one subnet.

Platform-specific backend, identical guest contract

The guest sees the same topology on every supported host, while Barn follows the host’s native networking owner:

  • macOS: a pinned socket_vmnet service provides the private link. Host mode is the default; shared mode is explicit. QEMU still runs as the user.
  • Linux with active NetworkManager: Barn creates an owned barn0 bridge through nmcli and integrates with active firewalld policy.
  • Linux with systemd-networkd: Barn installs owned units and uses the distribution qemu-bridge-helper so QEMU remains unprivileged.
  • Inactive networkd: activation is allowed only after a pre-mutation scan proves that existing units cannot claim a real host interface.

Supporting both Linux managers is not abstraction for its own sake. Starting networkd on a desktop or RHEL-family host merely because Barn knows how to write .network files can disrupt the host’s real network. The backend must follow the component already in charge.

Host networking is a transaction

A bridge or vmnet daemon outlives one CLI process and crosses a privilege boundary, so Barn treats installation as a reversible host transaction:

  1. inspect routes, interfaces, services, ownership, and existing state;
  2. print the exact plan before mutation;
  3. re-check the preconditions immediately before apply;
  4. write root-owned state describing what Barn created and what existed before it;
  5. prove an unprivileged QEMU attachment;
  6. accept the installation only after readiness checks pass.

A foreign interface that happens to use the same .1/24 is not adopted. A modified owned file is not overwritten. Uninstall refuses while recorded nodes are live and restores only the prestate named by the manifest. Failure is a reason to stop, not permission to delete whatever appears to be in the way.

The accepted trade-off

Guest internet traffic uses QEMU’s user-mode network. That is not the fastest possible forwarding path, but it keeps ordinary egress unprivileged and portable. The traffic that matters to a Pigsty lab—host-to-guest, replication, service calls, and package distribution from a local control node—stays on the private link.

The result is a useful separation of concerns: the management NIC makes a machine easy to bootstrap; the private NIC makes it a stable member of the lab. Neither has to pretend to be the other.

Read next: Declarative does not mean destructive.

2.3 - Declarative Does Not Mean Destructive

How Barn uses per-node hashes and explicit operations so missing configuration can never authorize deletion.
Note

Renamed 2026-09-29: names now follow the unreleased Barn 0.9.0 candidate. The prior source review was on 2026-09-26: the original publication date is retained; the text below reflects the implementation reviewed on this date. See Status for released versus candidate behavior and dated acceptance evidence.

“Declarative” is often shortened to “make reality equal the file.” That is a useful slogan until the file is incomplete, the wrong branch is checked out, or one YAML group is temporarily removed. If absence is treated as deletion, an ordinary editing mistake becomes a destructive operation.

Barn uses a narrower rule:

Desired state may authorize creation. It can describe drift. It never authorizes destruction by omission.

The distinction is central to a VM runtime because roots, data disks, SSH keys, and local evidence are not stateless replicas. Recreating them may be correct, but it must be a decision the operator can see.

From Inventory to node identity

Barn does not hash the whole Pigsty Inventory. It first extracts the fields it owns, fills defaults, canonicalizes image selectors and architecture, and builds a canonical resolved spec. Exact Catalog artifact resolution remains separate, so a channel update does not itself change a node’s spec hash. Each node then receives a hash of:

  • the deployment envelope shared by every node, such as subnet, login user, architecture policy, and the deployment-level default image request; and
  • exactly that node’s resolved definition.

Adding a peer therefore does not change an existing node’s hash. Editing an unconsumed Pigsty field—PostgreSQL version, packages, or service policy—does not produce VM drift. The VM layer reacts only to the contract it actually understands.

This also avoids a dangerous half-promise: Barn does not pretend to implement Ansible’s entire variable system. Unknown vm_* keys and conflicting values inside the owned namespace fail. Everything outside the documented boundary is opaque rather than partially interpreted.

Note

Decision status: current. Barn converges additions automatically, but definition changes and removal require explicit commands. See Daily Operations for the command workflow.

The five plan outcomes

barn plan compares desired state, applied deployment state, and committed node state. The result is intentionally small:

Outcome Meaning Apply path
create desired node has no committed state barn up creates it
unchanged definition and runtime still match running peer stays untouched; stopped peer may start
recreate node definition changed explicit barn recreate --force <node>
missing applied node is absent or skipped in the Inventory explicit barn destroy <node> --force, or restore it to the file
envelope drift subnet, login identity, architecture, or runtime policy changed whole-deployment recreate

Plan is read-only. It reports the exact node sets and, in text mode, the command that applies the required explicit transition.

Why up stops at drift

Barn could decide that changing CPU or memory is harmless enough to apply, or that a new image should silently rebuild a root disk. Pre-1.0 intentionally does neither. A changed VM definition is classified as recreate and up returns a typed conflict.

That conservative boundary has two advantages:

  1. all changes that can invalidate Guest state share one visible operation;
  2. Barn can finish every prerequisite check before touching the current node.

The recreate path resolves the selected emulator, acceleration policy, firmware, image bytes, network backend, shares, and persistent-disk contract before destruction. If a foreign emulator is missing or a share is unsafe, the existing VM remains intact.

Why missing nodes block convergence

A node can disappear from desired state for many reasons that do not express deletion intent:

  • the operator opened a reduced Inventory while debugging;
  • a group was renamed or filtered;
  • vm_skip temporarily marks a real or external host;
  • a merge conflict dropped a YAML branch;
  • the configuration file itself is unavailable.

When applied state contains such a node, up stops and names it. The operator must either restore the definition or run the explicit destroy command. This is deliberately more friction than automatic garbage collection—and far less friction than recovering an unintended disk deletion.

Persistent data disks add another boundary. Normal destroy preserves them. Whole-deployment destroy --delete-persistent explicitly includes owned persistent disks, including retained disks, and accepts no node selectors; deleting deployment keys as well requires whole-deployment destroy --purge or purge. Retention is not a backup guarantee: guest bootstrap can reset unrecognized or confirmed damaged test filesystems, even on persistent disks. See Data disks. One confirmation cannot silently grow into broader authority.

Convergence is still incremental

Safety does not mean rebuilding everything. New nodes are created without stopping existing peers. Selected stopped nodes start without recreating running ones. A per-node recreate preserves peers and, when requested by the disk contract, persistent data.

The result is declarative where desired state is strong evidence—creation and comparison—and explicit where the cost is irreversible. Barn does not make the operator manually calculate drift, but it also does not confuse a diff with permission.

Read next: A PID is not a virtual machine.

2.4 - A PID Is Not a Virtual Machine

Why Barn combines QMP identity, process evidence, typed invocations, and journals before it signals or deletes anything.
Note

Renamed 2026-09-29: names now follow the unreleased Barn 0.9.0 candidate. The prior source review was on 2026-09-26: the original publication date is retained; the text below reflects the implementation reviewed on this date. See Status for released versus candidate behavior and dated acceptance evidence.

A pidfile answers one question: which integer did a process have when the file was written? It does not prove that the process is still alive, that the PID was not reused, that the executable is QEMU, or that this particular QEMU owns the node an operator wants to stop.

That is not enough authority for SIGKILL, and certainly not enough authority to remove a root disk.

Barn treats identity as a chain of independent evidence. Each link has a different job, and destructive action proceeds only when the required links agree.

QMP is the primary runtime identity

Every VM receives a generated UUID and an expected QEMU name. After launch, Barn connects to the QEMU Machine Protocol socket and asks QEMU for both. The VM is not considered started merely because the process returned or a socket path appeared; QMP must report the expected name and UUID.

The same check guards shutdown. A QMP endpoint with a different name or UUID is not “probably the old VM.” It is a hard identity mismatch, and Barn sends no command through it.

QMP also provides the clean path: request Guest powerdown, wait for the Guest, then ask QEMU to quit if the bounded graceful wait expires. Process signals are fallback tools, not the primary lifecycle API.

Note

Decision status: current. This record explains the fail-closed lifecycle boundary. Operational recovery starts with Troubleshooting, not manual deletion.

Process identity closes the fallback gap

QMP may be unavailable after a crash, a damaged runtime directory, or a half-completed shutdown. For that case Barn records a process tuple:

  • PID;
  • executable path;
  • process start time;
  • SHA-256 of the observed command line.

The complete typed QEMU invocation is stored beside it. Before sending SIGTERM, Barn re-reads the live process and requires the tuple to match. Before escalating to SIGKILL, it captures the tuple again, specifically to close the PID-reuse window created by the bounded TERM wait.

If QMP still answers but a QMP operation fails, Barn does not bypass that live control plane with a signal. If QMP reports another identity, it stops. If the process tuple cannot be verified, it stops. “Unable to prove” is a result, not a reason to weaken the check.

Unreleased 0.9 candidate update: when QMP is unavailable and the recorded PID is positively identified as an unrelated process, Barn treats the old VM as stopped and never signals that unrelated process. This differs from an unreadable or ambiguous identity, which still blocks the operation.

Journals describe work before state exists

Committed node state cannot describe the earliest part of creation: disks and seed media must exist before the VM can start, and the process must start before its identity can be committed. A crash in that interval would otherwise leave artifacts with no trustworthy owner.

Barn writes a mode-0600 prepare journal first. It contains:

  • operation and VM UUIDs;
  • node name and resolved-spec hash;
  • each completed artifact from a fixed kind/path allowlist;
  • the typed QEMU invocation once preparation is complete;
  • the exact node-state path once commit succeeds.

The journal is strict versioned JSON. Unknown fields, invalid UUIDs, unsafe paths, repeated artifacts, wrong modes, symlinks, or a path outside the node directory invalidate it.

Recovery can therefore answer a bounded question: which artifacts did this uncommitted operation create? It is not a request to scan the directory and guess.

Rollback is narrower than cleanup

An offline rollback is allowed only when no committed node state exists and no QMP socket or pidfile from the typed invocation remains. The node directory may contain only the journal and the completed allowlisted artifacts. Rollback then removes the completed artifacts in reverse order, followed by the journal and empty node directory.

Unreleased 0.9 candidate update: a failed first up can be retried after the Inventory is edited. Safe cleanup follows the journal’s completed artifact list rather than requiring the new desired spec to match the failed old spec.

A committed node is never rolled back by a stale prepare journal. A pre-existing disk is never added to the action list. An unexpected file blocks directory removal instead of being swept up as collateral damage.

Normal destroy follows the same philosophy. It proves containment, file type, ownership boundary, process death, and an exact artifact set. Persistent disks live behind their own preservation and purge rules. Directories are removed only after the known files are gone, so an unknown entry turns into an error.

Atomic state makes the evidence durable

State updates use a same-directory temporary file, fsync, atomic rename, and parent-directory fsync; symlink targets are rejected. Deployment and node locks serialize mutations. The goal is not to make crashes impossible—it is to ensure a crash leaves either an old committed fact or a new committed fact, plus a journal for the bounded interval between them.

This design is intentionally conservative. It may ask an operator to inspect an ambiguous resource that a more aggressive tool would delete. For a local database lab, preserving the evidence is the safer failure mode.

Read next: repo.yaml is intent; catalog.json is evidence.

2.5 - repo.yaml Is Intent; catalog.json Is Evidence

Why Barn separates human-authored image policy from generated metadata that must match the actual qcow2 artifacts.
Note

Renamed 2026-09-29: names now follow the unreleased Barn 0.9.0 candidate. The prior source review was on 2026-09-26: the original publication date is retained; the text below reflects the implementation reviewed on this date. See Status for released versus candidate behavior and dated acceptance evidence.

A static image repository sounds like a directory of qcow2 files plus a JSON index. The difficult part is deciding which facts a maintainer may write by hand and which facts must be derived from the bytes being published.

If checksums and sizes live in the hand-authored source, they are easy to copy incorrectly. If policy exists only in generated JSON, reviewing a channel change or deprecation requires reading machine output. Barn keeps the two jobs separate.

repo.yaml: what the maintainer means

The source-controlled repo.yaml contains author intent:

  • repository revision and defaults;
  • image families and aliases;
  • movable channels such as stable;
  • exact versions and architectures;
  • boot mode and support status;
  • immutable upstream locations and provenance notes.

It deliberately does not contain generated artifact size, SHA-256, or virtual size. A compact entry can say that d13:stable points to one exact version with amd64 and arm64 variants without pretending to know facts that belong to the files. This historical policy excerpt illustrates the format; see Image Repositories for a complete working example and the reference for current versions:

defaults: { image: d13, channel: stable, arch: native, boot: uefi }
images:
  d13:
    aliases: [debian13, debian, trixie]
    channels: { stable: "20260810.2566.0" }
    versions:
      "20260810.2566.0":
        status: supported
        variants:
          amd64: {}
          arm64: {}

This is the right layer for review: a pull request can show that a channel moved, a version was deprecated, or a provenance statement changed.

Note

Decision status: current. Repository syntax and client behavior are documented in Images; candidate preparation is a separate image-pipeline contract.

catalog.json: what the repository can prove

catalog.json materializes policy against the local repository. For every variant it records the exact filename, byte count, SHA-256, qcow2 virtual size, boot contract, source user, and immutable upstream provenance.

Filename, byte count, digest, and virtual size are materialized and checked against the artifact. Boot mode, source user, status, and provenance are validated policy copied from repo.yaml; inspection does not independently prove those declarations. Build forces qcow2 parsing, rejects backing files, external data, encryption, and unknown incompatible features, and runs structural checks before atomically replacing the Catalog.

The artifact identity is the tuple (image, exact version, architecture), not the channel that selected it. Files keep readable immutable names:

images/d13-20260810.2566.0-arm64.qcow2

Readable names are an operational feature: an administrator can inspect, mirror, or recover a repository with ordinary filesystem tools. Integrity still comes from generated metadata and verification, not from trusting the name.

Three operations, three responsibilities

The repository CLI keeps observation, generation, and proof separate:

Command Responsibility
barn repo scan report tracked, missing, untracked, or unsafe artifacts without changing anything
barn repo build validate source and artifacts, then atomically materialize the Catalog
barn repo verify rebuild the materialization in memory and require byte-for-byte equality with the published Catalog

build never edits repo.yaml or qcow2 bytes. verify is stronger than “every checksum is valid”: it also proves that no source policy or artifact change was omitted from the generated Catalog.

Publication follows the same direction. Upload immutable image bytes first; publish the Catalog and its matching signature last. Publish that pair together where possible. A client refuses a mismatched pair during a partial upload; the order avoids advertising image bytes that are still in transit.

Selectors may move; artifacts may not

Human configuration needs convenient selectors. d13:stable, el9@9, and [email protected] can resolve to newer exact versions as the repository evolves. Numeric prefixes compare dot-separated components as integers, so 9.10 sorts after 9.9.

After resolution, the client persists the exact version, architecture, size, and digest. An already resolved node does not become a different machine because a channel moves. Convenience exists at selection time; immutable identity exists at execution time.

Transport and trust are different questions

Official and plain-HTTP Catalogs require a trusted detached signature. An operator who explicitly selects a local directory or HTTPS repository may use an unsigned Catalog because local ownership or authenticated transport is the explicit trust decision. An implicit compiled default remains in the signed trust domain even if its URL is HTTPS.

Accepted Catalog state is tracked independently per repository. Barn rejects unknown keys, a revision below that repository’s high-water mark, and different bytes at the same revision. An explicit downgrade is visible and scoped to the selected repository; resetting to the embedded Catalog does not erase the anti-rollback record.

Catalog acceptance is only the first half. Every pull still checks byte count, SHA-256, and qcow2 structure. Verified base images become read-only, and node root disks are overlays, so normal VM writes never mutate the trusted base.

Separate trust domains stay separate

Image Catalog keys authorize image policy. Release signing proves the Barn application artifacts and checksum manifest. The two key sets are intentionally independent: permission to publish a VM image must not imply permission to ship a new Barn binary, or vice versa.

The Barn 0.9.0 candidate defaults to https://repo.pigsty.io/barn and expose --mirror for https://repo.pigsty.cc/barn; --repo remains the explicit custom override. Updated since 0.7.0: the two official repositories may fall back to each other for image downloads, always verifying the same Catalog size and SHA-256. Custom repositories remain exclusive. Catalog updates still use the selected source; embedded upstream URLs remain provenance and never become an artifact fallback. Source configuration, generated Catalog, uploaded artifacts, signing, and public availability remain separate release gates.

That is the larger design principle: policy should be pleasant to review, but facts about shipped bytes should be generated, reproducible, and independently verifiable.

3 - Release Notes

Current Barn releases plus preserved pre-rename development records.
Important

Barn is pre-1.0. Versioned release notes appear alongside preserved Farrow release and Piglet development records; historical entries do not establish support for current Barn bytes.

3.1 - Farrow 0.8.0: clearer recovery and refreshed images

Recover host preparation, isolate failed nodes, preserve VM identities, and start the September Debian and Ubuntu images.

Farrow 0.8.0 reduces manual work after interrupted setup and partial VM starts. It also refreshes the Debian and Ubuntu images while retaining every previous Catalog artifact and the identity of existing VMs.

What changed

  • Host preparation follows the command. Interactive start, restart, and reload can prepare missing host tools and restore an intact Farrow network. On macOS, new network installation completes Homebrew discovery/installation or the verified archive download before requesting administrator authentication, so Homebrew cannot invalidate a credential acquired too early.
  • A failed node does not block independent peers. A missing host share fails its own node during up or start; stopped peers can still start when a new node fails to prepare. Errors name the source and mount, and Farrow does not create an empty replacement. Restart/reload/recreate check share access before stopping existing VMs.
  • Recovery preserves identity. A missing public key is derived from the original private key. A lost private key produces backup-recovery guidance instead of a new login identity. macOS vmnet log-directory recovery retains network ownership evidence and avoids false subnet-conflict reports.
  • Failures keep their context. Scoped retry commands preserve the inventory, repository, and applicable flags; a start retry remains start. Setup and its retry share one operation ID, and bounded event logs work before deployment state exists. Uncached image information no longer requires QEMU.
  • Cleanup reports the final result. Explicit persistent-disk deletion and purge no longer describe disks as both retained and deleted. Owned disks left by a previously removed node do not block destruction of the remaining lab.

September images

Embedded Catalog 2026092001 contains 37 artifacts across nine families, including all 27 previous artifacts. These new stable versions cover amd64 and arm64:

Family System version Catalog version
d12 Debian 12.15 20260909.2596.1
d13 Debian 13.7 20260914.2601.1
u22 Ubuntu 22.04.5 20260913.0.0
u24 Ubuntu 24.04.5 20260911.0.0
u26 Ubuntu 26.04.1 20260918.0.0

Debian keeps the offline XFS tools and generated en_US.UTF-8 locale, with C.UTF-8 as the default. Ubuntu keeps Canonical’s original image bytes; deployment accounts and networking are configured by cloud-init. Existing VMs and explicitly pinned image versions keep their original bases. See Images for repository and update behavior.

Install or upgrade

curl -fLO https://github.com/pgsty/farrow/releases/download/v0.8.0/install.sh
chmod +x install.sh
FARROW_VERSION=0.8.0 ./install.sh
export PATH="$HOME/.local/bin:$PATH"
farrow version

For an existing lab, review farrow plan and then run farrow up from its inventory directory. On first use, run farrow up in a terminal to prepare the host and create the default lab.

Farrow remains pre-1.0 and uses GitHub’s pre-release channel; keep the explicit FARROW_VERSION. The release includes macOS/Linux amd64/arm64 archives, Linux DEB/RPM packages, checksums, SBOMs, the installer, and a Homebrew formula. Other installation methods are in the Quick Start.

start still powers on existing nodes; up applies the inventory and retries unfinished guest setup. No separate repair command is required. The existing test-data reset policy is unchanged: confirmed unusable test filesystems can be cleared, including persistent data disks, with an explicit data-loss notice. Missing devices, failed probes, busy mounts, or host I/O errors do not authorize formatting; root disks and host shares stay outside that recovery path.

Validation and limits

Four hosts completed the seven-system pro path: two macOS arm64/HVF hosts and two Linux amd64/KVM hosts, each with Rocky Linux 9.8/10.2, Debian 12.15/13.7, and Ubuntu 22.04.5/24.04.5/26.04.1. The baseline candidate 6d7870e performed clean initialization from the LAN repository. Runtime candidate 1c054a0 then passed in-place installation, healthy repeated up, stop/start, two rounds of guest SSH, data-disk access, Ansible configuration reads, and control-node SSH. Both Macs also passed Ansible ping on all seven nodes. VM UUIDs, image identities, and healthy root/data disk paths and inodes were retained. The temporary acceptance VMs were subsequently cleaned up.

The following are single measurements, not a performance distribution. The first up includes image download:

Host Platform Clean first up at 6d Healthy up at 1c Existing-disk start at 1c
m0 Linux amd64 / KVM 117.915 s 3.924 s 36.944 s
m1 macOS arm64 / HVF 86.309 s 1.745 s 39.639 s
m3 Linux amd64 / KVM 98.443 s 2.169 s 44.068 s
m5 macOS arm64 / HVF 87.946 s 1.467 s 38.162 s

The release tag points to 320a32afa8f6fca02592215aa0d5607ca4e852b2, which changes only README and release notes relative to the tested runtime. Complete local make check and release archive/package verification passed. The source CI, independent packaging snapshot, and tag workflow all passed; the tag workflow produced 20 release assets, including 19 checksummed payloads. The release is public on GitHub’s pre-release channel. All 20 anonymous downloads returned HTTP 200; their full SHA-256 digests match the GitHub API and inspected draft, and all 19 payloads match checksums.txt.

The UX audit and image refresh record preserve the earlier regression, image-boot, and upgrade evidence.

Both official image repositories serve the same signed Catalog as the release. An isolated farrow update against each endpoint verified its signature and activated revision 2026092001. All ten new image objects at each endpoint returned HTTP 200 with matching content lengths; this was not a fresh full-body hash check of every public qcow2.

The public installer completed isolated user-directory installations on macOS arm64 and Linux amd64. Both CLIs reported 0.8.0 / 320a32a, and the installed CLI/helper bytes matched their verified public archives. The Linux download used a temporary SSH loopback forward to the existing proxy, removed afterward. Default installations and VM/network state were unchanged. These checks verify binary delivery; fresh host setup and VM boot through the public installer remain untested.

The Homebrew tap update provides 0.8.0 with all four archive checksums matching the public release. Local formula checks, strict online audit, and native arm64 brew fetch passed. Homebrew CI also passed its metadata, updater, style, platform, and audit checks on macOS and Linux. No new Homebrew install, upgrade, or brew test was performed.

This is a clean 6d baseline followed by a 1c lifecycle replay, not a second clean initialization at 1c. The Homebrew authentication-order regression fails before the fix and passes after it; its fresh formula-install path was not replayed natively after the fix. Native macOS setup used the verified LAN backend archive. Physical-host reboot, a complete Pigsty installation, and native macOS amd64 or Linux arm64 operation remain outside this run.

macOS directory sharing remains unavailable with the tested QEMU directory descriptor behavior. The new preflight improves diagnosis; it does not add sharing support. The pro inventory used no host shares. A missing control-node guest private key is now reported even if an old ready marker exists, but automatic private-key reinjection is still not implemented. Management SSH can remain usable while peer SSH carries that limitation. See Status for the full dated matrix.

3.2 - Farrow 0.7.0: simpler test labs and automatic recovery

A shorter first run, compact progress, independent guest setup, and recovery through up.

Farrow 0.7.0 makes local test labs easier to start and recover. Repeat farrow up to finish interrupted work, retry incomplete guest setup, and refresh older guest helpers without restarting running VMs.

What changed

  • A shorter first run. Interactive up can create the default inventory, prepare missing host tools, and restore an intact inactive Farrow network. Short checks stay quiet; long work shows progress and a compact final result.
  • Usable guests stay available. Data disks, shares, guest hostnames, node-to-node SSH, and private networking initialize independently. Optional failures report specific limitations while working management SSH remains available. Healthy stages are skipped on subsequent up calls.
  • Test disks recover automatically. Working filesystems are reused; unrecognized or confirmed damaged filesystems are reset and mounted again. The result explicitly reports discarded data. Probe errors, missing devices, busy mounts, and backend I/O errors do not trigger formatting.
  • Fewer manual fixes. Unwritable shares fall back to read-only and retry after permissions are corrected. Occupied automatic SSH ports are reassigned for stopped guests. Interrupted image transfers resume, and official repositories can fail over without bypassing digest verification.
  • Clearer output and state. Successful commands show a short summary; limitations are grouped, and JSON/YAML keep structured results. Guest warnings use a disposable cache outside the schema-2 VM documents and node artifact directories, so older releases can still read and manage the deployment.

Upgrade notes

Data disks are disposable test storage. up may clear a damaged filesystem, including one marked persistent. Persistence retains a disk across VM destroy/recreate; it does not preserve corrupt filesystem contents during recovery. Keep valuable data outside these test disks. Root disks and host shared directories are not reset by this recovery.

There is no separate repair command. Repeating up performs recovery; start continues to power on existing nodes without applying an inventory. --no-wait skips readiness and these guest recovery checks.

A usable guest with optional limitations returns exit 0. Automation that needs all configured features must inspect nodes[].warnings in JSON/YAML. Recovery actions, including data resets, appear in nodes[].repairs. Downgrading the CLI does not restore discarded data or revert installed guest helpers.

A pre-existing 0.6.0 bootstrap failure can already have deleted the staged control-node SSH key before installing it. up restores management access and independent setup, but reports control-ssh if that key is missing. It does not reinject private keys during an in-place retry. After reviewing disk effects with farrow plan, explicitly recreate the affected control node if peer SSH is needed.

Install or upgrade

curl -fLO https://github.com/pgsty/farrow/releases/download/v0.7.0/install.sh
chmod +x install.sh
FARROW_VERSION=0.7.0 ./install.sh
farrow version
farrow up

The release includes macOS/Linux amd64/arm64 archives, Linux DEB/RPM packages, the installer, checksums, SBOMs, and a Homebrew formula. It follows the existing pre-1.0 GitHub pre-release policy; specify FARROW_VERSION when installing.

Validation

The release commit is 9c6d4896d93733d1cb60a7e5d8591e9a06659c9d. It passed the source CI and the independent packaging snapshot before tagging. The tag workflow repeated the gates and produced 20 release assets: 19 checksummed payloads plus the checksum manifest. All 20 assets downloaded anonymously with HTTP 200 and matched the inspected bytes.

The public macOS arm64 and Linux amd64 installers installed the exact archive binaries and reported version 0.7.0 with this commit. On Ubuntu 26.04 amd64 with KVM/QEMU 10.2.1 and Ubuntu 24.04 guests, the recovery matrix exercised ext4/XFS corruption, retained disks, failed probes, busy mounts, read-only share fallback, and repeated healthy up without replacing the VM process. A public 0.6.0 bootstrap that failed its management-egress probe was resumed by 0.7.0 in 3.3 seconds; the existing data disk and UUID survived the probe failure. The old 0.6.0 binary still completed status, stop, start, and destroy after the upgrade. A fresh VM from the final 0.7.0 archive started without warnings, and a deliberately damaged disposable ext4 disk was reset by the public installer in 3.2 seconds with an explicit data-loss notice while the VM process stayed in place.

That interrupted 0.6.0 bootstrap may have deleted the staged control-node SSH key before installing it. Management SSH recovers, but peer SSH remains an explicit control-ssh limitation; the key is not reinjected during an in-place retry. Recreate the affected control node after reviewing farrow plan if peer SSH is required. Fresh 0.7.0 guests install the key normally.

macOS validation includes CLI smoke checks and cross-compilation. This release does not claim a new HVF guest replay, host reboot test, Linux arm64 run, or full Pigsty installation.

3.3 - Farrow 0.6.0: Ubuntu 24.04 and smoother local labs

Ubuntu 24.04 defaults, useful plans before setup, clearer status, and reliable expansion and recreation.

Farrow 0.6.0 defaults to Ubuntu 24.04 and improves the everyday loop of planning, starting, expanding, and rebuilding a local Pigsty lab.

What changed

  • Ubuntu 24.04 by default. New inventories and the embedded catalog use u24:stable. Catalog revision 2026090501 also includes the Debian 12/13 and Rocky Linux 8/9 updates already available in the official repositories.
  • Useful plans before setup. plan for Catalog images works without QEMU or host networking installed (registered local-* images still need qemu-img cache validation) and shows exact image versions, resource totals, pending starts, changed fields, disk effects, and commands that retain custom -f paths.
  • Readable status and errors. Status shows images, CPU, and memory; one damaged node no longer hides healthy peers. Corrupt state names the actual file and cause. Image digest failures return exit 7; SSH exit 255 passes through unchanged. --no-wait clearly reports that readiness was skipped.
  • Checks before disruption. Selected recreate detects conflicting peer changes before deleting disks. reload checks startup dependencies before stopping guests. Stop, destroy, and runtime cleanup handle deployment state consistently under the existing lock.
  • Guest names stay current. Starting commands and node removal refresh Farrow-managed guest hosts entries and control-node SSH configuration. Recreated peers remain reachable without clearing guest known_hosts. User SSH text and global option scope are preserved.
  • Fewer CLI surprises. Custom init paths produce usable next commands; presentation flags respect option values; malformed integer sizes and extra YAML documents are rejected without truncation. ALL_PROXY/all_proxy provides a fallback while respecting scheme-specific proxies and NO_PROXY.

Upgrade notes

Upgrading Farrow does not replace existing disks or change an explicitly selected image. If an old inventory relied on the implicit Debian 13 default, add vm_image: d13 under all.vars before applying it with 0.6.0. Review farrow plan before applying changes; farrow start uses the applied state.

CPU and memory changes still use recreate: root and non-persistent data disks are replaced, while persistent data disks are retained. --no-wait skips both readiness and guest metadata refresh; a later farrow up completes them. Scripts should use --json or --yaml instead of parsing status columns; partial status results include healthy nodes and a failures array, with exit 5.

Install or upgrade

curl -fLO https://github.com/pgsty/farrow/releases/download/v0.6.0/install.sh
chmod +x install.sh
FARROW_VERSION=0.6.0 ./install.sh
farrow version
farrow doctor

The release also includes four platform archives, amd64/arm64 DEB and RPM packages, and a Homebrew formula. As a pre-1.0 release it keeps the GitHub pre-release flag, so the installer needs the explicit version above. See the Quick Start.

Validation

The lifecycle and UX changes passed two adversarial Claude Code Fable 5.1 reviews at xhigh effort, plus the complete local make check gate. An isolated macOS arm64/HVF lab exercised Ubuntu 24.04 boot, scale-out, control-to-peer SSH, stop/start, reload, recreate, partial status failures, and scale-in. The final guest SSH scope correction also passed effective OpenSSH configuration tests.

The tag workflow repeats source checks and verifies archives, packages, SBOMs, installer, formula, release metadata, and checksums. These checks do not imply a new Linux-host VM replay, host-reboot test, or complete Pigsty installation.

3.4 - Farrow 0.4.0: one command, working data disks, one voice

A first run that is one command, a default data disk that works on every image, readiness failures that name the cause, and one output style across the CLI.

Farrow 0.4.0 was the public pre-1.0 release superseded by 0.5.0. It makes the first run one command, fixes the default data disk on Debian and Ubuntu images, and gives every command the same output style. The Pigsty Inventory format, the fixed-IP deployment model, the state layout, and the embedded Catalog revision 2026082903 are unchanged.

What changed

  • On a terminal, farrow up runs farrow setup itself when the fixed-IP network has never been installed, shows the setup plan, asks before the privileged step, and then continues. farrow init points at farrow up.
  • vm_disks[].fs defaults to auto: a blank disk is formatted XFS when the guest has mkfs.xfs and ext4 otherwise, the same choice Pigsty’s Vagrant flow makes. The old xfs default failed on Debian and Ubuntu images, which ship without xfsprogs. Deployments created with the old default are not reported as drift and their persistent disks stay compatible.
  • The guest error marker carries the failing command’s last message, so up reports guest bootstrap failed during data-disks: xfs requested but mkfs.xfs is unavailable instead of an exit status.
  • Lifecycle commands and status print a node table and, after up, a next: farrow ssh <node> hint. plan and validate print one line when nothing changes; image list, network status, doctor, and preflight errors use plain sentences without machine codes; spec hash and other internals moved to --json. Errors about an unknown node list the nodes.
  • farrow ssh <node> -- 'df -h /data; id' passes the remote command exactly as OpenSSH does.

Upgrading

A d13, d12, or Ubuntu node created by 0.3.0 or earlier whose /data never mounted needs one farrow recreate <node>; the disk is then formatted ext4 on those images and XFS on Enterprise Linux images. Automation that runs up on an unprepared host without a terminal still needs farrow setup --yes first.

Verification boundary

Source commit 8ecb8476c7dbc934d8cbbee935ac53884d00fcdb passed the complete local source gate: unit and race tests, vet, Staticcheck, deadcode, errcheck, govulncheck, shell and module checks, four target builds, the image-pipeline and installer boundaries, and dependency licenses. The tag workflow repeated those checks and built and verified every archive, native package, SBOM, and the installer before the Release was made public.

The new first-run path (up running setup) is covered by unit tests and was not replayed on a fresh host before this release. The dated macOS arm64/HVF and Ubuntu amd64/KVM evidence remains listed on the Status page; source, package, release, and native-host evidence remain separate gates.

Install or upgrade

Download the installer and assets from the Farrow 0.4.0 GitHub Release:

curl -fLO https://github.com/pgsty/farrow/releases/download/v0.4.0/install.sh
chmod +x install.sh
FARROW_VERSION=0.4.0 ./install.sh
farrow version
farrow doctor

Homebrew formula and amd64/arm64 DEB/RPM packages are attached to the same pre-release. Existing deployment and Catalog state remains readable.

3.5 - Farrow 0.5.0: explicit disposal, explicit repositories, reproducible images

A no-confirmation whole-lab purge, explicit global and China repository selection, no hidden artifact fallback, and an eight-target official-image candidate pipeline.
Note

This page describes 0.5.0. Official mirror failover was added in 0.7.0, and the unreleased 0.9 candidate removes the rm alias. Use current CLI guidance for your installed version.

Farrow 0.5.0 was the public pre-1.0 release superseded by 0.6.0. It adds an explicit command for disposable labs, makes repository geography an operator choice, and adds a reproducible path for preparing the next official guest images. The Pigsty Inventory contract, deployment state format, and embedded Catalog revision 2026082903 are unchanged.

What changed

  • farrow purge (alias farrow rm) removes the complete deployment, persistent data disks, deployment keys and state, and the default SSH fragment without confirmation. The verified image cache and host-global network remain. Absence is idempotent, while unidentifiable residual node artifacts still fail closed.
  • Released binaries use https://repo.pigsty.io/farrow by default. Long-only --mirror selects https://repo.pigsty.cc/farrow; --repo remains the highest-precedence override, followed by --mirror, FARROW_REPO, and the global default. Both official roots keep canonical signed-Catalog trust.
  • Catalog upstream URLs are provenance, not a fallback. A selected repository must contain the exact Catalog-named qcow2 or the pull fails with guidance to choose another root or import a local image.
  • The source tree now has a digest-pinned offline builder for Debian 12/13 and Rocky Linux 8/9 on amd64/arm64. It records the exact package closure, SBOM, provenance, and testing manifest, and can assemble an unsigned candidate repository for later native smoke and signing review.
  • The pinned source/release toolchain moves to Go 1.27.1, GoReleaser 2.18.0, golangci-lint 2.13.2, and current selected Go modules.

Image boundary

The eight-target matrix fixes concrete guest prerequisites: Debian 12/13 gain the XFS userspace needed for explicitly XFS-formatted data disks; Rocky Linux 8 gains /usr/bin/python3, working SSH drop-in inclusion, and clean interface naming state; Rocky Linux 9 receives the same legacy-network cleanup.

Those are candidate-build inputs, not newly published Catalog artifacts. Every result remains unsigned and testing until native boot/readiness smoke, repeat-build comparison, production signing, upload, and Catalog publication complete.

Upgrade and disposal

No state, Inventory, or Catalog migration is required from 0.4.0. Existing cached images remain usable. New downloads use the global repository unless --mirror, --repo, or FARROW_REPO selects another root.

purge is deliberately non-interactive and irreversible for deployment disks and keys. Continue to use confirmed farrow destroy when preserving persistent disks or removing selected nodes.

Verification boundary

Release source commit fc85b65ff6a24b0933b56ae1179be9ada2ba91b1 passed the complete local source gate: module and shell checks, unit and race tests, vet, Staticcheck, deadcode, errcheck, govulncheck, four target builds, simulated image-pipeline boundaries, installer tests, and exact dependency-license verification. GoReleaser 2.18.0 also accepted the release configuration.

The tag workflow independently repeats those checks and builds and verifies every archive, native package, SBOM, formula, installer, release metadata file, and checksum before the pre-release is published. No new native VM lifecycle replay or published-image claim is inherited from these source gates.

Install or upgrade

Download the installer and assets from the Farrow 0.5.0 GitHub Release:

curl -fLO https://github.com/pgsty/farrow/releases/download/v0.5.0/install.sh
chmod +x install.sh
FARROW_VERSION=0.5.0 ./install.sh
farrow version
farrow doctor

The same pre-release includes the Homebrew formula and amd64/arm64 DEB/RPM packages.

3.6 - Farrow 0.3.0: explicit catalogs and actionable readiness

Explicit image-catalog updates, per-node bootstrap diagnostics, native guest interface names, and a smaller CLI.

Farrow 0.3.0 was the public pre-1.0 release superseded by 0.4.0. It removes implicit Catalog refreshes, turns guest bootstrap failures into actionable per-node results, and simplifies the CLI without changing the Pigsty Inventory or fixed-IP deployment model.

What changed

  • up, plan, and ordinary image commands use one active local Catalog snapshot and never fetch Catalog metadata implicitly. farrow update explicitly fetches the configured repository; image sync activates an exact URL or file.
  • Guest bootstrap writes an atomic failure stage. Partial operations report every failed node, stage, and error, and readiness failures point directly to farrow logs <node>.
  • Already-running guests can be rechecked without restarting QEMU. A partial lifecycle still rebuilds the SSH client configuration from every committed node.
  • Netplan matches deterministic MAC addresses without renaming interfaces. vm_disks[].fs: auto prefers XFS and falls back to ext4 when necessary.
  • The redundant ss command and ambiguous root/flag shorthands are removed. image reset replaces reset-manifest, which remains an alias.

Verification boundary

Source commit da6d02426da93c677c94c67fec4eb4fcecf4766a passed the complete local source gate and a full GoReleaser snapshot: unit and race tests, vet, Staticcheck, govulncheck, four target builds, image-pipeline and installer boundaries, archive/package parity, dependency licenses, SBOMs, and native Linux package verification. The tag workflow repeated those checks before the Release was made public.

This release does not claim a new native VM replay. The dated macOS arm64/HVF and Ubuntu amd64/KVM evidence remains listed on the Status page; source, package, release, and native-host evidence remain separate gates.

Install or upgrade

Download the installer and assets from the Farrow 0.3.0 GitHub Release:

curl -fLO https://github.com/pgsty/farrow/releases/download/v0.3.0/install.sh
chmod +x install.sh
FARROW_VERSION=0.3.0 ./install.sh
farrow version
farrow doctor

Homebrew formula and amd64/arm64 DEB/RPM packages are attached to the same pre-release. Existing 0.1/0.2 deployment and Catalog state remains readable; Catalog refresh is now always explicit.

3.7 - Farrow 0.2.0: selected convergence and release integrity

VPN-aware network preflight, truly selected scale-out, committed-state integrations, checksum-verified multi-platform artifacts, and the 0.1.0 upgrade boundary.

Farrow 0.2.0 was the public pre-1.0 release superseded by 0.3.0. It keeps the Pigsty inventory and on-disk deployment format introduced by 0.1.0 while fixing the network and selected-convergence boundaries found during the final native replay.

What changed

  • A less-specific VPN exclusion such as 10.0.0.0/8 no longer blocks Farrow’s owned 10.10.10.0/24; equal or more-specific foreign routes, overlapping interfaces, occupied addresses, and a missing owned route still fail closed.
  • farrow up <node> downloads and prepares only the selected node. Desired inventory peers without state appear as absent; SSH/hosts/provisioning, UUID and port allocation, lifecycle commands, and persistent-disk checks use the committed node set without losing future scale-out intent.
  • New guests write # farrow-deployment-host and remove both that marker and the released # farrow-project-host marker before adding current host rows.
  • Command cancellation, structured output, confirmation, reload, diagnostic redaction, installer retention, and the smaller dependency graph from the unpublished intermediate work are included directly in 0.2.0.

Native and release evidence

The exact source commit completed a macOS arm64/HVF replay with MonoProxy active: selected u24-1 create/SSH/stop/start, incremental cached el9-1 create, two-node SSH, five explicit absent peers, and whole destroy all passed. On Ubuntu 26.04 amd64/KVM, the current Linux binary audited an existing four-node deployment and reached its control guest without mutation.

Local make check, source CI, and the complete packaging workflow passed. The tag workflow built four archives, amd64/arm64 DEB and RPM packages, SPDX SBOMs, Homebrew formula, installer, checksums, and release metadata. GitHub Actions uploads those verified CI outputs to a draft for review before public release, without a separate application signature or provenance bundle.

The signed image Catalog remains revision 2026082903 with 9 families and 27 architecture artifacts. The default repository remains https://repo.pigsty.cc/farrow; repo.pgsty.com/farrow is an independently verified source/alternate endpoint, not the compiled default.

Install or upgrade

Download install.sh and the assets from the Farrow 0.2.0 GitHub Release:

chmod +x install.sh
FARROW_VERSION=0.2.0 ./install.sh
farrow version
farrow doctor

0.1.0 deployment state remains readable. Run farrow status while retained VMs are live to converge any pre-release process-birth identity. Existing guests adopt the new /etc/hosts marker when recreated.

Because Farrow is still below 1.0, GitHub labels 0.2.0 as a pre-release.

3.8 - RC6 development candidate: owner-scoped Tier-1 delivery

Exact RC6 identity, four requested native product passes, durable network transactions, reproducible local archives, and the boundary that keeps this candidate unpublished.
Caution

Pre-Barn historical record. It preserves the predecessor candidate’s exact identity and does not establish support for current Barn bytes or paths. See current status.

Piglet 1.0.0-rc.6 is the owner-scoped local development candidate for the single native-QEMU path. It closes the requested Quick and exact four-node full scenarios on both Tier-1 hosts and adds durable privileged-network transactions. It is deliberately not a public release.

Warning

No Homebrew operation, public tag, remote push, GitHub Release, package repository, production signature, attestation, or support commitment was created. The hashes below identify retained local artifacts; this site does not provide them as downloads.

Frozen identity

Field RC6 value
Version 1.0.0-rc.6
Source commit 7db733184463cc189ffa738335c213fc9a2982de
Go go1.27.0
Source epoch 1787657920
Build timestamp 2026-08-25T11:38:40Z
Channel development
Signature / attestation false / false
Exact full profile SHA-256 912fea61bf1602c2a437570561a6ab4d0a5a8c152695147ad9e96ae831bc9336

Four requested product scenarios

Host Scenario Result Guest contract
macOS arm64 / HVF Quick PASS Ubuntu 24.04.4, dba UID/GID 88, 2 vCPU, 64 GiB root, 64 GiB /data
Linux amd64 / KVM Quick PASS same contract
macOS arm64 / HVF exact full PASS .10–.13, UID 88, 64 GiB roots, 128 GiB data disks, 2/1/1/1 vCPU, four-way peers
Linux amd64 / KVM exact full PASS same contract

All eight final full-profile guests reported Ubuntu 24.04.4. The projects were destroyed through Piglet after assertions; shared image caches, project markers, and keys were intentionally retained.

Durable native networking

Network install and uninstall now use one root-owned strict-prefix transaction:

  • root planning returns an owner/host/prestate-bound token;
  • apply replans under the host-global lock and accepts only that token;
  • a typed, fsynced journal is published before mutation;
  • each fixed action is checkpointed after exact postcondition verification;
  • interrupted work blocks ordinary private mutation until an explicit forward or rollback recovery plan is separately token-approved.

Darwin completed a real interrupted forward recovery and ended protected and healthy in default host mode. Linux completed real install, rollback/retry, four-node operation, uninstall, and host restoration before the final adversarial patch. That patch closed socket-state canonicalization, overly broad systemd enablement, NetworkManager ordering, and field-scoped recovery effects, then passed consolidated source/race gates.

Per the owner’s final direction, no VM or network test ran after that last patch. Therefore the post-audit Linux install/uninstall/reinstall replay is explicitly not run. This page does not upgrade source/race evidence into a native result.

macOS shared mode and subnet conflicts

The supported default remains socket_vmnet host mode. Shared mode passed a two-node contract on a proven-free alternate subnet, but it is an explicit fallback and not an isolation boundary.

The historical default-subnet failure was VMNET_SHARING_SERVICE_BUSY (1009). VirtualBox was a plausible contaminant, not a proven owner of that incident. Immediately before the final migration, the observed subnet interface was the older Piglet-created bridge100. Preflight now rejects foreign interfaces by identity instead of adopting a matching .1/24 address. Operators can remove the confirmed owner or move the whole lab to one warned canonical RFC1918 /24; Piglet never changes only the guest addresses or selects a random escape subnet.

Reproducible local archives

Two independent local RC6 output trees passed the strict release verifier and were byte-identical for the four archives, checksums, release metadata, and formula:

Archive SHA-256
Darwin amd64 1295288ff198b53fcb761a6e8794087d75a46105fc19980fabcd44f0c70fb9ef
Darwin arm64 308310b0f2d179f98c8be78ea09f89d226167072c936387bc42d717a922ec0c6
Linux amd64 547a61f6cc0768071df349cbf5c17d7ddfe3ab3cea59e6b4026e3e3e616a5550
Linux arm64 afc9ce1043d377cc3b4ef8bdf77826a8139a8c839685025853e8bee8100c6a2e

The formula is an inert build artifact. Earlier candidates exercised offline RPM/DEB consumption and ephemeral Cosign/SLSA round trips, but those results are mechanism evidence and are not relabeled as RC6 publication/signing.

What remains public-GA work

  • literal reboot persistence on both Tier-1 hosts;
  • current native smoke on macOS amd64 and Linux arm64;
  • the deliberately deferred Linux final network replay;
  • remaining image normalization, byte-reproducibility decision, hosting, and active/standby manifest-key custody;
  • production release identity, signing/attestation, published Homebrew and Linux package channels, and clean-host consumption;
  • a durable owner-operated macOS HVF runner and explicit release authorization.

See the current tutorial, design, and status for the maintained boundary.

3.9 - Development snapshot: the Go 1.27 product surface

Quick and four-node private semantics, schema-3 owned profiles, Pigsty inventory integration, persistence, state migration, and verified release mechanisms.
Caution

Pre-Barn historical record. Names, commands, paths, hashes, and claims on this page describe the predecessor snapshot only. Use the current Barn status and guides for present behavior.

Piglet’s 2026-08-24 source snapshot has moved well beyond an initial QEMU spike. It now presents one coherent local-VM product: zero-configuration Quick, fixed-address private labs, 13 Piglet-owned profiles, an audited Pigsty inventory boundary, explicit persistence/state migration, diagnostics, and a reproducible release toolchain.

It is still a development snapshot—not a stable release.

Note

This page is a historical 2026-08-24 snapshot. A later predecessor candidate is archived separately; neither page is current Barn release evidence.

Warning

There is no public v1.0 tag, signed production artifact, Homebrew tap, or DEB/RPM repository. All embedded image records remain testing. Local packages and signature round trips prove mechanisms, not production custody.

One native runtime

Piglet directly drives native QEMU through HVF on macOS and KVM on Linux. It owns strict specification resolution, image/qcow2 verification, pure-Go NoCloud CIDATA, QMP/process identity, SSH readiness, atomic state, journals, events, repair, and bounded deletion. QEMU runs as the invoking user and never silently falls back to TCG.

There is no second provider/runtime path and no arbitrary QEMU-argument escape.

Quick on both Tier-1 hosts

The retained Go 1.27 Quick runs cover the public no-YAML path on macOS arm64 and Linux amd64. The contract is meta/dba, 2 vCPU, 4 GiB memory, 64 GiB root, sparse 64 GiB /data, user NAT, SSH, and four loopback forwarding conventions.

The product supports plan, up, status, SSH/exec, stop/start/restart, drift classification, guarded recreate/destroy, no-wait, persistent-disk retention, key retirement, logs, repair, and redacted debug bundles.

Those forwards do not install applications. Pigsty/PostgreSQL bootstrap remains a separate integration gate.

Private labs and host networking

Private mode now has public preflight/status/install/uninstall flows on both Tier-1 host families. macOS uses pinned socket_vmnet v1.2.2 with host mode by default and evidence-backed shared/FD paths. Linux uses a reversible systemd-networkd/NetworkManager/bridge-helper transaction. Both keep QEMU unprivileged and block uninstall while the global lease is active.

The default 10.10.10.0/24 can be replaced by one explicit canonical RFC1918 /24. Profile, host install, lease, state, node addresses, and Pigsty inventory must move together. No random collision escape is chosen.

Retained four-node full and MinIO runs exercised fixed IPs, control-only lateral SSH, management internet, storage identity, stop/start persistence, and clean destroy on both Tier-1 paths. Earlier runs also cover crash recovery and 30/30 soak. The MinIO profile runs validate 16 VM data disks, not the MinIO application.

Schema-3 owned profiles and Pigsty inventory

The 13 embedded profiles contain 85 nodes, all using dba. Ordinary nodes have one 128 GiB /data; MinIO nodes have four 32 GiB disks. Catalog schema 3 owns scalability, image policy, and Pigsty inventory binding, with direct and build_subset modes.

piglet pigsty inventory reads a real Pigsty source tree, classifies and validates host/VIP/admin/service address semantics, rebases a coordinated custom subnet, and can atomically publish a mode-0600 marker-owned output. pigsty-vm exposes the same profile, network, lifecycle, and inventory contract through a small typed environment.

The wrapper has no provider fallback. Operational rollback means a prior verified Piglet artifact plus matching state backup.

Persistence, upgrade, and automation

Disks marked persistent: true survive ordinary destroy and compatible recreate. The current safety contract requires an independent TTY phrase or destroy --force --delete-persistent --yes-delete-persistent; project keys have a separate default-dry-run project purge-keys --yes boundary.

Schema 0→1 migration is stopped-only, no-lease, backup-first, atomic, and explicit through project upgrade-state --dry-run|--yes. Newer schemas are refused rather than downgraded.

Private node selectors, --no-wait, stable JSON responses, typed exit classes, shell completion, SSH config, marker-owned hosts blocks, per-node logs, and redacted support bundles complete the current operator/automation surface.

Images and release mechanisms

The formal embedded image set is el9, el10, d12, d13, u22, u24, and u26 on both Tier-1 native architectures. Retained matrix records report 7/7 per architecture; EL8 was retired from v1 because its arm64 kernel cannot satisfy the tested native HVF contract. The entries remain testing pending a production image channel and custody.

The source tree can build and verify four native archives, a Homebrew formula, Linux amd64/arm64 RPM and DEB packages, checksums, SPDX SBOMs, a combined release assembly, and Cosign signature/SLSA-provenance positive and tamper tests. Isolated package install/verify/remove and two-run reproducibility passed for the tested snapshots. The checked-in release workflow has not executed for a real tag.

Evidence must follow exact bytes

At this snapshot, catalog schema 3 and inventory integration had changed the checked-in profile/resolved digests after the retained full/MinIO runs, so exact-current native refresh was still required. Custom-subnet hosts publishing, applied storage.data_root/ssh.wait_timeout, and generic Quick users were also open.

RC6 later closed those implementation and exact-profile gaps. Historical native runs remain valid only for the bytes and behavior they actually exercised.

What remains before v1.0

The snapshot’s exact-profile, Pigsty-bootstrap, and Rocky 9.8 private-host gates were later exercised. The current remaining gates are production image/manifest/release custody, durable runner ownership, literal reboot recovery, Tier-2 native smoke, published package consumption, and a real signed/attested tag-bound release.

See the current tutorial, design, and status for the maintained boundary.