xenomorph v0.3.1
Replace your running Linux root filesystem with a new one live, without rebooting.
Highlights
Zero external dependencies — xenomorph no longer shells out to tar, gzip, cp, or any other tool for core operations. Layer extraction uses Zig's std.tar and std.compress natively. The only remaining child processes are init system coordination (systemctl, rc-service) and Containerfile RUN commands (intentional chroot+exec).
Secure container isolation — RUN commands in Containerfiles execute inside Linux namespaces (user, mount, PID, network) with a seccomp filter blocking 20 dangerous syscalls. Minimal /dev (5 devices via bind mount, not host /dev). Read-only /proc and /sys. Auto-detects the best isolation level and falls back gracefully.
Build caching — built rootfs images are cached as OCI layouts. Repeated pivot or build invocations with the same layers skip all image pulls and merging. CACHE_DIRECTORY env var support for systemd integration.
systemd rescue.target integration — NixOS module and systemd unit files for running xenomorph as a rescue target service. Cache warmup service pre-pulls images on boot so the pivot is instant. Ships with ready-to-use unit files in init/systemd/.
Dropbear SSH — --ssh-port, --ssh-password, --ssh-keyfile install and start a dropbear SSH server in the new rootfs. Random password printed before fork if not specified. Firewall rules flushed by default (--keep-firewall to opt out).
In-memory logging — all log messages are captured in a memory buffer alongside stderr output. The buffer is written to <log_dir>/xenomorph.log in the new rootfs just before pivot, so logs survive the exec and are available after reconnecting. No dependency on the old root filesystem for log persistence.
OCI library extracted — all OCI operations (registry client, layer handling, Containerfile parsing, layout writing, container isolation) live in oci-zig, a standalone Zig library.
Breaking changes
--execrenamed to--entrypoint. Use--command/--cmdfor arguments.--tailscaleflag removed.--tailscale-authkeyadds the image and creates the init script.--containerfileis mutually exclusive with--image/--rootfs.xenomorph buildwith no-oflag is cache-only (no output written).- Release tarballs no longer include raw binaries or qemu-test.
New flags
--entrypoint <cmd>— entrypoint for the new rootfs (replaces--exec)--command,--cmd <arg>— arguments passed to entrypoint (repeatable)--ssh-port <port>— start dropbear SSH server--ssh-password <pw>— set root password (default: random)--ssh-keyfile <path>— install authorized_keys--keep-firewall— don't flush iptables/nftables before pivot--systemd-mode— skip init coordination and process kill (for systemd units)--log-dir <path>— configurable log directory for headless mode--tailscale-image <ref>— override the tailscale OCI image--containerfile,--dockerfile— build from Containerfile--context <dir>— build context for Containerfile--rootfs-output <file>— also write a rootfs tarball from build
Bug fixes
- Fix crash when pulling registry images (
estimateImageSizecatch block caused unreachable panic) - Fix aarch64 build (use
clonesyscall instead offorkwhich doesn't exist on arm64) - Fix work directory auto-creation (create parent dirs for tmpfs mount point)
- Fix init script only created when services are actually configured
- Deduplicate
--image/--rootfswith normalized image references - Fix nix release build with upstream oci-spec-zig dependency