# EVE, the Linux Foundation's virtualization engine for edge devices

> EVE is a Linux Foundation project that turns an edge box, from a twenty dollar Orange Pi to an industrial PC, into a hypervisor host that partitions hardware between containerised applications. It boots LinuxKit images assembled with QEMU, and the orchestration layer is a set of Go microservices under pkg/pillar that the project is actively breaking apart.

**lf-edge/eve** — EVE is Edge Virtualization Engine 

- Repository: https://github.com/lf-edge/eve
- Website: https://www.lfedge.org/projects/eve/
- Stars: 549 · Forks: 188
- Language: Go
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/lf-edge-eve

## An operating system whose job is to run other operating systems

EVE is the Edge Virtualization Engine, and the project describes its aim as developing an open, agnostic and standardized architecture that unifies the approach to developing and orchestrating cloud-native applications across the enterprise on-premises edge.

The mechanism is hardware-assisted virtualization. Once installed, EVE has direct access to and control of the underlying resources and provides standard APIs that allow more efficient use of resources and can effectively partition hardware to increase workload consolidation and application multi-tenancy.

That is the whole proposition, and it is a different one from running containers directly on the operating system of an edge box. With EVE, the box runs a minimal hypervisor-capable system and the applications run as guests inside it. The gain is isolation between tenants, which matters when the hardware is a shared gateway in a factory or a retail chain and the applications are from different vendors, and the gain is flexibility, because the partition scheme can change without reflashing.

The scale range is unusually wide. EVE supports both ARM and Intel architectures and requires hardware-assisted virtualization, and while it can run on a board as small as a $20 Orange Pi, the sweet spot for its deployment is IoT gateways and industrial PCs. That sentence describes the intended market better than any feature list: EVE is aimed at the device in the back of a shop, not at a datacentre.

The project lives under the Linux Foundation Edge umbrella, with the homepage at lfedge.org/projects/eve, and the licence is Apache-2.0. The primary language is Go, the default branch is master, and the topics name edge, iot, linux-foundation, networking, operating-system, security and virtualization.

The repository also carries an unusual amount of process documentation for an operating system project: ADOPTERS.md, CLAUDE.md, CONTRIBUTING.md, MAINTAINERS.md, SECURITY.md, a `.cve-ignore` file, a `.syft.yaml` for generating a software bill of materials file, a `.spdxignore`, and a `NOTICE` file.

## LinuxKit and QEMU, orchestrated by Go microservices

EVE does not implement its own hypervisor or its own init system. It composes existing projects, and the README names three of them: QEMU, LinuxKit and Alpine Linux, just to name a few.

LinuxKit is the build system that assembles the bootable image, treating the operating system as a set of services packaged into a filesystem image with a small init that starts them. QEMU provides the virtual machines that the workloads run in, and Alpine Linux is the userland in the guest images. So EVE's own code is the orchestration layer and the device management, not the virtualisation primitives.

That layer is the Go code under `pkg/pillar`, and the README is unusually candid about its status. All of that functionality is being orchestrated by the Go microservices available under pkg/pillar, and then it asks why pillar, and answers: because pillar is the kind of a monolith we need to break out into true, individual microservices under pkg/.

So the structure of the repository is a statement about a refactor in progress. `pkg/pillar` is the large, existing Go service tree, and `pkg/` is where the individual services are being extracted to. The Makefile reflects the same split, with `PKGBASE=github.com/lf-edge/eve` and two separate variables for the module and the tree, `GOMODULE=$(PKGBASE)/pkg/pillar` and `GOTREE=$(CURDIR)/pkg/pillar`.

That is worth knowing before you read the code, because a search for a service will turn up it in one of two places depending on how far the extraction has progressed in the version you are looking at.

The device management side has its own tooling. The `evetest/` directory is the end-to-end test harness, `eve-tools/` holds the command line tools for a running device, `images/` holds the image definitions that LinuxKit consumes, and `pkg/` holds the Go services. There is also a `kernel-version.mk` and a `kernel-commits.mk` at the root, so the kernel is pinned and tracked as part of the build.

## Releases every two weeks, and tags that encode the target

EVE is described as an agile software project with a bi-weekly release schedule. Each release gets tagged with an x.y.z version in Git and a corresponding build is published on Docker Hub as `lfedge/eve:<version>-<hv>`, for example `lfedge/eve:17.9.0-kvm` or `lfedge/eve:17.9.0-k`.

The `hv` suffix is the interesting part, and it is not a single choice. The versions in the tag contain information about which hypervisor and target architecture are supported, and the options are listed as architecture `amd64`, `arm64` and `riscv64`, and hypervisor `kvm`, `k` and `mini`. Not all hypervisors are supported on all architectures.

