Introduction to Unikernel: Building and Deploying Lightweight, Secure Applications

Avatar photo

Om Prakash Yadav

July 17, 2025

Have you ever wondered what it would be like to have everything in the world just for yourself — where every resource and every service is just for you? Imagine you have rented a private villa on a small, quiet island. Everything in the villa — the rooms, the pool, and the beach — is just for you. No other guests can use anything there, and the staff are there just for you. Isn’t that exciting? I’m sure it is!

This concept also applies to applications, which are given their own space to work in without interference from others and without sharing resources. Any application could thrive in such an environment. So, the question is: “Does such an application environment exist?”

Enter unikernels — a unique application environment that can provide an exclusive environment just like your private villa. They are compact, single-application virtual machines, boosting speed, efficiency, and security.

In this article, we will take a closer look at what unikernels are, explore the different types of unikernels, discuss their benefits and limitations, and learn how to create and deploy a simple Nanos application (a type of unikernel) on AWS.

What is a Unikernel and why do we need it?

Before we look at unikernels, let us first understand why we need something like unikernels in the first place, and examine the limitations of current operating systems like Linux and Windows that lead us to look for alternatives.

Traditional operating systems are designed to run multiple applications simultaneously, which requires careful resource management to ensure smooth operation. The operating system kernel also performs numerous background tasks via memory management, process scheduling, disk I/O and peripheral management. However, our backend applications often do not need these functions, and yet the kernel consumes a lot of memory and CPU power to support them.

The solution to the above problem is simple: if the operating system causes too much overhead, why not let the user-space program take control of the hardware directly? This way, the application essentially becomes part of the kernel, accesses the hardware with fewer obstacles and significantly reduces the overhead of the operating system.

This is exactly the goal of unikernels — fine-tuning for specific tasks. They are lightweight, specialized virtual machines designed to run a single application, making the system smaller, faster and more secure. This unique form of virtualization merges the application and operating system into a single executable image, eliminating the need for the extensive features and services of traditional operating systems.

This specialization makes the system simpler and reduces resource consumption. It only contains the essential components required for the respective application and is, therefore, much smaller than conventional operating systems. This lean design leads to faster boot times and lower memory consumption. In addition, the smaller attack surface of unikernels also improves security.

Since it is executed as a single process, there is no overhead from context switching between multiple processes, resulting in faster execution and lower latency. Once compiled, unikernels can be run on local devices on Linux with QEMU and even on various hypervisors such as Xen, KVM, Nitro System and ESXi.

These hypervisors handle the interaction with the underlying hardware, allowing unikernels to benefit from virtualization without the overhead of a full operating system. The following block diagram will help you to better understand and visualize the whole thing.

Types of Unikernel

Recently, we reached out to several unikernel teams for one of our projects, but only received a few responses. After investigating some of the unikernels, we realized that only two — Nanos and Unikraft — are on the path to stability. Although conceptually both have the same basic principle, they have their own methods for deploying unikernel images and instances.

The main differences between the two unikernels are listed in the table below. However, one of the main differences between Unikraft and Nanos is that Unikraft relies more on its own cloud structure called Unikraft Cloud (which is ultimately based on a bare metal instance) for better performance, while Nanos offers the ability to create its own image that can run on all instance types on all cloud providers supported by Nanos.

Building Nanos unikernel (step-by-step instructions)

We have mentioned about Unikraft, but let’s leave that aside for now and concentrate on nanos.

Creating a Nanos unikernel involves several steps, from setting up the environment to deploying the final image and instance. In addition, Nanos uses an operational tool called OPS that streamlines various tasks, such as image and instance creation.

Before we get into creating images and instances, we first need to build both Nanos and the OPS tool from source code. Alternatively, we could also use pre-built versions of OPS and Nanos to run our application (refer nanovms). However, in this article, we will focus on building Nanos and OPS from source code.

Build OPS and Nanos

