DocsReleasesCommunityGuidesBlog

Kraftfile Reference (v0.6)

This document contains information about how to write a Kraftfile which is used to configure, build, package and deploy your application as a Unikraft unikernel.

This document contains the latest Kraftfile specification information.

The Kraftfile is the static configuration file used to programmatically build, run, package and deploy a unikernel using kraft. This document contains information about how to set that configuration including how to program Unikraft's core build system, third-party libraries, syntax options and more.

A Kraftfile is typically found at the top-level of a repository. It is possible to change this location using -K|--kraftfile in relevant sub-commands of kraft.

File names#

For legacy reasons, the following file names are automatically recognized by kraft where Kraftfile is the latest preferred name:

  • Kraftfile
  • kraft.yaml
  • kraft.yml

Top-level spec attribute#

All Kraftfiles MUST include a top-level spec attribute which is used by kraft to both validate as well as correctly parse the rest of the file. The latest spec number is v0.6:

spec: v0.6

The spec element, for legacy reasons, can also be specified as specification, for example:

specification: v0.6

Top-level name attribute#

An application name CAN specified, for example:

spec: v0.6
name: helloworld

When no name attribute is specified, the directory's base name is used. In some cases, a --name flag can also be used, e.g. in kraft pkg and kraft cloud deploy.

Top-level cmd attribute#

A cmd attribute CAN be specified as an array or string which can be used for setting default arguments to be used during the instantiation of a new unikernel instance.

Specified as an in-line array#

spec: v0.6
cmd: ["-c", "/nginx/conf/nginx.conf"]

Specified as a multi-line array#

spec: v0.6
cmd:
- -c
- /nginx/conf/nginx.conf

Specified as a string#

spec: v0.6
cmd: "-c /nginx/conf/nginx.conf"

Specifying kernel parameters#

The cmd attribute respects the Unikraft uklibparam convention of separating kernel arguments from application arguments via the -- delimiter, for example as a multi-line array:

spec: v0.6
cmd:
# Kernel arguments
- env.vars=[ "HOME=/" ]
# Delimiter
- --
# Application arguments
- -c
- /nginx/conf/nginx.conf

Top-level volumes attribute#

Read the main document on enabling, using and seeding filesystems in your application with Unikraft.

A volumes attribute CAN be specified to declare the list of runtime mounts which are provided to the unikernel machine instance.

In all cases when specifying the volumes element, there are two forms of syntax that can be used in the Kraftfile, known as "short-hand" and "long-hand" depending on preference.

When specifying a destination path, this MUST be represented as an absolute path.

Short-hand syntax#

In its most simple form, a source path on the host is mapped to a destination path in the unikernel using a colon (:) delimiter. For every item in the list of volumes, the source is automatically inspected to determine its driver.

spec: v0.6
volumes:
- ./src:/dest

In the above example, ./src represents a path which points to a directory on the host which is made possible via the 9P File System driver.

Long-hand syntax#

spec: v0.6
volumes:
- source: ./src
destination: /dest
driver: 9pfs
readOnly: false

Top-level rootfs attribute#

Read the main document on enabling, using and seeding filesystems in your application with Unikraft.

The rootfs element CAN be specified to define the root filesystem. In every case of being specified, the resulting artifact which is passed to the unikernel machine instance is a read-only CPIO archive. Depending on the provided path, kraft will dynamically serialize the path into such an archive.

The provided path to the rootfs element can be one of the following:

When invoking kraft build or kraft run and the provided path of the rootfs is either a directory or a Dockerfile, the resulting filesystem will be dynamically serialized and stored in .unikraft/build/initramfs.cpio.

Specifying an existing CPIO archive (initramfs file)#

spec: v0.6
rootfs: ./initramfs.cpio

Specifying a directory#

spec: v0.6
rootfs: ./rootfs/

Specifying a Dockerfile#

spec: v0.6
rootfs: ./Dockerfile

Top-level unikraft attribute#

