Skip to content

ahimsalabs/yobo

Repository files navigation

yobo

Fast microVM execution for development. Run commands in isolated Linux VMs with container image support, shared filesystems, and sub-second boot times.

# Run a command in an Ubuntu VM
yobo run --image docker.io/library/ubuntu:24.04 -- cat /etc/os-release

# Interactive shell
yobo shell --image docker.io/library/ubuntu:24.04

# Persistent VM with workspace mount
yobo start --vm mydev --image ubuntu:24.04 --workspace ~/projects/myapp
yobo shell --vm mydev   # connect from another terminal

Features

  • Fast boot (~100ms) via libkrun/KVM
  • OCI image support - pull and run any container image
  • Shared filesystems - mount your workspace into the VM
  • Rootless operation - no root required (user namespaces)
  • Layer deduplication - shared base images across VMs
  • eBPF observability - BTF-enabled kernel for tracing

Requirements

  • Linux with KVM support (/dev/kvm accessible)
  • User namespaces enabled
  • subuid/subgid configured for your user

Check KVM access:

ls -l /dev/kvm
# If permission denied, add yourself to the kvm group:
sudo usermod -aG kvm $USER
# Then log out and back in

Check subuid/subgid:

grep $USER /etc/subuid /etc/subgid
# Should show something like: cbro:100000:65536
# If missing, add with:
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER

Quick Start (Pre-built)

If someone has provided you with a pre-built yobo binary and libkrunfw.so:

# Install binary
mkdir -p ~/.local/bin ~/.local/lib
cp yobo ~/.local/bin/
mkdir -p ~/.local/lib/yobo
cp libkrun.so* libkrunfw.so* ~/.local/lib/yobo/

# Add to shell profile (~/.bashrc or ~/.zshrc)
export PATH="$HOME/.local/bin:$PATH"
export LD_LIBRARY_PATH="$HOME/.local/lib/yobo:$LD_LIBRARY_PATH"

# Test
yobo run --image alpine:latest -- echo "Hello from VM!"

Building from Source

Prerequisites

Rust & Go toolchains:

# Rust (1.70+)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Go (1.24+)
# See https://go.dev/doc/install

Task (task runner):

# macOS
brew install go-task

# Linux
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin

System dependencies (Debian/Ubuntu):

sudo apt install build-essential pkg-config libssl-dev fuse-overlayfs

System dependencies (Fedora/RHEL):

sudo dnf install gcc make openssl-devel fuse-overlayfs

Build Steps

1. Build yobo CLI (Rust + Go init)

# Build everything (Go init + Rust CLI)
task build

# Outputs:
#   - yobo-init-go/yobo-init   (Go static binary, embedded in CLI)
#   - target/release/yobo      (Rust CLI)

Or manually:

# Step 1: Build Go init (must be first)
cd yobo-init-go
CGO_ENABLED=0 go build -ldflags="-s -w" -o yobo-init .
cd ..

# Step 2: Build Rust CLI (embeds the Go binary)
cargo build --release

2. Build Custom Kernel (libkrunfw)

The custom kernel adds eBPF/BTF support for observability. This takes ~20-30 minutes.

Additional dependencies (Debian/Ubuntu):

sudo apt install libncurses-dev bison flex libelf-dev bc \
     python3 python3-pyelftools dwarves libdw-dev zlib1g-dev

Additional dependencies (Fedora/RHEL):

sudo dnf install ncurses-devel bison flex elfutils-libelf-devel bc \
     python3 python3-pyelftools dwarves elfutils-devel zlib-devel

Build and install:

# Build and install to ~/.local/lib
task libkrunfw-install

# Or manually:
cd libkrunfw
./build.sh install

This builds Linux 6.12 with BTF support and installs libkrunfw.so to ~/.local/lib/.

3. Install

# Install yobo with bundled libkrunfw to ~/.local/
task install

# Or manually copy:
cp target/release/yobo ~/.local/bin/

Add to your shell profile:

export PATH="$HOME/.local/bin:$PATH"
export LD_LIBRARY_PATH="$HOME/.local/lib/yobo:$LD_LIBRARY_PATH"

Development Build

For faster iteration without embedding the init binary:

task build-dev   # or: cargo build

Usage

One-shot commands

# Run a command and exit
yobo run --image ubuntu:24.04 -- ls -la /

# With workspace mounted at /workspace
yobo run --image ubuntu:24.04 --workspace . -- ls /workspace

Interactive shell

# Shell with PTY
yobo shell --image ubuntu:24.04

# With resource limits
yobo shell --image ubuntu:24.04 --cpus 4 --memory 4096

Persistent VMs

# Start a named VM (shows monitoring console)
yobo start --vm mydev --image ubuntu:24.04 --workspace ~/code

# In another terminal, connect to it
yobo shell --vm mydev
yobo run --vm mydev -- make build

# List running VMs
yobo list

# Stop a VM
yobo delete --vm mydev

VM configuration

Flag Description Default
--image OCI image reference required
--workspace Host directory to mount at /workspace none
--cpus Number of vCPUs 2
--memory Memory in MB 2048
--vm VM name (for persistent VMs) auto-generated

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                            Host                                  │
│  ┌─────────────┐                                                │
│  │   yobo CLI  │                                                │
│  └──────┬──────┘                                                │
│         │ fork() + user namespace                               │
│         ▼                                                       │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                    microVM (KVM)                          │   │
│  │  ┌────────────────────────────────────────────────────┐  │   │
│  │  │               yobo-init (PID 1)                    │  │   │
│  │  │  - Control port 47100 (JSON)                       │  │   │
│  │  │  - Command port 47101 (binary framing)             │  │   │
│  │  └────────────────────────────────────────────────────┘  │   │
│  │                                                          │   │
│  │  virtiofs mounts:                                        │   │
│  │    /           ← OCI image layers (overlay)              │   │
│  │    /workspace  ← host workspace directory                │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

Components:

  • yobo CLI (Rust) - VM lifecycle, image pulling, client connections
  • libkrun - Lightweight KVM-based VMM (no QEMU dependency)
  • yobo-init (Go) - Guest PID 1, command execution, PTY allocation
  • fuse-overlayfs - Rootless overlay for OCI layers

See docs/ARCHITECTURE.md for details.

File Layout

~/.yobo/
├── layers/              # Shared OCI image layers (deduplicated)
│   └── <digest>/        # Unpacked layer directory
└── <vm-name>/
    ├── .yobo-meta.json  # VM configuration
    ├── upper/           # Overlay upper layer (VM writes)
    ├── work/            # Overlay work directory
    ├── merged/          # Overlay merged view (rootfs)
    └── vm.info          # Running VM info (ports, auth)

~/.cache/yobo/
└── yobo-init            # Extracted embedded init binary

Testing

task test         # All tests (Rust + Go)
task test-rust    # Rust tests only
task test-init    # Go tests only
task check        # cargo check + clippy

Troubleshooting

"permission denied" on /dev/kvm

sudo usermod -aG kvm $USER
# Log out and back in

"newuidmap: write to uid_map failed"

# Check subuid/subgid are configured
grep $USER /etc/subuid /etc/subgid

# Add if missing
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER

"libkrunfw.so: cannot open shared object file"

# Ensure library path is set
export LD_LIBRARY_PATH="$HOME/.local/lib/yobo:$LD_LIBRARY_PATH"

# Verify library exists
ls -la ~/.local/lib/yobo/

Stale VM mounts

# If a VM didn't clean up properly
fusermount -u ~/.yobo/<vm-name>/merged
rm -rf ~/.yobo/<vm-name>

Custom libkrun/libkrunfw

yobo uses custom-built versions of libkrun and libkrunfw with patches for:

  1. eBPF/BTF support (libkrunfw) - Enables in-guest eBPF programs
  2. ICMP passthrough (libkrun + libkrunfw) - Makes ping work inside VMs

Build scripts are in libkrunfw/ and libkrun/. See docs/ARCHITECTURE.md for details.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors