# IncludeOS: a C++ unikernel you link into your service

> IncludeOS turns a normal-looking C++ program into a bootable unikernel by linking the operating system into the binary. The build path runs through Nix on Linux, the API is explicitly unstable, and the last release is v0.15.0 from 2019.

**includeos/IncludeOS** — A minimal, resource efficient unikernel for cloud services

- Repository: https://github.com/includeos/IncludeOS
- Website: https://includeos.github.io/
- Stars: 5,246 · Forks: 399
- Language: C++
- License: Apache-2.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/includeos-includeos

## What IncludeOS removes from the stack

A conventional cloud service ships a binary, a container image, and a general-purpose operating system underneath both. IncludeOS argues that most of that OS is dead weight for a single-purpose service. The README states that starting a program with `#include <os>` will literally include a tiny operating system into your service during link-time. The result is a unikernel: your application and the kernel are one artifact, booted directly by a hypervisor rather than by a host OS.

The target audience is narrow and specific. You need to be writing C++ services, and you need to care about the memory and boot-time floor of your deployment. The README gives the headline number: a minimal bootable 64-bit web server, including operating system components and anything needed from the C/C++ standard libraries, is currently 2.5 MB. Boot time is quoted as about 300ms on Qemu/kvm, with an IBM Research integration through Solo5/uKVM reaching as low as 10 milliseconds.

This is not a general-purpose Linux replacement. There is no shell, no package manager, and no process model in the usual sense. If your service needs to fork, exec, or read arbitrary files from a filesystem, IncludeOS is the wrong shape of tool. The README also carries a blunt warning that the public API should not be considered stable, which matters more than the feature list when you are planning a deployment.

## How a unikernel gets built and booted

The mechanism is a link-time substitution. Your program is ordinary C++ with a `main`, but the build links in the IncludeOS kernel libraries, the C++ standard library (libc++ from LLVM), and a C library (musl libc) alongside your code. The output is a bootable image, not an ELF binary that expects an OS.

At runtime there is no host kernel underneath your service. The hypervisor loads the image, and IncludeOS brings up the hardware it needs: virtio and vmxnet3 network drivers with DMA, plus a modular TCP/IP stack. The README describes the stack as highly modular, which is the part that matters if you are shipping a network service, because you can leave out protocol layers you do not use.

Language support is broad on paper and uneven in practice. The README claims full C++11/14/17/20 language support with clang 18 and later, and exceptions with stack unwinding via libgcc. Then it qualifies that: certain language features, such as threads and filestreams, are currently missing backend support. That sentence is the most important one in the feature list. A C++ service that spawns worker threads, or that reads configuration through `std::ifstream`, will not port cleanly. The build and boot tooling is arranged around Nix files at the repository root: `default.nix`, `develop.nix`, `shell.nix`, `unikernel.nix`, `vmbuild.nix`, `chainloader.nix`, `overlay.nix` and `pinned.nix`.

## Installing IncludeOS and booting the hello world example

The README is explicit about the dependency floor: for building and booting IncludeOS services you need Nix and Linux. Nix downloads and sets up the correct versions of the required libraries and compilers. IncludeOS can currently not be built on macOS or Windows, so a macOS workstation is not a supported development host.

Building the kernel itself is a single command from the repository root:

```bash
$ nix-build
```

This builds the toolchain and all IncludeOS kernel libraries. The README warns that the first build takes roughly 7 hours on their machines, because the toolchain (clang, llvm, libcxx, musl and so on) is rebuilt from source, and there is no nix binary cache for those files at the moment. Subsequent builds are much faster once the toolchain is cached in the local nix-store. Plan for that first build before you schedule anything else.

For iterating on the kernel, the README recommends a development shell rather than repeated full builds:

```bash
$ nix-shell ./develop.nix
```

Inside that shell, `cmake -B build && cmake --build build` rebuilds IncludeOS, and the README notes that editors with clangd LSP support get proper goto-declarations and warnings. The README also suggests adding ccache with `--arg withCcache true` to most `nix-build` and `nix-shell` commands, which it says can cut rebuilds from a few minutes to a matter of seconds.

A minimal IncludeOS program looks like ordinary C++. The README gives this example:

```c++
#include <iostream>

int main(){
  std::cout << "Hello world\n";
}
```

A full service with a working Nix workflow is kept in the separate hello world repository, which the README says can also serve as a starting point for your own service. The in-repo example lives under `example/`, with `example/CMakeLists.txt` and `example/src/`. From the development shell, the README shows this sequence:

```bash
[nix-shell:~/repos/IncludeOS]$ nix-build ./unikernel.nix
[nix-shell:~/repos/IncludeOS]$ boot ./result/hello_includeos.elf.bin
```

The first command rebuilds the example unikernel; the second runs the resulting image with qemu through vmrunner. If `boot` is not on your path, the README points at vmrunner's booth as the requirement.

## The Nix dependency is the real adoption cost

Most unikernel projects ask you to accept a new runtime. IncludeOS asks you to accept a new build system first. Nix is not optional here, and the README treats it as the entry point rather than a convenience. That choice buys reproducibility: pinned toolchain versions, cached artifacts in the nix-store, and a development shell that carries clangd configuration for editor support.

It also imposes a hard boundary. A team standardized on CMake plus a distro toolchain, or on a CI runner that cannot install Nix, has to change its build infrastructure before it writes a line of service code. The 7-hour first build is a one-time cost, but it is a real one on a fresh machine or a cold CI cache, and the README states there is no binary cache for the toolchain at the moment.