The unikraft attribute CAN be specified and is used to define the source location of the Unikraft core which contains the main build system and core primitives for connecting your application as well as any third-party libraries or drivers and building the two together "from source".

If no unikraft element is specified, one of either template or runtime MUST otherwise be specified.

In all cases when specifying the unikraft element, there are two forms of syntax that can be used in the Kraftfile, known as "short-hand" and "long-hand" depending on preference.

Setting a specific version#

The attribute can be specified in multiple ways, the most common is simply to request the latest from a "stable" channel of Unikraft, e.g.:

spec: v0.6
name: helloworld
# Short-hand syntax
unikraft: stable
# Long-hand syntax
unikraft:
version: stable

The Unikraft project adopts two-channel release mode via stable and staging. Specifying the latter will provide to you bleeding-edge version of Unikraft.

To specify a specific version of Unikraft, including a specific Git commit, you simply set it as follows:

spec: v0.6
name: helloworld
# Short-hand for a specific version of Unikraft
unikraft: v0.14.0
# Long-hand for a specific version of Unikraft
unikraft:
version: v0.14.0
# Short-hand for a specific commit of Unikraft
unikraft: 70bc0af
# Long-hand for a specific commit of Unikraft
unikraft:
version: 70bc0af

Setting a specific source location#

If you wish to use a copy of the Unikraft core code which is a remote fork or mirror, it is possible to set this as the entry for the attribute. When specified like so, the top of the HEAD of the default branch will be used:

spec: v0.6
name: helloworld
# Short-hand syntax
unikraft: https://github.com/unikraft/unikraft.git
# Long-hand syntax
unikraft:
source: https://github.com/unikraft/unikraft.git

Alternatively, a specific tag, branch or Git SHA can be specified by setting:

spec: v0.6
name: helloworld
# Short-hand syntax for a specific branch
unikraft: https://github.com/unikraft/unikraft.git@staging
# Long-hand syntax for a specific branch
unikraft:
source: https://github.com/unikraft/unikraft.git
version: staging
# Short-hand syntax for a specific tag
unikraft: https://github.com/unikraft/unikraft.git@RELEASE-0.14.0
# Long-hand syntax for a specific ta
unikraft:
source: https://github.com/unikraft/unikraft.git
version: RELEASE-0.14.0
# Short-hand syntax for a specific commit
unikraft: https://github.com/unikraft/unikraft.git@70bc0af
# Long-hand syntax for a specific commit
unikraft:
source: https://github.com/unikraft/unikraft.git
version: 70bc0af0bd1c74b3af3c0584d7b7373dc42b2ce7

It is possible to access remote repositories which requires authentication over SSH, simply set this as part of the scheme:

spec: v0.6
name: helloworld
# Short-hand syntax for specifying an authenticated Git repository over SSH,
# which will select the default branch
unikraft: ssh://git@github.com/unikraft/unikraft.git
# Long-hand syntax for specifying an authenticated Git repository over SSH, and
# specifying a specific branch (or tag)
unikraft:
source: ssh://git@github.com/unikraft/unikraft.git
version: staging

To use Git authentication over SSH, you must start an SSH agent before invoking kraft, for example:

eval `ssh-agent`
ssh-add ~/.ssh/id_ed25519

Finally, it is possible to set the location of Unikraft's core to a path on the host. This is useful when you are hacking at the core directly or working whilst traveling and do not have access to an internet connection:

spec: v0.6
name: helloworld
# Short-hand sytnax for a specific path on disk
unikraft: path/to/unikraft
# Long-hand syntax for a specific path on disk
unikraft:
source: path/to/unikraft

Specifying KConfig configuration#

To declare any specific options from Unikraft's configuration system, you must always use the long-hand syntax. All KConfig options start with CONFIG_ and can be set in either list format with key and value delimetered with an equal (=) symbol or in map format:

