Skip to content

feat: add Hermit unikernel backend support#540

Open
jim-junior wants to merge 1 commit intourunc-dev:mainfrom
jim-junior:feat/add-hermit-rs
Open

feat: add Hermit unikernel backend support#540
jim-junior wants to merge 1 commit intourunc-dev:mainfrom
jim-junior:feat/add-hermit-rs

Conversation

@jim-junior
Copy link

Description

This PR adds initial support for the Hermit unikernel backend in urunc.

The implementation introduces a new unikernel type (Hermit) that integrates Hermit-based applications with the urunc runtime and QEMU as the underlying VM monitor. It also uses Initrd for storage and currently supports and is only tested on x86 arch.

Related issues

How was this tested?

  • Built a Hermit unikernel image using a custom bunnyfile including:
  • Ran the container using:
    sudo nerdctl run --rm -ti --runtime io.containerd.urunc.v2 jimjuniorb/hermit-qemu-hello-world:latest
  • Verified:
    • QEMU launches correctly
    • Unikernel boots successfully
    • Networking device (virtio-net) attaches without vhost
    • No crashes during VM initialization
    • Tested with networking disabled and enabled:
    • Without networking: boots successfully
    • With networking (virtio-net, no vhost): boots successfully

LLM usage

N/A

Checklist

  • I have read the contribution guide.
  • The linter passes locally (make lint).
  • The e2e tests of at least one tool pass locally (make test_ctr, make test_nerdctl, make test_docker, make test_crictl).
  • If LLMs were used: I have read the llm policy.

53fbfde
- QEMU-based execution only
- x86_64 architecture support
- initrd-based boot model
- virtio-net support via tap (no vhost)
- no block device support
- basic boot argument mapping for networking

Enables running Hermit unikernels via urunc with initial networking support.

Fixes: urunc-dev#97
Signed-off-by: jim-junior <jimjunior854@gmail.com>
@netlify
Copy link

netlify bot commented Mar 21, 2026

Deploy Preview for urunc canceled.

Name Link
🔨 Latest commit 57e80cf
🔍 Latest deploy log https://app.netlify.com/projects/urunc/deploys/69bedda4a0ce0d000842c5ae

Copy link
Contributor

@IrvingMg IrvingMg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Would it be possible to add at least some basic test cases for this?

cmdString += " -L /usr/share/qemu" // Set the path for qemu bios/data
cmdString += " -cpu host" // Choose CPU
cmdString += " -enable-kvm" // Enable KVM to use CPU virt extensions
cmdString += " -L /usr/share/qemu" // Set the path for qemu bios/data
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes seem unrelated. Maybe we can drop them to keep the PR focused on the feature?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for these changes was because of lint errors, when I run make lint it produces these output.

.....
INFO [runner] linters took 1.360433664s with stages: goanalysis_metalinter: 1.345219838s 
pkg/unikontainers/hypervisors/qemu.go:61:1: File is not properly formatted (gofmt)
        cmdString += " -L /usr/share/qemu" // Set the path for qemu bios/data
^
pkg/unikontainers/unikernels/hermit_rs.go:83:3: ineffectual assignment to deviceArgs (ineffassign)
                deviceArgs := " -device " + device + ",netdev=net0"
                ^
2 issues:
* gofmt: 1
* ineffassign: 1
INFO File cache stats: 2 entries of total size 7.6KiB 
INFO Memory: 194 samples, avg is 44.2MB, max is 204.4MB 

So inorder to fix that, I did run

gofmt -w pkg/unikontainers/hypervisors/qemu.go

Thats what led to these changes. However, considering they are not part of the feature, I am going to revert them.

Comment on lines +67 to +74
switch fsType {
case "initrd":
return true
case "virtiofs":
return true
default:
return false
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
switch fsType {
case "initrd":
return true
case "virtiofs":
return true
default:
return false
}
return fsType == "initrd" || fsType == "virtiofs"

nit: I think we could do this instead.

}

func (h *Hermit) MonitorCli() types.MonitorCliArgs {
switch h.Monitor {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Looks like we only check h.Monitor == "qemu". Do we need a switch here?

}

func (h *Hermit) Init(data types.UnikernelParams) error {
mask := 24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: What if we make this a constant, like DefaultCIDRMask?

@jim-junior
Copy link
Author

Alright @IrvingMg , let me update the PR basing on your feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for Hermit-rs

2 participants