Building
Astromesh OS is built with mkosi and tested with QEMU. This page covers building the image locally. There are two paths — a Docker container or a WSL2 + KVM dev-loop — but in both cases the real gate is CI.
Prerequisites
Section titled “Prerequisites”The entire build toolchain — mkosi, QEMU/KVM, dm-verity, the UKI tooling — is Linux-only. You cannot build the image natively on Windows or macOS. On those hosts you build inside Linux, either a privileged Debian container (Docker) or a WSL2 Debian instance with KVM.
Docker path (Windows / macOS)
Section titled “Docker path (Windows / macOS)”Build inside a privileged Debian trixie container. Bind-mount the source tree, install the toolchain, build the runtime .deb first, then build the image:
docker run --rm -it --privileged -v "$PWD":/work -w /work debian:trixie bash# inside the container:apt-get update && apt-get install -y mkosi qemu-system-x86 git python3 python3-pip# build the runtime .deb first (see .github/workflows/phase0-ci.yml), then:PHASE0_MODE=stub mkosi buildThe --privileged flag is required because mkosi needs loop devices to assemble the rootfs. PHASE0_MODE=stub builds with a local stub provider so the boot-to-agent check can run without a real frontier API key.
WSL2 + KVM local dev-loop
Section titled “WSL2 + KVM local dev-loop”For fast iteration without waiting on CI (and without the TCG flakiness of GitHub-hosted runners), reproduce the boot/update gate locally in WSL2 with KVM.
One-time setup (from the Windows host)
Section titled “One-time setup (from the Windows host)”wsl --install -d Debian --no-launch# enable systemd + drvfs metadata, then apply:wsl -d Debian -u root -- bash -lc "printf '[boot]\nsystemd=true\n\n[automount]\noptions=metadata\n' > /etc/wsl.conf"wsl --shutdown# install the same toolset CI uses:wsl -d Debian -u root -- bash -lc "apt-get update && apt-get install -y mkosi systemd-ukify systemd-boot systemd-boot-efi mtools dosfstools ca-certificates qemu-system-x86 qemu-utils ovmf curl rsync git python3"# verify KVM is exposed (needs nested virtualization, default on Win11):wsl -d Debian -u root -- ls -l /dev/kvmIf /dev/kvm is missing, add nestedVirtualization=true under [wsl2] in %UserProfile%\.wslconfig and run wsl --shutdown.
Fetch the runtime .deb once
Section titled “Fetch the runtime .deb once”The runtime .deb rarely changes — it depends only on runtime.pin. Fetch the latest CI build once into dist/ (run on the Windows side, where gh is authenticated):
gh run download -n astromesh-deb -D distRun the loop
Section titled “Run the loop”Run as root in WSL (mkosi needs loop devices). The source of truth stays on D:\; the harness rsyncs into a native ext4 path (~/astromesh-build) and builds there, because drvfs cannot host a mkosi rootfs build:
wsl -d Debian -u root -- bash /mnt/d/monaccode/astromesh-os/tests/local/dev-loop.sh updateDev-loop targets
Section titled “Dev-loop targets”| Target | What it does |
|---|---|
build | Build the image only |
boot | Single boot, asserting immutability and health |
update | Full A/B v1→v2 update gate (default) |
inspect | Compare the UKI roothash against the on-disk verity PARTUUIDs |
clean | Clean build artifacts |
Bumping the pinned runtime
Section titled “Bumping the pinned runtime”The astromesh runtime baked into the image is pinned in runtime.pin:
# runtime.pinASTROMESH_REF=<commit SHA of monaccode/astromesh>To move the image to a new runtime, edit ASTROMESH_REF to a new commit SHA of monaccode/astromesh, then re-run CI. The image is reproducible from that exact ref, and CI fails if it cannot resolve it. Because the runtime .deb depends only on runtime.pin, a bump is the trigger for rebuilding it.
Next steps
Section titled “Next steps”- Architecture — what the build produces and why (verity, A/B, the 500 MB ceiling).
- Roadmap — the phase gates that each build must clear.