spec: v0.6
name: helloworld
# Using list-style formatting
unikraft:
kconfig:
- CONFIG_EXAMPLE=y
# Using map-style formatting
unikraft:
kconfig:
CONFIG_EXAMPLE: "y"

A more complex example#

All three sub-attributes, source, version and kconfig, can be used together to generate a very specific definition of the Unikraft core:

spec: v0.6
name: helloworld
unikraft:
source: https://github.com/unikraft/unikraft.git
version: stable
kconfig:
CONFIG_EXAMPLE: "y"

Top-level runtime attribute#

The runtime attribute CAN be specified and is used to access a pre-built unikernel. The unikernel runtime can be specified either as a path to an OCI image, a directory representing a project (i.e. one which contains a Kraftfile) or a path to a unikernel binary image.

If no runtime element is specified, one of either template or unikraft MUST otherwise be specified.

The runtime attribute is a powerful primitive for re-using pre-built unikernel images. Whilst the unikraft element allows for ultimate customization of the unikernel binary, this is not always necessary for new projects. For example, you may wish to simply program a Python3 application and not wish to

a) build the unikernel representing the python3 runtime for all projects b) care not for making customizations to the kernel at all

The Unikraft Open-Source Project hosts a public access unikernel registry of images which can be viewed directly in your terminal. Simply call the following to see the latest applications:

kraft pkg ls --apps --update

To view applications for different platforms and architecture which do not match your host:

kraft pkg ls --apps --update --all

All of these applications are built openly in our community catalog.

To get started using an existing runtime, which represents either an off-the-shelf application such as NGINX or Redis, or a high-level language runtime such as Python3 or Ruby, you can simply set the name of the image in the runtime element:

spec: v0.6
runtime: unikraft.org/python3:latest

The runtime element can be used as simply as the above snippet but becomes more useful when customizing the filesystem. For example, loading a Python3 application into the filesystem and setting the path to the application to execute:

spec: v0.6
runtime: unikraft.org/python3:latest
volumes:
- ./src:/src
cmd: ["/src/main.py"]

The above example can then simply be executed with kraft run.

Top-level template attribute#

The template attribute CAN be specified to reference an external repository which contains an application based on another Kraftfile. This offers a convenient mechanism for customizing or re-using configuration or files across multiple applications.

If no template element is specified, one of either runtime or unikraft MUST otherwise be specified.

When using a template, the source of the template can be qualified by either specifying a component of type-application or as a path to a repository representing an application (whether on disk or remotely via Git).

Just like libraries and the unikraft element, the template is a component which can be expressed using different different syntaxes. If an application has been previously sourced via kraft pkg source then the template can be specified as simply as:

spec: v0.6
# Short-hand syntax
template: app/elfloader:stable
# Long-hand syntax
template:
name: elfloader
version: stable

Alternatively, the application can be specified:

# As a remote Git repository:
template: https://github.com/unikraft/app-elfloader.git
# As a tarball representing an application repository:
template: https://github.com/unikraft/app-elfloader/archive/refs/heads/stable.tar.gz
# Or finally as a directory on your host representing an application:
template: /home/unikraft/apps/elfloader

The process of applying the template's Kraftfile on top of another is achieved with an overlay mechanism. This means that elements which are included in the top-level Kraftfile will overwrite the template's when specified. For example, given the above top-level Kraftfile with no additional attributes, the template's attributes will be used verbatim.

To demonstrate the overlay approach, let's assume the following template with a top-level unikraft element and some targets:

spec: 0.6
name: template
unikraft:
version: stable
kconig:
- CONFIG_LIBVFSCORE=y
targets:
- qemu/x86_64

This template can be referenced as app/template:stable when sourced as a component via the package manager. When using a new top-level Kraftfile which references said template, we can make adjustments to the unikraft attribute, for example:

spec: 0.6
template: app/template:stable
unikraft:
version: staging

This will result in

