Skip to content

Latest commit

 

History

History

ic-os

IC-OS

Introduction

IC-OS is an umbrella term for all the operating systems within the IC, including SetupOS, HostOS, GuestOS, and Boundary-guestOS.

  • SetupOS: Responsible for booting a new replica node and installing HostOS and GuestOS.

  • HostOS: The operating system that runs on the host machine. Its main responsibility is to launch and run the GuestOS in a virtual machine. In terms of its capabilities, it is intentionally limited by design to not perform any trusted capabilities.

  • GuestOS: The operating system that runs inside a virtual machine on the HostOS. The core IC protocol is executed within the GuestOS.

  • Boundary-GuestOS: The operating system that runs on boundary nodes. It contains all the services necessary to fulfill the two main tasks of the boundary nodes: (1) route ICP API requests to a healthy replica of the right subnet (ic-boundary); and (2) translate HTTP requests into ICP API requests to allow direct access to dapps from the browser.

Managing IC-OS files

For details on adding to and removing files from IC-OS builds, refer to the components/ documentation

Building IC-OS images

All the IC-OS images can be built though Bazel.

Environment setup

Building IC-OS images locally requires environment configuration. The required packages are found in ic/ci/container/Dockerfile.

In addition to these packages, Bazel must be installed.

As an alternative, the following script can be used to build the images in a container with the correct environment already configured:

./ci/container/container-run.sh

Build targets

Each image has its own build targets, which are variations of the image:

  • SetupOS: prod, dev

  • HostOS: prod, dev

  • GuestOS: prod, dev, dev-malicious

  • BoundaryGuestOS: prod, dev

The difference between production and development images is that the console can be accessed on dev images, but not on prod images.

Note: The username and password for all IC-OS dev images are set to root

Building images

Use the following command to build images:

$ bazel build //ic-os/{setupos,hostos,guestos,boundary-guestos}/envs/<TARGET>/...

All IC-OS image build outputs are stored under /ic/bazel-bin/ic-os/{setupos,hostos,guestos,boundary-guestos}/envs/<TARGET>

Example:

$ bazel build //ic-os/guestos/envs/dev/...
# This will output a GuestOS image in /ic/bazel-bin/ic-os/guestos/envs/dev

Under the hood: Building an image

IC-OS images are first created as docker images and then transformed into "bare-metal" or "virtual-metal" images that can be used outside containerization.

Rather than installing and relying on a full-blown upstream ISO image, the system is assembled based on a minimal Docker image with the required components added. This approach allows for a minimal, controlled, and well understood system - which is key for a secure platform.

Note
For a detailed overview of the build process, refer to the Bazel icos_build macro

The main build stages are as follows:

Docker

The docker build process is split into two dockerfiles. This split is necessary to ensure a reproducible build.

Dockerfile.base

ic/ic-os/{setupos,hostos,guestos,boundary-guestos}/context/Dockerfile.base
  • The Dockerfile.base takes care of installing all upstream Ubuntu packages.

  • Because the versions of these packages can change at any given time (as updates are published regularly), in order to maintain build determinism, once a week, the CI pipeline builds a new base image for each OS. The result is published on the DFINITY public Docker Hub.

Dockerfile

ic/ic-os/{setupos,hostos,guestos,boundary-guestos}/context/Dockerfile
  • The Dockerfile builds off the published base image and takes care of configuring and assembling the main disk-image.

  • Any instruction in this file needs to be reproducible in itself.

Image Transformation

The docker image is then transformed into a bootable "bare-metal" or "virtual-metal" VM image for use outside containerization (either in a VM or as a physical host operating system). The resulting image is minimal, with only a few systemd services running.

Note that all pre-configuration of the system is performed using docker utilities, and the system is actually also operational as a docker container. This means that some development and testing could be done on the docker image itself, but an actual VM image is still required for proper testing.

Injection of additional binaries

As a caching optimization, additional IC services, configuration, scripts and binaries are added to the image late in the build process.

IC-OS Directory Organization

  • components/: This directory contains scripts and components that are copied to the target IC-OS.

  • bootloader/: This directory contains everything related to building EFI firmware and the GRUB bootloader image.

  • scripts/: This directory contains build and utility scripts for the IC-OS.

Adding a new dependency to an IC-OS image

To add a new package to an IC-OS image you need to:

  • Update the list of packages to install in ic/ic-os/{setupos,hostos,guestos,boundary-guestos}/context/packages.common

    • Commit the changes and wait for CI to publish the base image

  • Update the base image hash in ic/ic-os/{setupos,hostos,guestos,boundary-guestos}/context/docker-base.<env>