raft / docs

Installation and host setup

Set up a dedicated Ubuntu host, install the Raft CLI, provision Incus, acquire a workspace image, and verify readiness.

Review prerequisites in System requirements before starting.

Install prerequisites on the workspace host

Connect to your host over SSH, verify its host key fingerprint, and install baseline packages:

HOST: Install baseline system packages
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
  ca-certificates curl gnupg python3 openssh-server iptables btrfs-progs

Verify passwordless sudo on the host:

HOST: Verify passwordless sudo
sudo -n true && echo "Passwordless sudo is functional"

Clone repository and install controller CLI

On your controller machine, clone the repository and install the raft CLI tool using uv:

CONTROLLER: Clone repository and install CLI
git clone https://github.com/Microck/raft.git raft
cd raft
uv sync --locked
uv tool install --editable .

Add ~/.local/bin to PATH and verify the CLI:

CONTROLLER: Verify CLI installation
export PATH="$HOME/.local/bin:$PATH"
raft --help

Configure host inventory on the controller

The controller reads host definitions from ~/.config/raft/incus.json. Initialize the configuration directory and template:

CONTROLLER: Initialize configuration file
mkdir -p ~/.config/raft
cp docs/incus.example.json ~/.config/raft/incus.json
chmod 600 ~/.config/raft/incus.json

Verify interactive SSH to establish known host keys:

CONTROLLER: Verify host SSH access
ssh user@host-address "echo Host SSH connected successfully"
ssh -o BatchMode=yes user@host-address "echo Batch SSH functional"

Edit ~/.config/raft/incus.json. Set the ssh target. Leave image empty during initial setup:

CONTROLLER: ~/.config/raft/incus.json
{
  "lab": {
    "ssh": "user@host-address",
    "image": ""
  }
}

Location names use letters, digits, underscores, or hyphens. The first configured location is the default for raft new.

Provision the dedicated host

Run the automated host deployer from your controller:

CONTROLLER: Provision host infrastructure
python3 deploy/deploy.py --location lab
Infrastructure created by the deployer

The deployer runs over SSH and configures the host:

  1. Installs Incus 6.0 LTS and nftables packages.
  2. Creates the isolated raft Incus project.
  3. Creates a 60 GiB Btrfs storage pool (raft-data).
  4. Creates private bridge interface rfbr0 (10.232.0.1/24) with NAT.
  5. Configures nftables bridge filters to block inter-workspace traffic and restrict host access.
  6. Installs and enables raft-network.service and raft-expire.timer units.

Acquire a native workspace image

Workspaces require an unprivileged Debian 13 development image matching the host architecture:

Download the release archive, checksum, and manifest from Raft releases. The sha256sum check gates import so corrupted archives are rejected:

HOST (ARM64): Download, verify, and import release image
curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.1.0/raft-dev-arm64.tar.gz
curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.1.0/SHA256SUMS
curl -fsSL -O https://github.com/Microck/raft/releases/download/v0.1.0/manifest-arm64.json

sha256sum --ignore-missing -c SHA256SUMS && \
  sudo incus --project raft image import ./raft-dev-arm64.tar.gz --alias raft-dev

Retrieve and pin the image fingerprint

Query the published raft-dev image on the host:

HOST: Retrieve published image fingerprint
sudo incus --project raft image list raft-dev --format json | python3 -c '
import json, sys
data = json.load(sys.stdin)
print(next(img["fingerprint"] for img in data if any(a.get("name") == "raft-dev" for a in img.get("aliases", []))))
'

Copy the 64-character hex output into image in ~/.config/raft/incus.json on the controller:

CONTROLLER: ~/.config/raft/incus.json
{
  "lab": {
    "ssh": "user@host-address",
    "image": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
  }
}

Replace the example string with your actual fingerprint. Raft requires this immutable fingerprint to prevent unexpected image mutations when creating workspaces.

Check host status with doctor

Run raft doctor on your controller to inspect host readiness:

CONTROLLER: Run doctor diagnostics
raft doctor

Check that Incus, the network service, and the expiration timer are active. For the full report contents, see Controller diagnostics.

Next step

Proceed to First working box to launch, verify, and manage your first workspace.

On this page