Kibotos

Try Kibotos on a single machine

This page shows how to install ctrl and node on one Linux machine, together with the PostgreSQL database and object storage they depend on, then build a Template and create your first Workspace. Apart from the downloads, the steps take about fifteen minutes. Use it to evaluate Kibotos before a full deployment.

A deployment installed this way is only suitable for evaluation: all components listen only on the local machine, the object storage uses the administrator credential directly, and all data lives on this one machine. For a production deployment, see Installation overview.

Overview

After installation, this machine runs:

ComponentSourceListens on
PostgreSQLDistribution package127.0.0.1:5432
Silo, an S3-compatible object storageDebian package released by Silo127.0.0.1:9000
ctrlkibotos-ctrl from the release set127.0.0.1:18092 (API), 127.0.0.1:18101 (node access)
node, using the KiboVM backendkibotos-node from the release set127.0.0.1:18091 (data plane)
kibo and kibo-buildRelease setDoes not listen

Certificates for ctrl and node are issued for names. This page writes the two names ctrl.kibotos.test and node-a.nodes.kibotos.test into /etc/hosts, both pointing to 127.0.0.1. kibo also runs on this machine.

Prerequisites

  • A Debian 13 amd64 machine, on which this page was verified. At least 4 CPUs, 8 GiB of memory, and 40 GiB of free disk space.
  • /dev/kvm and /dev/net/tun exist, cgroup v2 is in use, and time synchronization is on. To try it in a virtual machine, enable nested virtualization.
  • You can use sudo and reach the public internet, to download the release set, Silo, and the container image for the Template.
  • The release set is downloaded from GitHub, which requires a GitHub account with read access to the Kibotos source repository.
  • Docker is not running on this machine. Docker changes the default policy of the FORWARD chain to DROP, and Workspaces then cannot reach the network. See Troubleshooting.

Run the steps below in order in the same terminal. Later steps use variables set in earlier ones.

Steps

1. Check the host

Confirm the virtualization devices, cgroup version, and time synchronization:

ls -l /dev/kvm /dev/net/tun
stat -fc %T /sys/fs/cgroup
timedatectl show -p NTPSynchronized

The second command should print cgroup2fs, and the third should print NTPSynchronized=yes.

2. Download the release set

Install the tools you need, log in to GitHub, then download and verify the release set of one version. Replace version with the version you want to try:

sudo apt-get install -y gh jq curl openssl
version=1.2.3
gh auth login
gh api -H 'Accept: application/vnd.github.raw' \
  "repos/felinics/kibotos/contents/scripts/fetch-release.sh?ref=v$version" > fetch-release.sh
bash fetch-release.sh "v$version"
cd "kibotos-releases/v$version"
sha256sum --check SHA256SUMS

Run all later commands in this directory.

3. Install PostgreSQL and Silo

Install PostgreSQL and create an account and a database for ctrl:

sudo apt-get install -y postgresql
db_password=$(openssl rand -hex 16)
sudo -u postgres psql -c "CREATE ROLE kibotos LOGIN PASSWORD '$db_password'"
sudo -u postgres createdb -O kibotos kibotos

Download and install Silo, have it listen only on the local machine, and keep its data in /var/lib/silo:

silo_release=https://github.com/pgsty/silo/releases/download/RELEASE.2026-09-16T00-00-00Z
curl -fLO "$silo_release/silo_20260916000000.0.0-1PGSTY_amd64.deb"
curl -fLO "$silo_release/silo_20260916000000.0.0-1PGSTY_amd64.deb.sha256sum"
sha256sum --check silo_20260916000000.0.0-1PGSTY_amd64.deb.sha256sum
sudo apt-get install -y ./silo_20260916000000.0.0-1PGSTY_amd64.deb
silo_password=$(openssl rand -hex 16)
sudo install -d -o silo -g silo -m 0700 /var/lib/silo
sudo install -m 0600 /dev/null /etc/default/silo
sudo tee /etc/default/silo >/dev/null <<EOF
MINIO_VOLUMES="/var/lib/silo"
MINIO_OPTS="--address 127.0.0.1:9000 --console-address 127.0.0.1:9001"
MINIO_ROOT_USER="kibotos"
MINIO_ROOT_PASSWORD="$silo_password"
EOF
sudo systemctl enable --now silo.service

Create the bucket that ctrl uses. curl calls the Silo API directly with an S3 signature:

until curl -fsS http://127.0.0.1:9000/minio/health/live; do sleep 1; done
curl -fsS --aws-sigv4 'aws:amz:us-east-1:s3' --user "kibotos:$silo_password" \
  -X PUT http://127.0.0.1:9000/kibotos-artifacts

4. Prepare names

Point the ctrl and node names to the local machine:

