| name | build-initrd |
| description | Initrd repack and guest binary management for Capsem. Use when adding new guest binaries, modifying capsem-init, changing the initrd repack process, or understanding which binaries get injected at boot vs baked into the rootfs. Covers the fast iteration loop, binary list, and how to add new guest binaries. |
Initrd Repack
just run automatically repacks the initrd before every boot. It cross-compiles guest binaries, injects them into the initrd, and capsem-init prefers initrd-bundled copies over rootfs copies at boot. This is the fast iteration loop (~10s) -- no full rootfs rebuild needed for guest binary changes.
Currently repacked binaries
| Binary | What it does |
|---|
capsem-init | PID 1 init script |
capsem-pty-agent | PTY-over-vsock bridge agent |
capsem-net-proxy | TCP-to-vsock relay for air-gapped HTTPS proxying |
capsem-mcp-server | MCP stdio-to-vsock relay for AI agent tool access |
capsem-sysutil | Guest suspend helper via vsock:5004; in-VM shutdown commands are disabled |
capsem-doctor | VM self-diagnostic suite (bash script) |
snapshots | Snapshot management CLI (Python, FastMCP client) |
diagnostics/ | pytest test files for capsem-doctor |
Adding a new guest binary
Update three places:
_pack-initrd recipe in justfile -- add the cross-compile + copy step
capsem-init in guest/artifacts/capsem-init -- add initrd-bundled fallback logic (check /binary before rootfs path)
- Binary list above -- add it to this skill
When to use which build path
| Changed | Command | Why |
|---|
| Guest binary source (Rust agent code) | just run | Auto-repacks initrd with new binary |
capsem-init script | just run | Init script is repacked into initrd |
guest/artifacts/diagnostics/*.py | just exec "capsem-doctor" | Test files repacked into initrd |
guest/artifacts/capsem-bashrc | just build-assets | Baked into rootfs, not initrd |
Profile package/root/build inputs (config/profiles/<id>/) | just build-assets | Affects profile-derived rootfs rendering |
| Installed packages (apt, pip) | just build-assets | Baked into the profile rootfs asset |
Guest binary security
All guest binaries are deployed read-only:
- Rootfs:
chmod 555 in Dockerfile template (rootfs mounted read-only)
- Initrd override:
chmod 555 in _pack-initrd and capsem-init after copying to tmpfs
- Guest processes cannot modify these binaries at runtime
How initrd repack works
The initrd is a gzip+cpio archive. _pack-initrd in the justfile:
- Builds Rust guest binaries via
cross_compile_agent() (on macOS: container build; on Linux: native cargo) -- outputs to target/linux-agent/{arch}/
- Creates a temp directory with the binaries + init script + diagnostics
- Sets permissions (chmod 555 for binaries, 755 for init)
- Packs as cpio+gzip, writes to
assets/{arch}/initrd.img
At boot, capsem-init checks if a binary exists in the initrd bundle (/binary) before falling back to the rootfs path. This means initrd copies always take priority.
Lesson: permissions are set in TWO places
Guest binary permissions must be 555 (read+execute, no write). There are two independent places that set permissions and both must agree:
- Dockerfile.rootfs.j2 --
chmod 555 when copying into the profile rootfs asset
- justfile
_pack-initrd -- chmod when copying into the initrd (overlays rootfs at boot)
The initrd copy WINS at runtime because it overlays the rootfs. So even if the Dockerfile says 555, if the justfile says 755, the guest sees 755. When fixing permissions, always check both places. A rootfs rebuild (just build-assets) alone won't fix it if the initrd repack still sets the wrong mode.