The examples in the README show how the tag is assembled. `docker run lfedge/eve:8.11.0-kvm-arm64` is the installer for 8.11.0 using kvm on arm64, and `docker run lfedge/eve:8.11.0-mini-riscv64` is the installer for 8.11.0 using mini on riscv64. If you leave off the architecture it defaults to whatever architecture you are running on, and the hypervisor is always part of the tag, so `docker run lfedge/eve:8.11.0-kvm` gives you the installer for your own architecture and `docker run lfedge/eve:17.9.0-k` the k variant.

Each Docker image is built for the architecture it runs on, which is the point of the `--platform` flag. The README gives both forms.

```sh
docker run --platform=linux/arm64 lfedge/eve:8.11.0-kvm-arm64
```

```sh
docker run --platform=linux/amd64 lfedge/eve:8.11.0-kvm-amd64
```

The README notes that this is unnecessary but does no harm if you are already running on the target architecture. On a machine such as an Apple Silicon Mac, the arm64 image works directly, and on amd64 Docker will normally pick the right architecture on its own.

The version numbers in the release history are worth noting. The recorded releases are 17.10.0 from 2026-10-16, 17.0.1-rc3 from 2026-10-17 and 17.9.0 from 2026-10-09, and the latest LTS release is linked separately from the main release list. The presence of an rc in the list shows the release process produces candidates as well as finals, and the LTS channel is a separate stream from the bi-weekly one, which is what you want for a device fleet where you cannot afford to change versions every fortnight.

## Why you cannot just docker run it

There is a sentence in the README that stops most first attempts, and it is worth quoting in spirit.

Since EVE is not just an application, but a compute engine that expects to be deployed on real or virtualized hardware, you cannot simply do `docker run` to give it a try. Instead, you need to use the EVE Docker container to produce one of the artifacts that you can then either run on bare metal hardware or deploy on virtualized infrastructure such as Google Compute Platform.

So the Docker image is a build tool, not the product. You run the container to produce an installer or a disk image, and that artefact is what boots on the device. The distinction matters because the two have completely different lifecycles: the container runs once on your workstation and the image it produces runs forever on the device.

The help text is the way to find out what the container can produce. The README suggests running `docker run lfedge/eve:<version>-kvm` to get the most up-to-date help message, and notes that `<command>` is the appropriate command to run and that leaving it blank gives the help message.

For the local development environment there is a compose file, and it shows the shape of the running system. It defines four named volumes, `persist`, `config`, `run` and `version`, and a bridge network called `eve` with IPv6 enabled and two subnets, one IPv6 in the fde3:84ac:fc48::/48 range and one IPv4. The services are the parts of EVE you can run as containers on a workstation: `storage-init`, which is the only service from the onboot section, `edgeview`, which runs privileged with the host's proc mounted read-only and the network namespace of the host, and `newlogd`.

The bridge network configuration is set with masquerading and inter-container communication enabled, and a MTU of 1500, which is the standard Ethernet value. The compose file also has a commented-out `ipvlan` network definition with a parent interface, which suggests an alternative networking mode for a device that is bridging a physical network rather than running behind NAT.

The `edgeview` service is the one to know about, because `edgeview` is a debugging tool in the EVE world and it is what lets you inspect a running device's state, and running it against a live device in a container is a common way to see what a device thinks it is doing.

## Building from source, and the toolchain it expects

To build EVE itself you need QEMU 3.x or newer, Docker, Make and Go 1.13 or newer installed, and the README walks through the rest.

Docker has to be running, and the check is worth doing properly. Run `docker version` and make sure that it returns both a version of the client and a version of the server, because a client without a server is the usual cause of a confusing first failure.

The system dependencies differ by platform. On macOS with Homebrew it is `brew install git make jq qemu gnu-sed`, and the note for M1 Macs is that qemu may also require `python3 nettle ninja gnu-tar` to install properly, giving the longer command `brew install git make jq python3 nettle ninja qemu gnu-sed gnu-tar`. On Ubuntu it is a longer apt line covering git, make, jq, qemu, binfmt-support, qemu-user-static, qemu-utils, qemu-system-x86 and qemu-system-aarch64.

The cross-architecture step is the one that is easy to miss. To enable execution of different multi-architecture containers, which is required on Linux and required to create EVE bootable images with a different architecture than the host, you run the multiarch/qemu-user-static container with reset.

```sh
$ docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
```

That registers the binfmt handlers so the Docker daemon can execute foreign-architecture binaries, which is how you build an arm64 image on an amd64 workstation. The `binfmt-support` package in the Ubuntu dependency list is the daemon-side half of the same feature.

The Makefile gives the constants that define the build, and they are worth reading. `HV_DEFAULT=kvm` with a comment that you use `make HV=kvm|k` to build KVM or k, and `GOVER ?= 1.25.12` as the Go version. `IMG_FORMAT=qcow2` is the disk image format, and `PROTO_LANGS=go python` says which language bindings to generate for the EVE API, which is the interface between the device and the controller.

