vhaudiquet f66024bfea docs: the brew tap-trust gate and the macOS from-source section
The one-command install edit had replaced the whole macOS section
instead of just the install lines, dropping the from-source sign
snippet; it is back, with the current entitlements path and
libarchive in the brew line. Homebrew's tap-trust gate now leads the
macOS install: dependencies from third-party taps stay refused until
their tap is trusted once, and libkrun ships from its own tap.
2026-10-31 18:45:06 -05:00

écrou logo

ecrou

a small microVM runtime based on libkrun

Try ecrou in the terminal

Installation

Linux (strictly confined snap, KVM required):

sudo snap install ecrou
sudo snap connect ecrou:kvm

macOS (Apple Silicon, Homebrew):

brew trust --tap libkrun/krun
brew install vhaudiquet/ecrou/ecrou

The brew trust step is Homebrew's tap-trust gate: dependencies from third-party taps stay refused until their tap is trusted once, and ecrou's engine, libkrun, ships from libkrun's own tap. The macOS build loads libkrun from that tap at runtime and boots through Hypervisor.framework; the formula signs the binary with the hypervisor entitlement macOS requires, so the install needs no extra steps. Building from source instead:

brew install libkrun/homebrew-krun/libkrun e2fsprogs libarchive
cargo build --release -p ecrou-cli
codesign --force --sign - --entitlements packaging/homebrew/ecrou.entitlements \
  target/release/ecrou

Every local build needs that last line: cargo output is ad-hoc signed without the entitlement, and macOS refuses VM creation to it — ecrou probe says so and prints the command.

Usage

$ ecrou run -it ubuntu
root@ecrou-vm-m2glhl:/# 

Embed ecrou into your project

ecrou is both a library and a tiny CLI frontend around it. The library is embeddable into any project, allowing to use microVMs easily.

Rust

ecrou is a Rust library, which can just be called:

use ecrou::vm::RunOptions;
use ecrou::NoProgress;

fn main() -> ecrou::Result<std::process::ExitCode> {
    let code = ecrou::vm::run(
        &RunOptions {
            image: "ubuntu:resolute".into(),
            command: vec!["uname".into(), "-a".into()],
            ..RunOptions::default()
        },
        &NoProgress,
    )?;
    Ok(std::process::ExitCode::from(code.clamp(0, 255) as u8))
}
Languages
Rust 99.4%
Ruby 0.6%