Here is a simple step-by-step guide to help you create the OPS and Nanos code from scratch (source: nanovm ):

      1. The very first step is to set up a Linux computer as a host computer for various operational tasks. This can either be a local Linux computer on site or an AWS virtual machine.
      2. Make sure you have the latest version of Go (Golang) installed along with the GCC compiler and make.Log in to your Linux computer via SSH and make sure that the path to go is included in your Linux computer path.
        
         # Remove older version of go.
         sudo apt-get remove golang-go
         sudo apt-get remove --auto-remove golang-go
         sudo apt-get update
         sudo rm -rf /usr/local/go
        
         # Download the latest go version (above 1.22.1)
         wget https://go.dev/dl/go1.22.1.linux-amd64.tar.gz
        
         # Unzip the downloaded tar file
         sudo tar -C /usr/local -xzf ~//go*.linux-amd64.tar.gz
        
         # Set the path
         export PATH=$PATH:/usr/local/go/bin
        
         # Before we install GCC, update the packet list
         sudo apt-get update
        
         # Install GCC
         sudo apt-get install gcc
        
         # Verify the GCC Installation
         gcc --version
        
         # Install make
         sudo apt-get install make
        
        
      3. Log in to your Linux computer via SSH and make sure that the path to go is included in your Linux computer path.
        
        # Below path should be present in the Linux machine path.
        export PATH=$PATH:/usr/local/go/bin
        
      4. Clone the OPS source code to a folder of your choice.
        
        # Command to clone the source code
        git clone https://github.com/nanovms/ops.git
        
      5. Navigate to the cloned OPS directory and execute the following commands.
        
        # Installs dependencies for ops
        make deps       
        
        # Generates protobuf files.
        make generate    
        
        # Build the ops tool, which generates Ops binary.
        make build
        
      6. After completing the build, copy the OPS (exe) from the OPS directory to the folder “/home/ubuntu/. ops/bin/ops” (location for OPS in Ubuntu).
        
        # Copy OPS binary
        cp ops ~/.ops/bin/ops 
        
        # Update the path
        export PATH=$PATH:/home/ubuntu/.ops/bin
        
      7. Please note that to update the OPS code, you need to pull the latest code and run the following command.
        
        go build
        
      8. Clone and build Nanos source code
        
        # Clone Nanos code.
        git clone https://github.com/nanovms/nanos.git    
        
        # Build nanos code.
        make
        
      9. After successful build, copy the following files into the folder with the latest OPS version (please replace the OPS version (0.1.xx ) with the latest OPS version).
        
        # Copy the post build files.
        cp output/platform/pc/boot/boot.img ~/.ops/0.1.xx/. 
        cp output/platform/pc/bin/kernel.img ~/.ops/0.1.xx/.
        cp output/tools/bin/mkfs ~/.ops/0.1.xx/.
        cp -r output/klib/bin/* ~/.ops/0.1.xx/klibs/.
        
      10. Before creating an image and instance on AWS, make sure your ~/.aws/credentials file is set up correctly and create a bucket in S3 storage.
        
        # Run the below command to configure your AWS credentials.
        aws configure
        
        # Enter Access Key ID
        AWS Access Key ID:
        
        # Enter Secret Access Key
        AWS Secret Access Key:
        
        # Region details
        
        Default region name [ap-south-1]:
        
        # Output format
        Default output format [None]:
        
        # Install AWSCLI
        sudo apt install awscli
        
        # Run the following command to create a sample bucket on ap-south-1 region.
        aws s3api create-bucket --bucket --region ap-south-1
        
        

        Create image and instance


      11. Below is an example of the image configuration file. The detailed configuration of the OPS tool can be found under this link:
        
        # Image Config file
        
        {
        
            "Args": ["./sample application"],
        
            "CloudConfig" :{
                "Platform" :"aws",
                "ProjectID" :"",
                "Zone":""
                "BucketName":"",
        
        }
        

        Sample command for creating an image.

        
        ops image create -c  -i  -t aws 
        

        Once the image has been successfully created, it would look like this:

        
        ubuntu@ip-172-22-0-132:~/testing/testing$ ops image create -c instancenew.json -t aws -i unikernel_image file1
        100% |███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| (4098/4098, 399 it/s)
        aws image 'unikernel_image' created...

         

      12. Example of an instance configuration file.
        
        # Instance config file
        
        {
            "CloudConfig" :{
                "Platform" :"aws",
                "ProjectID" :"",
                "flavor":"",
                "Zone":"",
                "VPC": "",
                "Subnet":""
        
            },
        
            "RunConfig": {
                "Ports":["80","443","8080"]
             }
        
        }

        Sample command for creating an instance.

        
        ops instance create -c  -i   -t aws
        

        A successful instance creation would look like this:

        
        ubuntu@ip-172-22-0-132:~/testing/testing$ ops instance create -i unikernel_instance Unikernel_image -t aws -c instancenew.json
         Created security group sg-0f6b9bc85c2df01e3 with VPC vpc-3a45dc53.
         aws instance 'unikernel_instance' created...
        

        Here you can see an example of a successfully deployed and running nanos application on AWS (Running instance).

      13. Alternatively, we can use QEMU to run the Nanos image on our local Linux.

        
        # Make sure QEMU is installed.
        sudo apt-get install qemu-kvm
        sudo apt-get install qemu-system-x86
        

Linux vs Nanos comparison

To analyse the performance differences between Linux and Nanos in terms of I/O operations and execution time, we performed tests with some basic C++ code examples. The results can be found below.

  • Executed a C++ program to measure the time required for a CPU-intensive task that searches for prime numbers in the range 0 to 10,000,000. Observations have shown that Nanos consistently takes less time to complete the task compared to Linux, with small variations but generally stable averages.

            Execution time taken by Nanos

Execution time taken by Nanos

  • Similarly, we executed a sample program to determine the average time to execute an IO operation to read and write a file of size 2mb. The results show that Nanos performs better compared to Linux in terms of the average time required for one iteration of an IO operation. (observed that the readings are quite inconsistence here).

Nanos average time per IO iteration

Nanos average time per IO iteration

Use cases for Unikernels

Unikernels offer unique advantages that make them well-suited for a range of applications in various fields. While their suitability largely depends on the requirements of your project, here are some key use cases to keep in mind.

  • Unikernels can efficiently run lightweight microservices that consume minimal resources. Each microservice can be packaged as a unikernel, enabling rapid scaling and deployment in cloud environments.
  • Unikernels are well suited for environments in which fast boot times and low resource consumption are important.
  • Developers can quickly prototype and test applications with unikernels because the process of creating and deploying a unikernel is simple and efficient.

Challenges and limitations of Unikernels

While unikernels offer several advantages, their niche application and smaller ecosystem also come with some challenges and limitations that can affect their adoption and use. Here are some of the main concerns:

  • Creating unikernels can be more complicated than developing traditional applications, as developers need to be familiar with the specific unikernel frameworks. The tool, which is used for various operational activities, has limited functionality and must be extended according to requirements. For example, we cannot create multiple instances with a single command in OPS tool. The flexibility to create volumes of different types in different cloud providers is also limited.
  • The ecosystem for unikernels is less developed than that of traditional operating systems and container platforms. This can lead to a lack of libraries, tools and community support, making development and troubleshooting more difficult. Support for system calls is limited, which is always a problem for complex applications.
  • The network layer of Nanos (and other unikernels) is implemented with the LWIP (Lightweight IP) stack, which can affect performance for applications which require more ports and threads per port.
  • Debugging unikernels can be more complex due to their binary nature. Traditional debugging tools may not work as effectively, and the lack of a full operating system can make it difficult to diagnose problems.

Let us try to summarize what we have discussed about Unikernel and precisely about Nanos.

Unikernels provide a transformative approach to application deployment by combining applications with the necessary operating system components into a single executable image. This architecture not only improves performance and security, but also optimizes resource utilization, making unikernels particularly well suited for modern environments.

Their lightweight nature and short boot times can significantly reduce latency and improve data processing efficiency. In addition, unikernels facilitate lean microservices architectures that allow developers to deploy independent, scalable services with minimal overhead. However, like any emerging technology, unikernels also come with a number of challenges. The complexity of development, a less established ecosystem, troubleshooting difficulties and potential compatibility issues are all important factors to consider.

As technology advances and the ecosystem grows, unikernels will become an indispensable tool for developers and influence the future of efficient, flexible and secure application delivery.

Have you ever tried a unikernel? If so, we’d love to hear about your experiences! If not, feel free to ask us any questions about getting started!

 

left-icon
1

of

4
right-icon

India’s choice for business brilliance

TallyPrime is a complete business management software to manage your business easily, faster, and efficiently. Access to complete features, from billing to insightful reports.

Accounting and Billing | Inventory Management | Insightful Business reports | GST Returns and reconciliation | Connected e-invoice & e-way bill solution | Cash and Credit Management| Security and user management.

Get 7-days FREE Trial!

I have read and accepted the T&C
Submit