Testing a change
Validating a branch
Validating a branch needs the branch's own instructions on a server, and those never go near production. Keep a second operations clone for test servers only:
git clone <hostwarden-url> hostwarden-test
cd hostwarden-test
git switch <branch>
bin/hostwarden-init
Give it a workspace of its own — never --clone of the production
one — and list your production hosts in its memory/blacklist.md.
Off main it does not auto-update; git pull brings the branch's
next push, and bin/hostwarden-update --unpin makes it follow
main.
Trying a command
Trying a command needs no server at all when a container answers it:
whether a flag exists in this release, what a package is called,
what a config test prints. scripts/lab.sh runs one per family —
debian, ubuntu, rhel (AlmaLinux), fedora, suse (openSUSE Leap),
alpine — from the official image of the current stable release, with
docker or podman (OrbStack brings docker on macOS;
HOSTWARDEN_LAB_ENGINE picks one where both are installed):
scripts/lab.sh exec debian -- apt-get -s install nginx
scripts/lab.sh list
scripts/lab.sh down
A lab container is neither a server nor local mode, so a development
session uses it directly. Each worktree gets its own, labelled with
the worktree's name and a checksum of its path, and down removes by
that label alone. It also self-expires: up gives it a fixed
lifetime, HOSTWARDEN_LAB_TTL seconds (default 6h), and the engine
removes it on its own once that ends, whether or not down was ever
run — a command still running at that moment is killed with it. They
run without a published port, a host path, the engine's socket or any
extra privilege. The lab never starts the engine; start OrbStack,
Docker Desktop or podman machine yourself.
The mode guard decides what a development session may do to the local container engine:
- Allowed: reading, pulling, building, running and creating on
the local engine;
scripts/lab.sh execandscripts/lab.sh down, which touch the lab's own containers only. - Denied: a run that asks for host access or publishes a port; a
build that writes its result to this machine; another engine by
--context,--hostorDOCKER_HOST;exec, and every command that changes containers, images or volumes.
On Linux the engine runs as root; on macOS a bind mount reaches your home — which is why a run that asks for host access is denied.
Lab VMs
A container cannot answer for systemd services, the firewall, kernel parameters, a reboot or the SSH pipeline, and there is no container for FreeBSD or macOS. For the Linux cases, a lab VM is a test server of the test clone above:
scripts/lab.sh vm up debian --ops ~/hostwarden-test
It uses OrbStack or Lima, whichever is installed, and refuses a
--ops that is not an operations clone, is the checkout the worktree
came from, or has no host on its blacklist. OrbStack machines mount
your Mac's home by default; the lab creates them --isolated,
without that mount, and installs sshd with your public key for root,
so the host is <name>.orb.local. Lima's templates mount your home
too; the lab creates them --mount-none, and the host is
lima-<name> once ~/.ssh/config has Include ~/.lima/*/ssh.config.
The development session never uses the VM — the mode guard denies
orb, limactl shell and lima commands inside one — and hands its
question to a session in the test clone instead (see
Asking an operations session).
The guard also denies creating, starting, stopping, deleting or
changing a VM directly: scripts/lab.sh vm up creates and starts
one without your home mounted, and scripts/lab.sh vm down
deletes the VMs that worktree created, and no other.