hyperlight: move to hyperlight-unikraft 0.14.1 and add selectable guest runtimes - #1259
Open
Dan Chiarlone (danbugs) wants to merge 7 commits into
Open
Dan Chiarlone (danbugs) wants to merge 7 commits into
Dan Chiarlone (danbugs) wants to merge 7 commits into
Conversation
0.13.0 was a ground-up rewrite of hyperlight-unikraft: the pyhl module the backend was built on is gone, the kernel is embedded in the crate, and the library API is SandboxBuilder/AppSandbox. 0.14.0 reshaped that API again (cooperative step model, typed errors), and 0.14.1 lets a restored guest take the mounts the restore names and keys snapshots by the kernel and host contract they depend on. hyperlight-host and hyperlight-common move to 0.17.0 with it. Default features are off so the hluk CLI's clap and tracing-subscriber are not pulled into mxc. Signed-off-by: danbugs <danilochiarlone@gmail.com>
The pyhl install/runtime layer no longer exists, so the backend now drives SandboxBuilder and AppSandbox directly: - The Unikraft kernel ships inside the crate. An image home holds only the agent rootfs (initrd.cpio), the warmed snapshot directory, and a VERSION stamp naming the rootfs release. A home whose stamp is another release's, or whose snapshot was saved by a build with another snapshot key (the crate's kernel and host contract), is treated as not installed: --setup-hyperlight rebuilds it without --force, and a run warms a new snapshot by itself when only the snapshot is stale. - Setup pulls ghcr.io/hyperlight-dev/hyperlight-unikraft/agent at the pinned initrd tag, boots it once, and saves the snapshot. - Every request restores that one warm image with its own mounts and network policy; the kernel builds its mount table from the mounts the restore names. Later calls on the same runner rewind to it. - Timeouts bound each step for a blocked guest and interrupt the vCPU from a watchdog thread for a busy one; either way the guest is dropped and the next call boots from the rewind point. - CallFailed carries the guest's status, which becomes the exit code as before (sys.exit(N) -> N, uncaught exception -> 1). The rootfs is needed only to warm: a home holding just a snapshot this build loads runs, and setup keeps a rootfs of this release instead of pulling it again. A warm is saved beside the snapshot directory and swapped into place, so a failed or concurrent warm never leaves a half-written layout. The e2e workflow fetches only the agent rootfs, since the kernel is embedded in the crate. On Windows the runner takes Hyperlight's single-VM mode through the crate's configure_surrogates, skipping the 512 pre-spawned helper processes (about 3.5 s); it holds one sandbox at a time. Signed-off-by: danbugs <danilochiarlone@gmail.com>
pyhl was the 0.12 library's Python tool, gone since 0.13; nothing in the backend is pyhl any more. The override is now $MXC_HYPERLIGHT_HOME (the MXC_ prefix the other backends use) and the data directory ~/.local/share/mxc-hyperlight or %LOCALAPPDATA%\mxc-hyperlight, with the dev fallbacks <exe>/mxc-hyperlight and <cwd>/.mxc-hyperlight. An old pyhl home is simply no longer looked at. Signed-off-by: danbugs <danilochiarlone@gmail.com>
Dan Chiarlone (danbugs)
requested review from
a team
and
a balanced review from Copilot
September 24, 2026 07:03
Copilot started reviewing on behalf of
Dan Chiarlone (danbugs)
September 24, 2026 07:03
View session
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Windows rootfs upgrades can fail, and the runtime-aware E2E prerequisite checks can incorrectly skip or run cases.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 3
Open (3)
What changed in this PR
Ports the Hyperlight backend to hyperlight-unikraft 0.14.1 and adds selectable guest runtimes with per-runtime installation and snapshots.
Changes:
- Reworks Hyperlight boot, snapshot, timeout, mount, and OCI rootfs handling.
- Adds six runtime choices across contracts, parsing, SDK types, and policy identity.
- Adds runtime E2E fixtures, CI setup, and backend documentation.
| File | Description |
|---|---|
tests/configs/hyperlight_python_hello.json |
Adds Python runtime fixture. |
tests/configs/hyperlight_node_hello.json |
Adds Node hello fixture. |
tests/configs/hyperlight_node_exit_code.json |
Adds Node exit-code fixture. |
src/testing/wxc_e2e_tests/tests/e2e_windows.rs |
Adds per-runtime E2E cases and skipping. |
src/testing/wxc_e2e_tests/src/lib.rs |
Updates Hyperlight installation probes. |
src/core/wxc/src/main.rs |
Adds multi-runtime setup CLI handling. |
src/core/wxc_common/src/wire.rs |
Adds Hyperlight wire configuration. |
src/core/wxc_common/src/policy_identity.rs |
Includes runtime in Hyperlight policy identity. |
src/core/wxc_common/src/models.rs |
Defines runtime and request models. |
src/core/wxc_common/src/config_parser.rs |
Normalizes and validates Hyperlight configuration. |
src/core/wxc_common/src/config_contract_adapters/v0_9/state_aware.rs |
Initializes the new IR field. |
src/core/wxc_common/src/config_contract_adapters/v0_9/one_shot.rs |
Initializes the new IR field. |
src/core/wxc_common/src/config_contract_adapters/v0_8.rs |
Initializes the new IR field. |
src/core/wxc_common/src/config_contract_adapters/v0_7.rs |
Initializes the new IR field. |
src/core/wxc_common/src/config_contract_adapters/v0_6.rs |
Initializes the new IR field. |
src/core/wxc_common/src/config_contract_adapters/dev/state_aware.rs |
Initializes state-aware Hyperlight IR. |
src/core/wxc_common/src/config_contract_adapters/dev/one_shot.rs |
Converts development runtime configuration. |
src/core/wxc_common/src/common_request_ir.rs |
Carries Hyperlight configuration in the IR. |
src/core/mxc_engine/src/run.rs |
Adds Linux KVM availability checking. |
src/core/mxc_engine/src/probe.rs |
Updates Hyperlight probe terminology. |
src/core/mxc_engine/src/policy/exact/v0_10.rs |
Initializes the exact-contract field. |
src/core/mxc_config_contract/tests/version_boundaries/experimental.rs |
Tests the version boundary. |
src/core/mxc_config_contract/tests/v0_10_0_alpha/fixtures/one_shot/valid/hyperlight_node.json |
Adds a valid Node fixture. |
src/core/mxc_config_contract/tests/v0_10_0_alpha/experimental/root.rs |
Tests the root Hyperlight section. |
src/core/mxc_config_contract/tests/v0_10_0_alpha/experimental/hyperlight.rs |
Tests runtime values and validation. |
src/core/mxc_config_contract/tests/v0_10_0_alpha/experimental.rs |
Registers Hyperlight contract tests. |
src/core/mxc_config_contract/src/dev/one_shot.rs |
Adds the development request field. |
src/core/mxc_config_contract/src/dev/mod.rs |
Exports Hyperlight contract types. |
src/core/mxc_config_contract/src/dev/experimental.rs |
Defines runtime contract types. |
src/core/lxc/src/main.rs |
Adds Linux multi-runtime setup handling. |
src/Cargo.lock |
Updates Hyperlight and supporting dependencies. |
src/backends/hyperlight/common/src/lib.rs |
Implements the new runtime, snapshot, timeout, and installer paths. |
src/backends/hyperlight/common/Cargo.toml |
Updates Hyperlight and OCI dependencies. |
sdk/node/src/types.ts |
Exposes Hyperlight runtime configuration. |
sdk/node/src/generated/v0_10_0_alpha/wire.ts |
Regenerates development wire types. |
sdk/node/README.md |
Documents SDK backend support. |
schemas/dev/mxc-config.schema.0.10.0-alpha.json |
Regenerates the development schema. |
README.md |
Links the Hyperlight backend guide. |
docs/schema.md |
Documents the runtime field. |
docs/hyperlight/hyperlight-backend.md |
Adds the comprehensive backend guide. |
docs/hyperlight-integration-plan.md |
Removes the superseded design document. |
.github/workflows/hyperlight-e2e.yml |
Installs and tests selected runtimes in CI. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Setup used docker or podman to pull the rootfs image and copy initrd.cpio out of it, so a host without a container runtime could not set Hyperlight up. It now speaks just enough of the OCI distribution API itself: an anonymous pull token, the manifest (through an index when the tag names one), and the layer tarballs, streamed through gunzip and tar and checked against their digests. ureq (rustls with ring, as the 0.12 crate used), flate2, tar, sha2 and serde_json come in behind the hyperlight feature. The download is bounded (30 s to resolve and connect, 60 s to a response, 30 min for a layer) so a dead link fails instead of hanging setup. The e2e workflow no longer needs crane: it runs --setup-hyperlight, which also exercises the real install path in CI. Signed-off-by: danbugs <danilochiarlone@gmail.com>
The design note from the original integration was the only document on the backend, and it described the 0.12 shape: pyhl, a kernel file, network rejected, tests that no longer exist. The guide covers what ships now: setup and the image home, how a run works, the fields the backend honours, what the guest has, the design choices that still hold, and the messages to expect. The README and SDK backend table link it. Signed-off-by: danbugs <danilochiarlone@gmail.com>
The Hyperlight backend can boot any of the guest runtimes hyperlight-unikraft publishes, so a request needs a way to name one. The `hyperlight` section's `runtime` says what process.commandLine is source for: `agent` (the default), `python`, `python-shell`, `node`, `bash` or `dotnet-jit`, each named as upstream names the image. The section sits beside `wslc` and `windowsSandbox` in the 0.10.0-alpha contract: the request IR, the domain model, the parser's section validation, the adapters, the engine's exact builder and the policy identity all carry it, and the generated schema and TypeScript are regenerated. The runtime is part of the policy identity because it picks the image the sandbox boots. Signed-off-by: danbugs <danilochiarlone@gmail.com>
The image home now holds one directory per runtime (agent/, python/, node/, ...), each with its rootfs, snapshot and stamp, so runtimes install, upgrade and run independently. The runner picks the directory from the request's hyperlight.runtime and keys its booted guest on it; the image table gives each runtime its upstream image and scratch size. The images that take source through a warm driver are selectable: agent, python, python-shell, node, bash and dotnet-jit. The compiled images run a program baked into the rootfs, so they are not. --setup-hyperlight takes runtime names and installs agent by default, and a run naming an uninstalled runtime fails at preflight with the setup command to run. The e2e workflow installs agent, python and node, and the suite gains a plain-Python hello, a Node.js hello and a Node.js exit-code case on both platforms. The guide gains the runtime table and the per-runtime layout. Signed-off-by: danbugs <danilochiarlone@gmail.com>
Dan Chiarlone (danbugs)
force-pushed
the
hyperlight-unikraft-0.14
branch
from
September 24, 2026 07:36
32446d3 to
e1401ff
Compare
Copilot started reviewing on behalf of
Dan Chiarlone (danbugs)
September 24, 2026 07:37
View session
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Moves the Hyperlight backend from hyperlight-unikraft 0.12.1 to 0.14.1 and opens it up to all six driver-based runtimes: agent (default), python, python-shell, node, bash, and dotnet-jit.
SandboxBuilder/AppSandboxwithfrom_initrd/from_snapshot,snapshot_to/restore,submit/stepunder a deadline; uses hluk'sconfigure_surrogatesandload_snapshot/save_snapshot~/.local/share/mxc-hyperlight/, each with its rootfs, snapshot, and version stamp;--setup-hyperlight[=RUNTIME,...]installs themhyperlight.runtimefield in the 0.10.0-alpha contract selects the runtime; policy identity hashes it only for Hyperlight containmentpyhltomxc-hyperlightdrops the old directoryNetworking is documented as rejected in this release: 0.10 documents can't populate the legacy host lists, and wiring the directional egress model is a follow-up.
Microsoft Reviewers: Open in CodeFlow