Hyperlight is a lightweight Virtual Machine Manager (VMM) designed to be embedded within applications. It enables safe execution of untrusted code within micro virtual machines with very low latency and minimal overhead.
We are a Cloud Native Computing Foundation sandbox project.
Run Unikraft unikernels on Hyperlight, a lightweight Virtual Machine Manager (VMM) designed for embedded use within applications.
This project enables running Linux applications (Python, Node.js, Go, Rust, C/C++) on Hyperlight micro-VMs using Unikraft as the guest kernel. It provides:
- hyperlight-unikraft - A CLI host that loads and runs Unikraft kernels on Hyperlight
- Example configurations - Ready-to-use kraft configs for building various applications
┌──────────────────────────────────────────────────────────────┐
│ Your Application (Python, Node.js, Go, Rust, C/C++) │
│ (runs as ELF binary inside the VM) │
├──────────────────────────────────────────────────────────────┤
│ Unikraft Kernel (ELF loader + VFS + POSIX) │
│ - Mounts initrd as ramfs │
│ - Loads and executes application ELF │
├──────────────────────────────────────────────────────────────┤
│ hyperlight-unikraft (embedded Hyperlight host) │
│ - Loads kernel ELF + initrd │
│ - Passes arguments via magic header in initrd │
├──────────────────────────────────────────────────────────────┤
│ Hyperlight VMM (hypervisor interface) │
│ - Creates micro-VM with identity-mapped page tables │
│ - Provides PEB structure with memory regions │
├──────────────────────────────────────────────────────────────┤
│ KVM (Linux) / MSHV (Windows) │
└──────────────────────────────────────────────────────────────┘
- Host loads kernel and initrd:
hyperlight-unikraftreads the Unikraft kernel ELF and optional initrd (CPIO archive) - Arguments embedded in initrd: Application arguments are prepended to the initrd with a magic header (
HLCMDLN\0) - VM starts: Hyperlight creates a micro-VM with identity-mapped memory and jumps to the kernel entry point
- Kernel extracts initrd: Unikraft mounts the initrd as a RAM filesystem, extracts the embedded cmdline
- Application runs: The ELF loader loads and executes the application binary (e.g.,
/usr/bin/python3) - Output via console: Application output goes through
outbto port 0xE9, which Hyperlight captures
- No host function calls - The Unikraft kernel runs entirely within the VM
- Identity-mapped memory - Simplified memory layout (vaddr == paddr)
- Generic cmdline mechanism - Pass arguments to any application via
-- arg1 arg2 ... - Fast cold start - Hyperlight's lightweight design enables millisecond startup times
Common on both Linux and Windows:
Linux-only (needed to build Unikraft kernels locally):
- KVM (
/dev/kvmreadable/writable) - Go 1.25+ (builds
kraft-hyperlight)
Windows-only:
- Windows Hypervisor Platform (
Enable-WindowsOptionalFeature -Online -FeatureName HypervisorPlatform; reboot) - Developer Mode enabled (Settings → For developers → Developer Mode)
- Kernels are pulled pre-built from GHCR;
kraft-hyperlightis not required.
# 1. Toolchain
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo install just
# 2. kraft-hyperlight (builds Unikraft kernels)
git clone --branch hyperlight-platform https://github.com/unikraft/kraftkit.git
cd kraftkit && go build -o kraft-hyperlight ./cmd/kraft
sudo mv kraft-hyperlight /usr/local/bin/ && cd ..
# 3. This repo + host CLI
git clone https://github.com/hyperlight-dev/hyperlight-unikraft.git
cd hyperlight-unikraft/host
cargo build --release
sudo cp target/release/hyperlight-unikraft /usr/local/bin/
cd ..
# 4. Run any example
cd examples/helloworld-c
just build # build the Unikraft kernel with kraft-hyperlight
just rootfs # build the rootfs CPIO via Docker
just runFor Python workloads specifically, the pyhl binary wraps the
python-agent-driver image (kernel + CPIO with numpy/pandas/pydantic/
yaml/jinja2/bs4/tabulate/click/tenacity/tqdm/openpyxl/pypdf/markdown-it-py/
pillow/lxml/cryptography/dateutil/dotenv preloaded) behind a simple
setup / run workflow:
# One-time: build the driver image (kernel + CPIO)
cd examples/python-agent-driver
just rootfs && just build
cd ../..
# Install pyhl
cargo install --git https://github.com/hyperlight-dev/hyperlight-unikraft \
hyperlight-unikraft-host --bin pyhl
# Point pyhl at the image you just built — creates ./.pyhl/ in cwd
pyhl setup --from examples/python-agent-driver
# Run Python
pyhl run -c 'import pandas as pd; print(pd.DataFrame({"x":[1,2,3]}).sum().to_dict())'
pyhl run my_script.py
pyhl run my_script.py --repeat 4 # 5 hermetic invocationsEach pyhl run process pays a ~10s cold start (kernel boot + Py_Initialize
- preloaded imports) once, then every user invocation (including the
first) runs hermetic at ~100ms — the driver snapshots the post-warmup
state and restores between calls, so
__main__globals andsys.modulesdon't leak between runs.
pyhl setup is idempotent — re-running reports the existing install and
exits 0; pass --force to overwrite. Artifacts are found via
--dest/$PYHL_HOME / ./.pyhl/ / ~/.local/share/pyhl/, in that order.
# 1. Toolchain
# Install Rust via https://www.rust-lang.org/tools/install
cargo install just
# 2. This repo + host CLI
git clone https://github.com/hyperlight-dev/hyperlight-unikraft.git
cd hyperlight-unikraft\host
cargo build --release
Copy-Item target\release\hyperlight-unikraft.exe $env:USERPROFILE\.cargo\bin\ -Force
cd ..
# 3. Run any example (kernel pulled from GHCR)
cd examples\helloworld-c
just build # docker pull ghcr.io/hyperlight-dev/hyperlight-unikraft/helloworld-c-kernel
just rootfs # docker build + extract CPIO
just run| Recipe | Linux | Windows |
|---|---|---|
just build |
kraft-hyperlight build |
docker pull the pre-built kernel from GHCR |
just rootfs |
docker build --target cpio + extract the CPIO |
same |
just run |
hyperlight-unikraft <kernel> --initrd ... |
same |
just clean |
remove .unikraft/ and the CPIO |
same |
| Example | Binary | Notes |
|---|---|---|
helloworld-c |
Static PIE C binary | Compiled with musl-gcc |
rust |
Static PIE Rust binary | Compiled with rustc --target x86_64-unknown-linux-musl |
python |
CPython 3.12 | Rootfs from Docker, script passed via cmdline |
go |
Static PIE Go binary | Compiled with musl via Docker for CGO support |
nodejs |
Node.js 21 | Rootfs from Alpine, script passed via cmdline |
hostfs-posix-c |
C + unmodified POSIX | open/read/write/mkdir against /host, forwarded by lib/hostfs |
hostfs-posix-py |
Python + stdlib | Same as hostfs-posix-c using open()/os.mkdir/os.stat |
--mount HOST_DIR[:GUEST_PATH] preopens a host directory for the guest:
# Default: guest-visible at /host
hyperlight-unikraft kernel --initrd app.cpio --mount ./work
# Custom guest mount point
hyperlight-unikraft kernel --initrd app.cpio --mount ./work:/datalib/hostfs in the guest auto-mounts HOST_DIR at GUEST_PATH (default
/host); unmodified POSIX calls (open, read, write, stat,
mkdir, truncate, …) are forwarded by the VFS driver to the host's
FsSandbox tool handlers. The guest mount point is advertised runtime
via an HLHSMNT TLV in init_data, so one kernel build can serve
different mount points. Reserved kernel dirs (/, /bin, /dev,
/proc, /sys, /usr) are refused to avoid shadowing the initrd.
Every path the guest sends is resolved relative to HOST_DIR and any
escape (via .. or symlinks) is rejected host-side.
Known limitation: opendir/readdir don't work yet (see
lib/hostfs/README.md). Stat and enumerate known paths instead.
--exec CODE / -e CODE feeds a snippet to the guest interpreter as
-c CODE. The host handles all the argparse-escape quoting internally,
so you can pass arbitrary whitespace, quotes, and newlines without
wrapping:
hyperlight-unikraft python-kernel --initrd python.cpio --memory 96Mi \
--exec 'for i in range(3): print(i * i)'Works for any interpreter that treats -c as "run the next arg as
code" — CPython, sh, etc. node -e works identically with -e.
examples/hostfs-posix-py wraps it in two Justfile recipes:
just exec "print('hi'); print(2 + 2)"
just run-file path/to/myscript.py # file's contents → --execNo --mount involved. No /host/… path contract. The host just passes
argv.
--exec and positional -- args are mutually exclusive (clap enforces
it at parse time) — they both populate argv, so letting both through
would silently lose one. If you need inline code plus extra sys.argv
arguments, drop back to the raw -- form and do the quoting yourself:
hyperlight-unikraft python-kernel --initrd python.cpio --memory 96Mi \
-- -c '"import sys; print(sys.argv[1:])"' alpha beta gamma
# => ['alpha', 'beta', 'gamma']The inner -c payload is wrapped in outer double-quotes so uk_argparse
preserves whitespace, with internal quotes backslash-escaped. Anything
after is plain argv.
For interpreted languages, pass the script path after --:
# Python
hyperlight-unikraft kernel --initrd python.cpio --memory 256Mi -- /script.py arg1 arg2
# Node.js
hyperlight-unikraft kernel --initrd node.cpio --memory 512Mi -- /app/server.js --port 8080hyperlight-unikraft [OPTIONS] <KERNEL> [-- <APP_ARGS>...]
Arguments:
<KERNEL> Path to the Unikraft kernel binary
<APP_ARGS>... Arguments passed to the application (after --)
Options:
-m, --memory <MEMORY> Memory allocation [default: 512Mi]
--stack <STACK> Stack size [default: 8Mi]
--initrd <CPIO> Path to initrd/rootfs CPIO archive
-q, --quiet Suppress kernel output
-h, --help Print help
-V, --version Print version
hyperlight-unikraft/
├── host/ # Rust host (hyperlight-unikraft CLI + pyhl)
├── examples/ # Ready-to-use kraft configs
│ ├── helloworld-c/ # C (musl-gcc)
│ ├── rust/ # Rust (musl)
│ ├── python/ # CPython 3.12
│ ├── python-agent-driver/# Python with pre-loaded packages (pyhl)
│ ├── go/ # Go (musl via Docker)
│ ├── nodejs/ # Node.js 21
│ ├── hostfs-posix-c/ # Host filesystem sandbox (C)
│ ├── hostfs-posix-py/ # Host filesystem sandbox (Python)
│ ├── dotnet/ # .NET
│ ├── powershell/ # PowerShell
│ ├── shell/ # Shell
│ └── ...
├── runtimes/ # Dockerfiles for runtime images
└── demos/ # Demo materials
This project builds on the following upstream repositories:
| Repository | Description |
|---|---|
| hyperlight-dev/hyperlight | Hyperlight VMM |
| unikraft/unikraft | Unikraft core with Hyperlight platform support |
| unikraft/app-elfloader | ELF loader application |
| unikraft/kraftkit | Kraft build tool with Hyperlight machine driver |
Please review the CONTRIBUTING.md file for more information on how to contribute to Hyperlight.
This project holds fortnightly community meetings to discuss the project's progress, roadmap, and any other topics of interest. The meetings are open to everyone, and we encourage you to join us.
- When: Alternating Wednesdays at 09:00 and 07:00 (PST/PDT) Convert to your local time
- Where: Zoom! - Agenda and information on how to join can be found in the Hyperlight Community Meeting Notes. Please log into hackmd to edit!
The Hyperlight project Slack is hosted in the CNCF Slack #hyperlight. To join the Slack, join the CNCF Slack, and join the #hyperlight channel.
For more information, please refer to the main Hyperlight project.
See the CNCF Code of Conduct.