Library / SDK
unikraft/unikraft avatar
unikraft/unikraft

Unikraft: building single-purpose kernels instead of running on Linux

A next-generation cloud native kernel designed to unlock best-in-class performance, security primitives and efficiency savings.

3,874 stars1,508 forksCNOASSERTION

At a glance

What is it?
Unikraft is a C-based unikernel development kit that assembles a kernel from only the libraries an application needs. It suits teams who can rebuild their stack per workload, and it is the wrong tool for anything that expects a shell, a package manager or a general-purpose OS.
Who is it for?
Adopt Unikraft if you control the build of a single-purpose service and want the kernel image to contain only what that service links, and if you accept rebuilding per target instead of patching a running system. Do not adopt it for workloads that need a general-purpose userspace, an interactive shell or arbitrary third-party binaries, because those components are not part of the picture.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Unikraft actually replaces

A normal service ships as a process inside a container or a virtual machine, and the kernel underneath it is a general-purpose one. That kernel carries schedulers, drivers, filesystems and system call surfaces for every workload it might ever host, not for the one you are deploying. Unikraft takes the opposite position: the kernel is built at the same time as the application, and it contains the libraries that application links against and nothing else.

The README frames this as a development kit rather than a kernel. It describes Unikraft as powering containerless applications by letting you "radically customize and build custom OS/kernels", and the feature list returns to the same idea repeatedly: a modular design where you include only necessary components, which yields leaner configurations and, in the project's phrasing, a reduced attack surface. The audience is therefore narrow and specific. It is people who build the binary themselves and are willing to treat the kernel as a build artifact. If your deployment model is pulling an image someone else built and running it under a shared kernel, Unikraft asks you to change that model, not just the image.

The library model behind the build

The repository layout is the clearest statement of how the project is organised. The top level holds arch/, drivers/, lib/, plat/ and support/ alongside Config.uk, Makefile and Makefile.uk. Those directories map onto the mechanism: arch/ holds architecture-specific code for x86 and ARM, plat/ holds platform support for the hypervisors and environments a unikernel can run on, drivers/ holds device support, and lib/ holds the components that get selected into a build. Config.uk is the configuration entry point that decides which of those components are present.

The Makefile is inherited from Buildroot, and its header credits Erik Andersen, the Buildroot developers and NEC Europe Ltd. That lineage explains the build system's shape: a Kconfig-style configuration step feeding a Make-based assembly process. The README confirms the two supported routes. The recommended one is the companion command-line tool kraft; the alternative is the GNU Make-based system, which the README points to as an "advanced usage guide". So there are two front ends over the same underlying library selection, one opinionated and one manual.

This is where the trade-off lives. Selecting libraries at build time removes code, which is the point, but it also means the composition happens before the application runs and cannot be changed afterwards. There is no loading a missing driver at runtime.

Installing kraft and running a first unikernel

The README's quick start goes through the companion CLI rather than the Make system. On macOS, Linux and Windows the interactive installer is a single shell pipeline that fetches and runs an install script from get.kraftkit.sh.

bash
curl -sSfL https://get.kraftkit.sh | sh

On macOS there is also a Homebrew formula, and the README gives it as a separate path rather than a replacement for the installer.

bash
brew install unikraft/cli/kraftkit

For Debian, Fedora, RHEL, Arch and Windows the README does not spell out a package command. It directs you to the interactive installer or to the additional installation instructions linked from the project's documentation site. Treat that as the boundary of what the README itself covers.

With the CLI in place, the first unikernel is a single command. The README calls the result an "ultra-lightweight unikernel virtual machine" and uses the community helloworld image.

bash
kraft run unikraft.org/helloworld:latest

Instance management and discovery are two more commands from the same quick start. The first lists running and stopped instances, the second refreshes and lists the community image catalog inside the CLI.

bash
kraft ps --all
kraft pkg ls --update --apps

If you would rather not install anything on the host, the README offers a pre-built development container with the dependencies needed to build and try Unikraft in emulation mode. It mounts your working directory at /workspace and drops you into a shell.

bash
docker run --platform linux/x86_64 -it --rm -v $(pwd):/workspace --entrypoint bash kraftkit.sh/base:latest

The README also mentions GitHub Codespaces as a way to try the starter examples without a local toolchain. What you should see after kraft run is the helloworld image booting as a virtual machine; the README's claim is that boot is measured in milliseconds against tens of seconds for Linux-based systems, which is a claim from the project's feature list rather than something this article can confirm.

Where the unikernel model breaks down

The single most important limitation is the one the design creates on purpose. A unikernel has no general-purpose userspace. You cannot open a shell, install a package, run a debugger inside the guest, or start a second process that was not compiled into the image. Debugging is therefore a build-and-redeploy loop, and any diagnostic tooling has to be linked in as a library or attached from outside.

Language support is a second constraint, and the README is less precise here than its feature list suggests. It claims "broad language and application support" and "extensive support for multiple programming languages", but it does not enumerate which runtimes are available or how complete each one is. That matters because a runtime that depends on fork, dynamic loading or a large set of POSIX calls will not fit the model without substantial work. The honest reading is that the project supports the languages its library set supports, and the README does not tell you which those are.