spec: 0.6
- template: app/template:stable
-
- unikraft:
- version: stable
- kconig:
- - CONFIG_LIBVFSCORE=y
+
+ name: template
+
+ unikraft:
+ version: staging
+
+ targets:
+ - qemu/x86_64

Which results in:

spec: 0.6
name: template
unikraft:
version: staging
targets:
- qemu/x86_64

Top-level libraries attributes#

Additional third-party libraries CAN be specified as part of the build and are listed in map-format. Similar to the unikraft attribute, each library can specify a source, version and a set of kconfig options, for example:

spec: v0.6
name: helloworld
unikraft: stable
libraries:
# Short-hand syntax for specifying the library "musl" on the stable channel
musl: stable
# Long-hand syntax for specifying a library at a specified source, using a
# specific Git branch, and specifying additional KConfig options
lwip:
source: https://github.com/unikraft/lib-lwip.git
version: stable
kconfig:
CONFIG_LWIP_AUTOIFACE: "y"
CONFIG_LWIP_DHCP: "y"
CONFIG_LWIP_DNS: "y"
CONFIG_LWIP_IPV4: "y"
CONFIG_LWIP_SOCKET: "y"
CONFIG_LWIP_TCP_KEEPALIVE: "y"
CONFIG_LWIP_TCP: "y"
CONFIG_LWIP_THREADS: "y"
CONFIG_LWIP_UKNETDEV: "y"
CONFIG_LWIP_WND_SCALE: "y"

In the above example, two additional libraries are used, musl and lwip. The names of these libraries are determined by what is sourced via kraft's package manager.

Top-level targets attributes#

A target is defined as a specific destination that the resulting unikernel is destined for and consists at minimum of a specific platform (e.g. qemu or firecracker) and architecture (e.g. x86_64 or arm64) tuple. A project can have multiple targets depending on use case but MUST have at least one.

Each target consists of at minimum an architecture and platform combination, therefore a project with two targets of qemu/x86_64 and xen/arm64:

spec: v0.6
name: helloworld
unikraft: stable
targets:
- plat: qemu
arch: x86_64
- plat: xen
arch: arm64

Within the list of targets, the architecture and platform attributes can be abbreviated to arch and plat, respectively, and be used interchangeably:

targets:
- plat: qemu
arch: x86_64
targets:
- plat: qemu
architecture: x86_64
targets:
- platform: qemu
arch: x86_64

The list of targets can now accept an even shorter syntax where only the architecture and platform are desired in the list:

targets:
- qemu/x86_64

This shorthand syntax can be mixed with full target elements:

targets:
- qemu/x86_64
- platform: qemu
architecture: arm64
- plat: fc
arch: x86_64

When left without any flags, kraft build will prompt you for the intended target to build.

It is possible to define targets simply based on different runtime properties or requirements. This is possible by setting both a name sub-attribute and a set of Kconfig options, for example the following two targets both target qemu/x86_64 platform/architecture tuple but initialize the rootfs either based on 9pfs or initrd, respectively:

spec: v0.6
name: helloworld
unikraft: stable
targets:
- name: helloworld-qemu-x86_64-9pfs
plat: qemu
arch: x86_64
kconfig:
CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS: "y"
CONFIG_LIBVFSCORE_ROOTFS_9PFS: "y"
CONFIG_LIBVFSCORE_ROOTFS: "9pfs"
CONFIG_LIBVFSCORE_ROOTDEV: "fs0"
- name: helloworld-qemu-x86_64-initrd
plat: qemu
arch: x86_64
kconfig:
CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS: "y"
CONFIG_LIBVFSCORE_ROOTFS_INITRD: "y"
CONFIG_LIBVFSCORE_ROOTFS: "initrd"
Edit this page on GitHub

Connect with the community

Feel free to ask questions, report issues, and meet new people.

Join us on Discord!
®

Getting Started

What is a unikernel?Install CLI companion toolUnikraft InternalsRoadmap

© 2024  The Unikraft Authors. All rights reserved. Documentation distributed under CC BY-NC 4.0.