repo.yaml Is Intent; catalog.json Is Evidence
This essay explains the Linux image repository contract in Barn 1.1.0 (macOS guests manage Apple .ipsw restore images and APFS base images separately via barn mac).
A static VM image repository needs two kinds of metadata: human policy decisions (which version is :stable, which old releases are deprecated, what aliases map to each family) and physical file facts (exact byte size, SHA-256 digest, qcow2 virtual disk size). Maintaining both in a single hand-edited JSON file invites copy-paste checksum errors and buries policy changes inside noisy diffs.
Barn splits those two concerns into two distinct files: repo.yaml for human intent and catalog.json for machine-verified evidence.
repo.yaml: human-authored policy
repo.yaml (schema: 1) is checked into version control and edited by maintainers. It declares:
- Repository
revisionand globaldefaults(image,channel,arch,boot) - Distribution families and their short aliases
- Movable release channels such as
stable - Exact version keys and supported architectures (
amd64,arm64) - Boot mode (
uefiorbios), supportstatus,source_user, and immutable upstream provenance URLs
Crucially, repo.yaml never contains hand-copied byte counts, SHA-256 digests, or virtual disk sizes:
Because repo.yaml stays compact and free of generated hashes, pull requests clearly show channel promotions, deprecations, and provenance updates (see Image Repositories for a complete walkthrough and Linux Images for the current 2026110502 catalog).
Repository authoring and client verification are covered in Linux Images; offline candidate normalization is covered in Image Pipeline.
catalog.json: machine-verified artifact evidence
catalog.json (schema: 3) is generated by barn repo build from repo.yaml and the actual .qcow2 files on disk. For every (image, version, arch) variant, barn repo build:
- Validates
repo.yamlpolicy declarations (boot mode,source_user, support status, and upstream provenance). - Inspects the corresponding
images/<image>-<version>-<arch>.qcow2file viaqemu-img, rejecting backing chains, external data files, encryption, or unknown incompatibleqcow2feature bits. - Computes the exact file size, SHA-256 digest, and
qcow2virtual capacity, and atomically writescatalog.json.
Each artifact is identified by the immutable tuple (image, exact version, architecture) and stored under a human-readable filename:
Predictable filenames make it easy to inspect, mirror, or rsync a repository with standard Unix tools, while catalog.json and its minisign signature provide cryptographic integrity verification.
Three repository commands, three distinct roles
| Command | Role |
|---|---|
barn repo scan /srv/barn |
Read-only audit: reports tracked, missing, untracked, and unsafe files without modifying the repository |
barn repo build /srv/barn |
Strictly validates repo.yaml and every declared .qcow2 file, then atomically writes catalog.json |
barn repo verify /srv/barn |
Rebuilds the catalog in memory and verifies that it matches the published catalog.json byte-for-byte |
barn repo build never modifies repo.yaml or .qcow2 files, and barn repo verify catches any drift between repo.yaml, the .qcow2 files on disk, and catalog.json. When publishing a repository update, always upload the immutable .qcow2 files first, then publish catalog.json and catalog.json.minisig together so clients never see a catalog entry whose image file is not yet available.
Movable selectors, immutable resolved identities
In barn.yml or CLI commands, selectors like d13:stable, el9@9, and el9@9.8 provide convenient moving targets (comparing dot-separated version components as integers so 9.10 sorts after 9.9).
Once barn plan or barn up resolves a selector for a node, Barn records the exact version, architecture, byte size, and SHA-256 digest in committed state. Updating a channel in a future catalog never mutates an already created VM behind your back.
Transport security and catalog signatures
Barn separates transport selection from catalog trust:
- Official and HTTP repositories always require a valid detached signature (
catalog.json.minisig) verified by one of Barn’s embedded production Ed25519 public keys. - Custom local directory and HTTPS repositories explicitly selected via
--repoorBARN_REPOmay use unsigned catalogs when you control the local filesystem or HTTPS endpoint. - Per-repository anti-rollback: Barn tracks the highest accepted catalog
revisionindependently for each repository root, rejecting older revisions (unless--allow-downgradeis passed tobarn image sync) and rejecting different catalog bytes at the same revision number. - Defense in depth on every pull: Even after a catalog is accepted, every downloaded or cached image is checked against its catalog byte size, SHA-256 digest, and
qcow2structural rules before being marked read-only (0444) and used as a backing image for copy-on-write node overlays.
Independent trust domains across releases, apps, and catalogs
Barn keeps its three distribution trust domains distinct:
- CLI release archives and Linux packages are published on GitHub Releases with
checksums.txtSHA-256 manifests and SPDX SBOMs. - Native macOS
Barn.appbundles use Apple Developer ID code signing and notarization (or local ad-hoc signing when built from source). - Linux image catalogs are authenticated via offline Ed25519 Minisign keys (
catalog.json.minisig).
In Barn 1.1.0, the compiled default repository is https://repo.pigsty.io/barn, --mirror selects https://repo.pigsty.cc/barn, and --repo selects any custom root. The two official mirrors can fall back to each other when downloading .qcow2 artifacts—always verifying the exact same catalog byte size and SHA-256 digest—while catalog updates (barn update) and custom --repo repositories always read from their explicitly selected source.