Architecture is a third boundary. The README lists x86 and ARM as supported and describes RISC-V as coming soon, linking to riscv.org. Anything outside that set is not a target today.

Finally, there is the operational mismatch. A unikernel image is rebuilt whenever the application or the library selection changes. Teams used to patching a base image across a fleet, or to hot-fixing a running container, will find that workflow does not transfer. If your environment depends on a shared kernel for multi-tenancy reasons, or on sidecars and service meshes that assume a Linux process tree, Unikraft is not a drop-in replacement for what you have.

Unikraft compared with Firecracker and Docker

The comparison people search for most often is Unikraft against Firecracker, and the difference is one of layer, not of degree. Firecracker is a virtual machine monitor: it boots a guest kernel, and that guest kernel is a general-purpose one, typically Linux. Unikraft provides the guest kernel itself, assembled from selected libraries and linked with the application. So a Firecracker deployment still carries a Linux kernel inside the microVM, while a Unikraft deployment does not carry a kernel that was built for anything other than that application. The two are not mutually exclusive in principle, since a unikernel still needs something to boot it, but the thing being optimised is different: Firecracker narrows the device model and the VMM, Unikraft narrows the guest.

The Docker comparison is sharper because it is about isolation strategy rather than about virtualisation technology. Containers share one host kernel and isolate processes with namespaces and cgroups. Unikraft gives each application its own kernel and runs it as a virtual machine. The README's own framing is "containerless", which is the whole argument in one word. The consequence is that a container image can run anything the host kernel supports, while a Unikraft image runs only what was compiled into it. That is a real loss of generality, traded for a smaller set of components and, per the README, a smaller attack surface.

MirageOS occupies a similar conceptual space, building specialised unikernels, but from OCaml rather than from C with a Kconfig and Make build. If your codebase is OCaml, MirageOS is the more natural starting point; if it is C, or if you want the library selection expressed as build configuration rather than as a language-level abstraction, Unikraft is the closer fit. The README does not compare itself to either project, so treat these as differences in approach rather than as claims the project makes.

Releases, licence and the cost of keeping up

Unikraft releases on a roughly annual cadence with point releases in between. The recent list is RELEASE-0.21.0 (v0.21.0 Ijiraq) on 2026-05-20, RELEASE-0.20.0 (v0.20.0 Kiviuq) on 2025-09-12, and RELEASE-0.19.1 (v0.19.1 Pan) on 2025-07-17. The repository is not archived and the last push was on 2026-09-23. The default branch is staging, which is worth noting: the branch you land on is not named main or master, and that shapes how you should think about pinning.

Upgrade cost is dominated by the build model rather than by the release cadence. Because the kernel is assembled from libraries at build time, a version bump can change which libraries exist, what they expose, and how Config.uk resolves your selection. The project is pre-1.0, so the README's own version badge sits at v0.21.0 and there is no stability promise attached to it in what the project publishes. Anyone deploying this should expect to rebuild and re-verify rather than to patch in place.

The licence situation needs care. The README's badge states BSD-3, and the repository metadata reports the licence as NOASSERTION, meaning GitHub could not classify it from the files present. The Makefile is a different matter: its header places it under the GNU General Public License version 2 or later, and it carries copyright from Erik Andersen, the Buildroot developers and NEC Europe Ltd. So the tree is not uniform, and the badge alone does not describe every file. This is not legal advice; if you are distributing a built image or linking components into a product, read COPYING.md in the repository root and confirm the terms for the specific libraries you select, because your selection determines which licences end up in your image.

Editorial conclusion

Adopt Unikraft if you control the build of a single-purpose service and want the kernel image to contain only what that service links, and if you accept rebuilding per target instead of patching a running system. Do not adopt it for workloads that need a general-purpose userspace, an interactive shell or arbitrary third-party binaries, because those components are not part of the picture. Before committing, verify that the kraft CLI installs on your host, that kraft run unikraft.org/helloworld:latest boots in your hypervisor, and that the libraries your application needs are present in the repository's lib/ tree, since anything missing has to be written as a new library rather than installed at runtime.

Frequently asked questions

What are the key differences between unikernels and containers?

Containers share one host kernel and isolate processes on top of it, while a unikernel such as Unikraft builds a single-purpose kernel together with the application and runs it as a virtual machine. The README describes the result as containerless, and the practical consequence is that a container can run anything the host kernel supports, whereas a Unikraft image runs only what was compiled into it.

How does Unikraft compare with Docker?

Docker relies on a shared host kernel, so images stay portable across anything that kernel supports. Unikraft selects libraries at build time and links them with the application into its own kernel, which the README presents as a way to include only necessary components and reduce the attack surface. The trade-off is that you give up the ability to run arbitrary binaries at runtime.

How does Unikraft differ from MirageOS?

Both build specialised unikernels, but Unikraft is written in C and configures the build through Config.uk with a Make-based system inherited from Buildroot, while MirageOS builds unikernels from OCaml. The README does not compare the two, so the choice comes down to your existing codebase and whether you prefer configuration expressed as build settings or at the language level.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. unikraft/unikraft on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/unikraft-unikraft.svg)](https://hysenlabs.com/projects/unikraft-unikraft)