The second cost is API churn. The project's own README says the public API should not be considered stable. The release history backs up the caution: v0.15.0 (Cunning Conan) landed on 2019-05-09, v0.14.1 on 2019-04-04, and v0.14.0 on 2019-01-24. The repository's last push was on 2026-05-15, so work continues, but the tagged releases are old and there is a long gap between them. Treat the main branch as the thing you build against, and expect to re-read the changelog when you upgrade.

## Where IncludeOS is the wrong tool

Start with the missing backends. Threads and filestreams are called out in the README as lacking backend support. A service built around a thread pool, or one that parses config with `std::ifstream`, cannot simply be recompiled. You either restructure the service around the event model IncludeOS provides or you pick a different runtime.

Debugging is the second gap. A unikernel has no shell to log into, no `strace`, no `gdb` attach to a running process in the way a Linux service allows. The README points at `boot` and vmrunner for running images, and at the integration tests under `./IncludeOS/test/*/integration` for more advanced examples, but it does not document a rollback procedure or an operational debugging workflow. If your team's incident response depends on inspecting a live host, this model removes those tools.

Portability is the third. The README states that IncludeOS can currently not be built on macOS or Windows, even though the resulting service can run on Linux, Microsoft Windows and macOS hosts through KVM, VirtualBox and VMWare, and on cloud providers such as Google Compute Engine, OpenStack and VMWare vcloud. Development is a Linux activity; deployment is broader. Teams with mixed laptop fleets should weigh that asymmetry.

Finally, the driver story is hardware-specific. The README says IncludeOS will run on any x86 hardware platform, even a physical x86 computer, given appropriate drivers, but the shipped network drivers are virtio and vmxnet3. Bare-metal deployment outside those paths is not something the README claims as a supported default.

## How IncludeOS differs from a Linux unikernel build

The obvious comparison is a tool that takes an existing Linux application and compiles it into a unikernel image. That approach keeps the Linux system call interface, so an unmodified program can often be linked in with a compatibility layer. IncludeOS takes the opposite route: it is a new operating system written in C++, and your program targets its API directly rather than POSIX.

The trade-off is visible in both directions. IncludeOS gets a smaller floor because it never carries Linux compatibility code, and the README's 2.5 MB figure for a bootable web server reflects that. It also gets to define its own TCP/IP stack as a modular component instead of inheriting one. In exchange, you give up the ability to run an unmodified binary, and you inherit the API instability the README warns about.

If your goal is to unikernelize an existing Linux service with minimal code change, IncludeOS is not the path. If your goal is a new C++ service where you control the source and want the smallest possible bootable artifact, the direct-API model is the point rather than a drawback.

## Licence, maintenance and what an upgrade actually involves

IncludeOS is released under Apache-2.0, and the repository carries both a LICENSE and a NOTICE file, which is the usual Apache-2.0 arrangement for attribution. The README describes the project as free software with no warranties or restrictions of any kind. That phrasing is the project's own summary, not a legal opinion, and the LICENSE file is the document that governs. The NOTICE file is worth reading before you redistribute images, since Apache-2.0 attribution requirements travel with the artifact.

The maintenance picture is mixed and worth stating plainly. The repository is not archived, and its last push was on 2026-05-15, so there is recent activity. The newest tagged release is v0.15.0 from 2019-05-09. Those two facts together mean you are tracking a moving main branch with no recent release to pin against.

Upgrade cost follows from the Nix design. The toolchain is pinned through `pinned.nix` and the overlay files, so a toolchain bump is a repository change rather than something you do on your own schedule. Because the kernel is linked into your binary, a kernel upgrade means rebuilding and redeploying every service image, not patching a shared host. There is no shared runtime to update once. The README does not document a rollback path for a bad image, so your deployment tooling has to supply one.

## Conclusion

Adopt IncludeOS if you write C++ services, want a 2.5 MB bootable image, and are willing to build the whole toolchain from source with Nix on Linux. Do not adopt it if you need macOS or Windows builds, stable APIs, or the missing thread and filestream backends. Before committing, verify that nix-build completes in your environment, that your service avoids the unsupported language features, and that you are comfortable tracking a repository whose newest release is v0.15.0 from 2019.

## FAQ

### What is IncludeOS and what does it do?

IncludeOS is a minimal unikernel operating system for C++ services. Starting a program with #include <os> includes a tiny operating system into your service during link-time, producing a bootable image that runs under a hypervisor.

### How do I install IncludeOS and build it?

You need Nix and Linux, since IncludeOS can currently not be built on macOS or Windows. Running nix-build from the repository root builds the toolchain and all IncludeOS kernel libraries, and the README notes the first build takes roughly 7 hours because the toolchain is rebuilt from source.

### Where can I find IncludeOS examples?

A full hello world service with a working Nix workflow lives in the separate hello world repository, which the README says can be used as a starting point for your own service. More advanced examples are the integration tests under ./IncludeOS/test/*/integration, and the in-repo example sits under example/.

### What commands does the IncludeOS development workflow use?

The README shows nix-shell ./develop.nix to enter a development shell, cmake -B build && cmake --build build to rebuild IncludeOS, nix-build ./unikernel.nix to rebuild the example unikernel, and boot ./result/hello_includeos.elf.bin to run the image with qemu through vmrunner.

### Which C++ features are not supported in IncludeOS?

The README states that certain language features, such as threads and filestreams, are currently missing backend support. Exceptions and stack unwinding are supported, using libgcc.

## Sources

- [includeos/IncludeOS on GitHub](https://github.com/includeos/IncludeOS)
- [License: Apache-2.0](https://github.com/includeos/IncludeOS/blob/main/LICENSE)
- [Project website](https://includeos.github.io/)
- [README](https://github.com/includeos/IncludeOS/blob/main/README.md)
- [Releases](https://github.com/includeos/IncludeOS/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/includeos-includeos
