Automation and Guest Scripts
6 minute read
This guide shows how to drive Barn from unattended scripts and CI pipelines. Run all commands as the Unix user who owns the deployment, and pass the same -f <inventory> and BARN_HOME across invocations.
Prepare a predictable lab
Keep your inventory file in version control and pin vm_image to an exact version (such as vm_image: u24@20261017.0.1) so catalog updates never alter your base image mid-pipeline. Passing -f explicitly also prevents first-run setup from relocating an unedited default template to a different subnet. If you use a custom image repository, activate its catalog first with barn update --repo URL and pass the same --repo to setup and up.
Generate and validate the inventory before running host setup:
Once you have reviewed the host plan and ensured non-interactive sudo credentials (or a NOPASSWD policy) are available, prepare the host and bring up the lab:
For a generated inventory, barn init [template] --image <reference> writes all.vars.vm_image, so every node inherits the same image. References can be catalog aliases (el9), channels (u24:stable), or version selectors (u24@20261017.0.1). barn setup [template] --image <reference> also selects an image during generation, but rejects this generation flag when using an existing inventory.
--image/-I and --arch/-A share consistent spellings: barn init full -I u24 -A amd64 saves both choices in a new inventory; the same flags on validate, plan, up, reload, recreate, and resize only override desired state for that invocation. For example, preview barn plan -f barn.yml -I u24 -A arm64 --json, then use the same overrides when applying it. Setup’s -I/-A remain limited to template generation.
The same commands also accept --cpu/-C, --mem/-M, --scale/-S, and --disk/-D. Each specification follows CLI flags → nonempty BARN_* environment variables → inventory → defaults. Reuse the same flags and environment for validate, plan, and the operation that applies the plan.
Without an architecture flag, Barn uses BARN_ARCH, then inventory vm_arch, falling back to the host when unset; -A native overrides both and follows the host. Existing VMs require recreate to change image or architecture. For repeatable CI, save vm_image, vm_arch, and an exact image version; see the configuration reference.
barn setup --yes accepts the host-preparation plan without asking. On a terminal, up, start, restart, and reload show the same plan and ask once before installing packages or the Barn network; without a terminal they only report what is missing, so run barn setup --yes before them.
Validate JSON output alongside the exit code
Barn writes structured JSON/YAML payloads to stdout and human diagnostics to stderr. Because barn up returns exit code 0 when management SSH is ready—even if an optional stage such as a secondary data disk, Virtio-9p share, or peer SSH config reported a limitation (nodes[].warnings) or reformatted a damaged test disk (nodes[].repairs)—automation scripts should inspect the JSON payload alongside the exit code:
When a subsequent pipeline step requires ready guests, omit --no-wait on barn up (barn status --json reads cached state without re-probing guest SSH).
Exit codes and command-specific payloads
Pair CLI exit codes with each command’s JSON schema:
- Exit
2(usage): Missing inventory on first run, invalid flags, unknown image aliases, ordestroy/recreatewithout--yeswhen stdin is not a terminal (purgeruns without asking). - Exit
4(conflict): Inventory drift requiring explicit action (reason: recreate_requiredornodes_removed), applied state that changed during arecreatepreflight (reason: deployment_changed), or a deployment lock timeout (reason: deployment_busyafter waiting up to 10 minutes). - Exit
5(partial): Multi-nodeuporprovisionwhere some nodes succeeded and others failed—inspectnodes[]orresults[]before retrying. - Exit
7(integrity): A digest, signature, or identity check failed, including a catalog signature or signed revision that does not verify (reason: catalog_signatureorcatalog_equivocation). - Command-specific reports:
barn doctor --jsonexits0when host compute passes even if aclass: networkcheck reports an error; checkchecks[]andbarn network status --jsonbefore relying on the private bridge.barn sshandbarn execreturn the remote command’s exit status (or255on OpenSSH transport failure) and recordsuccess,exit_code,stdout, andstderrin--jsonmode.networkandhostsinstall/uninstallwithout--yesonly print the plan and exit0when stdin is not a terminal or the output is--json/--yaml; checkappliedin the result, or pass--yes.
Run single commands or batch scripts
Always place -- between the node selector and the remote command, and put Barn flags (--json, --verbose) before --:
Pass the program and its arguments as separate tokens to barn exec, using sh -c explicitly for pipes, redirection, or shell variables (see SSH passthrough and completion).
To run a health check or setup script across multiple running Linux nodes, save a local Bash script (a regular file or symlink to one, up to 4 MiB):
Execute it with barn provision:
Omitting node selectors runs the script on every node in the deployment (all target nodes must already be running). Barn streams the verified script bytes directly to Bash over SSH without writing a temporary script file in the guest, and records the script’s SHA-256 in the audit result.
- Concurrency and timeouts: Serial by default;
--parallelaccepts positive integers, with workers capped at the selected node count.--timeoutbounds the whole operation, defaults to1h, and accepts any positive duration.--sudouses non-interactivesudo -n. - Output capture and idempotency: Each node captures up to 1 MiB of
stdoutand 1 MiB ofstderr(settingstdout_truncated/stderr_truncatedwhen exceeded). Because partial runs leave completed guest changes in place, write idempotent scripts that are safe to re-run. - Exit codes:
provisionexits5when some nodes succeed and others fail, passes through a single target’s positive non-255exit code on failure, and exits1otherwise.
Pair the lab with Pigsty
Barn and Pigsty share the same Ansible YAML format. While barn init generates VM hardware topology, Pigsty provides complete service inventories (pigsty.yml) for PostgreSQL, Redis, and monitoring stacks. Provision the VMs with Barn first:
During barn up, Barn provisions the guest administrator account and installs the deployment private key on the control node designated by admin_ip, configuring its ~/.ssh/config so Ansible can reach all peer nodes over their fixed private IPs (see Security and Trust). Once barn up completes, SSH into the control node and run Pigsty’s deployment playbooks.