The media size is one of the more revealing settings. For the k hypervisor the default is 65536 megabytes and for everything else 32768, with the comment that k defaults larger so Longhorn on /persist has room after its 25 percent reserve, and that the kube-init pre-flight warns otherwise. Longhorn is a storage system, and the comment tells you that the k variant ships with a block storage stack, which is the practical difference between the two hypervisors beyond the virtualisation technology itself.

The build is also configured for live updates, with a `LIVE_UPDATE` flag that switches the root filesystem to ext4 so it can be written to, and a `LIVE_FAST=1` that generates the tar faster.

## The controller story and where EVE does not fit

A device operating system is only half of a deployment, and the README is clear that the recommended path involves a controller.

EVE-OS can be used with the open source Adam controller by following the instructions at Eden, and there are ongoing development of EVE-OS tutorials.

So the intended workflow is: a controller provisions a device, the device boots into EVE, and EVE then runs the applications the controller tells it to run, and reports back. A device that is provisioned by hand works, but the model is fleet management, and the tooling around it, the API defined by the protobuf bindings with Go and Python generated, exists for that reason.

Three limits are worth stating.

The first is that EVE requires hardware-assisted virtualization. That excludes a surprising number of cheap boards, and it means the board support list is a real constraint rather than a formality. The presence of a `boards/` directory in the repository suggests the list is maintained, and it is the first thing to check against your hardware.

The second is the size of the thing. EVE is an operating system with a hypervisor, a controller protocol, an update mechanism and a device API. If your problem is running three containers on one box, that is what Docker does, and it does it with a fraction of the complexity and a fraction of the boot time. EVE earns its weight when you have many devices to manage as a fleet, when the hardware has to be partitioned between mutually distrusting tenants, or when you need a consistent, remotely updatable image across hardware that varies.

The third is the operational surface. A bi-weekly release cadence with a separate LTS stream, a provisioning model, an update mechanism and a device API is a system with a real learning curve. The alternatives in the same space are a plain container runtime on the device with a fleet management layer on top, which is simpler and gives up the partitioning, and a full virtualisation platform with a hypervisor you install yourself, which gives up the integrated provisioning and update path that EVE provides.

The honest summary is that EVE is infrastructure for a specific shape of deployment, one where a large number of small heterogeneous devices need to be provisioned and updated as a fleet with hard isolation between workloads. If that is your problem, the fact that it is built from QEMU, LinuxKit and Alpine with a Go orchestration layer means you are standing on projects that already have years of hardening behind them, and that is a genuine argument in its favour.

## Conclusion

EVE suits a vendor or operator deploying applications to fleets of edge boxes that need hardware partitioning, a consistent boot and update mechanism, and a controller that can manage them as a group. It does not suit a single-server application, since EVE is a compute engine with a boot and provisioning model rather than something you run alongside your workloads. Verify first that the hypervisor variant in the image tag matches the hardware you will deploy to, because the tag encodes both the architecture and the hypervisor and not every combination is supported, that your board is on the supported list, and that the Go version the build expects matches the one in the Makefile.

## FAQ

### What is EVE?

EVE is the Edge Virtualization Engine, a Linux Foundation project that provides hardware-assisted virtualization on edge devices, with direct access to and control of the underlying resources so that hardware can be partitioned between workloads. It supports ARM and Intel architectures and runs on devices from a $20 Orange Pi up to industrial PCs.

### Which open source projects does EVE build on?

The README names QEMU, LinuxKit and Alpine Linux among the projects EVE builds on, with LinuxKit assembling the bootable image and QEMU providing the virtual machines. The orchestration and device management is EVE's own Go code, and the Makefile points at pkg/pillar as the module and tree used for it.

### How do I run EVE?

You cannot simply docker run it, because it is a compute engine that expects to run on real or virtualized hardware. You run the lfedge/eve container to produce a deployment artifact, an installer or disk image, and then run that on bare metal or on virtualized infrastructure such as Google Compute Platform.

### What do the tags on the lfedge/eve images mean?

The tag has the form lfedge/eve:<version>-<hv>, optionally with the architecture, and it encodes both. The supported architectures are amd64, arm64 and riscv64, and the hypervisors are kvm, k and mini, though not every hypervisor is supported on every architecture. The image also exists for the LTS release channel.

### What do I need to build EVE from source?

QEMU 3.x or newer, Docker, Make and Go 1.13 or newer, plus the system dependencies for your platform. On Linux you also need binfmt support enabled for cross-architecture builds, which the README covers with the multiarch/qemu-user-static container run with --reset -p yes.

## Sources

- [lf-edge/eve on GitHub](https://github.com/lf-edge/eve)
- [License: Apache-2.0](https://github.com/lf-edge/eve/blob/master/LICENSE)
- [Project website](https://www.lfedge.org/projects/eve/)
- [README](https://github.com/lf-edge/eve/blob/master/README.md)
- [Releases](https://github.com/lf-edge/eve/releases)

---

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