Skip to content

v0.3.1

Latest

Choose a tag to compare

@github-actions github-actions released this 28 Mar 11:03
· 19 commits to main since this release

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 isolationRUN 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

  • --exec renamed to --entrypoint. Use --command/--cmd for arguments.
  • --tailscale flag removed. --tailscale-authkey adds the image and creates the init script.
  • --containerfile is mutually exclusive with --image/--rootfs.
  • xenomorph build with no -o flag 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 (estimateImageSize catch block caused unreachable panic)
  • Fix aarch64 build (use clone syscall instead of fork which 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/--rootfs with normalized image references
  • Fix nix release build with upstream oci-spec-zig dependency