printf '%s\n' '127.0.0.1 ctrl.kibotos.test node-a.nodes.kibotos.test' | sudo tee -a /etc/hosts >/dev/null
getent hosts ctrl.kibotos.test node-a.nodes.kibotos.test

5. Install and start ctrl

Install the ctrl package and write the configuration:

sudo apt-get install -y "./kibotos-ctrl_${version}_amd64.deb"
sudo install -o kibotos-ctrl -g kibotos-ctrl -m 0600 /dev/null /etc/kibotos/ctrl/config.toml
sudo tee /etc/kibotos/ctrl/config.toml >/dev/null <<EOF
[database]
dsn = "postgresql://kibotos:$db_password@127.0.0.1:5432/kibotos"

[identity]
trust_domain = "kibotos.test"
host = "ctrl.kibotos.test"

[storage]
root = "/var/lib/kibotos/ctrl"

[api]
listen = "127.0.0.1:18092"

[node_api]
listen = "127.0.0.1:18101"

[data_plane]
host_suffix = "nodes.kibotos.test"

[template_artifact_store]
endpoint = "127.0.0.1:9000"
region = "us-east-1"
bucket = "kibotos-artifacts"
namespace = "trial"
secure = false
path_style = true
credential_source = "static"
access_key_id = "kibotos"
secret_access_key = "$silo_password"
EOF

Initialize ctrl, issue the enrollment key for the first Operator, then start the service:

sudo -u kibotos-ctrl kibotos-ctrl init --config /etc/kibotos/ctrl/config.toml
sudo -u kibotos-ctrl kibotos-ctrl migrate --config /etc/kibotos/ctrl/config.toml
sudo -u kibotos-ctrl kibotos-ctrl enrollment create \
  --config /etc/kibotos/ctrl/config.toml --operator admin \
  --output /var/lib/kibotos/ctrl/operator-enrollment.key
sudo systemctl enable --now kibotos-ctrl.service

6. Install kibo and enroll

Install kibo and create the Operator identity with the key from the previous step:

sudo install -m 0755 "kibo_${version}_linux_amd64" /usr/local/bin/kibo
(umask 077; sudo cat /var/lib/kibotos/ctrl/operator-enrollment.key > operator-enrollment.key)
sudo rm /var/lib/kibotos/ctrl/operator-enrollment.key
kibo context enroll --endpoint https://ctrl.kibotos.test:18092 --key-file operator-enrollment.key
rm operator-enrollment.key
kibo version

The output of kibo version should contain Compatible yes.

7. Install node and join

Issue an enrollment key for the node, install the node package, and turn on IPv4 forwarding:

kibo enrollment create --node node-a --output node-enrollment.key
sudo apt-get install -y "./kibotos-node_${version}_amd64.deb"
printf '%s\n' 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/60-kibotos-forward.conf >/dev/null
sudo sysctl -p /etc/sysctl.d/60-kibotos-forward.conf

Write the node configuration. It gives Workspaces 2 CPUs and 4 GiB of memory, and reaches the public internet through the network interface of the default route:

uplink=$(ip -4 route show default | awk '{print $5; exit}')
sudo install -m 0600 /dev/null /etc/kibotos/node/config.toml
sudo tee /etc/kibotos/node/config.toml >/dev/null <<EOF
[backend]
type = "kibovm"

[resources]
cpu_limit = 2
memory_limit = "4G"

[storage]
root = "/var/lib/kibotos/node"
template_cache_limit = "10G"

[[storage.pool]]
id = "node-a"
path = "/var/lib/kibotos/node"

[runtime]
socket_root = "/run/kibotos/node"

[data_plane]
listen = "127.0.0.1:18091"
advertise = "https://node-a.nodes.kibotos.test:18091"

[ctrl]
endpoint = "https://ctrl.kibotos.test:18101"

[host_network]
address_families = ["ipv4"]
ipv4_pool = "100.64.0.0/16"

[host_network.public_internet]
ipv4_upstream_interface = "$uplink"
resolvers = ["1.1.1.1"]
EOF

Initialize the storage pool, join the cluster, and start the service:

sudo kibotos-node storage-pool init --id node-a --path /var/lib/kibotos/node
sudo kibotos-node join --config /etc/kibotos/node/config.toml --key-file node-enrollment.key
rm node-enrollment.key
sudo systemctl enable --now kibotos-node.service

Wait for the node to become READY, then set the capacity of its storage pool:

until kibo node get node-a | grep -q READY; do sleep 2; done
kibo storage-pool set-capacity node-a 20G
kibo node list

8. Publish a Platform

A Platform is the kernel and guest programs that a Workspace boots with. The release set already contains a built one. Publish it, approve it, and set it as the default:

kibo platform publish "kibotos-platform-kibovm_v${version}_amd64.tar.zst" --json > platform.json
platform_revision=$(jq -er '.result.platform.revision' platform.json)
kibo platform approve "$platform_revision"
kibo platform set-default "$platform_revision"

9. Build and publish a Template

A Template determines what is installed in a Workspace. Here you import a Debian system with curl from the official Docker Hub image buildpack-deps:trixie-curl. Install the build tool, look up the exact digest of the image, and write the definition file:

sudo apt-get install -y "./kibo-build_${version}_amd64.deb"
digest=$(skopeo inspect --format '{{.Digest}}' docker://docker.io/library/buildpack-deps:trixie-curl)
sudo install -d /srv/templates/debian
sudo tee /srv/templates/debian/template.json >/dev/null <<EOF
{
  "schema": "kibotos.template-definition/v1",
  "template_id": "debian",
  "display_name": "Debian 13 with curl",
  "description": "Imported from docker.io/library/buildpack-deps:trixie-curl",
  "platform": "linux/amd64",
  "architecture": "x86_64",
  "source": {
    "kind": "registry",
    "reference": "docker.io/library/buildpack-deps@$digest"
  },
  "platform_requirements": {
    "guest_protocol": 1,
    "rootfs_contract": 2
  },
  "guest": {
    "capabilities": ["filesystem.v1", "process.v1", "application-config.v1"],
    "ready_semantics": "vsock-http-ready/v1"
  },
  "required_capabilities": {},
  "rootfs": {
    "size_mib": 1024
  },
  "process_defaults": {
    "shell": "/bin/bash"
  }
}
EOF

Build it, then publish, approve, and set it as the default:

template_result=$(sudo kibo-build template /srv/templates/debian/template.json)
kibo template publish "$template_result" --json > template.json
template_revision=$(jq -er '.result.template.revision' template.json)
kibo template approve debian --revision "$template_revision"
kibo template set-default debian --revision "$template_revision"
kibo template list

10. Create your first Workspace

Create a Workspace, run a command in it, then delete it:

workspace_id=$(kibo workspace create --template debian -q)
kibo workspace exec "$workspace_id" -- cat /etc/debian_version
kibo workspace delete "$workspace_id" --yes

The first time a Template is used, the node must download and unpack the rootfs first, so creation takes a little longer.

The deployment is now ready to use. Continue from step 3 of the Quickstart, using the Template debian.

Notes

  • All components listen only on 127.0.0.1, so you can use kibo only on this machine. To access it from another machine, change the listen addresses in the configuration to 0.0.0.0, and have that machine resolve the two names to this machine's address. Publishing a Template uploads straight to object storage, so also make Silo listen on a reachable address and set the store endpoint in the ctrl configuration to it.
  • The object storage uses the Silo administrator credential. In a production deployment, give ctrl an identity that can access only its own bucket. See Prepare the bucket and permissions.
  • All data lives only on this machine, with no backup. The ctrl PKI is in /var/lib/kibotos/ctrl. If you lose it, all nodes and Operators must enroll again.
  • A production deployment can put ctrl and node on different machines. Follow the order in Installation overview.

Troubleshooting

SymptomCauseResolution
kibotos-ctrl.service restarts repeatedlyThe database or object storage is unreachable, or the credentials are wrongLook at sudo journalctl -u kibotos-ctrl.service -n 50. The reason field says which one
The node never becomes READYThe node did not start, or cannot reach ctrlLook at sudo journalctl -u kibotos-node.service -n 50
Creating a Workspace failsThe storage pool capacity is not set yet, or the Platform or Template is not set as the defaultFollowing the error message, redo the last part of step 7, or steps 8 and 9
The node log has node offers no public internet egressIPv4 forwarding is not on, or the default policy of the FORWARD chain is DROP (for example, because Docker is installed)Fix the cause stated in the log, then run sudo systemctl restart kibotos-node.service
kibo-build fails to download the imageThis machine cannot reach Docker HubUse a registry the machine can reach, and change reference in the definition file to the image there

Uninstall

Stop the services, remove the packages, then delete the data created on this page:

sudo systemctl disable --now kibotos-node.service kibotos-ctrl.service silo.service
sudo apt-get purge -y kibotos-node kibotos-ctrl kibo-build silo
sudo rm -rf /etc/kibotos/node /etc/kibotos/ctrl /var/lib/kibotos/node /var/lib/kibotos/ctrl \
  /var/lib/kibotos/build /var/lib/silo /etc/default/silo /srv/templates/debian \
  /etc/sysctl.d/60-kibotos-forward.conf
sudo -u postgres dropdb kibotos
sudo -u postgres dropuser kibotos
sudo sed -i '/ctrl\.kibotos\.test/d' /etc/hosts
rm -rf ~/.config/kibo/context

Next steps

On this page