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:
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
ca-certificates curl gnupg python3 openssh-server iptables btrfs-progsVerify passwordless sudo on the host:
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:
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:
export PATH="$HOME/.local/bin:$PATH"
raft --helpConfigure host inventory on the controller
The controller reads host definitions from ~/.config/raft/incus.json. Initialize the configuration directory and template:
mkdir -p ~/.config/raft
cp docs/incus.example.json ~/.config/raft/incus.json
chmod 600 ~/.config/raft/incus.jsonVerify interactive SSH to establish known host keys:
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:
{
"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:
python3 deploy/deploy.py --location labInfrastructure created by the deployer
The deployer runs over SSH and configures the host:
- Installs Incus 6.0 LTS and nftables packages.
- Creates the isolated
raftIncus project. - Creates a 60 GiB Btrfs storage pool (
raft-data). - Creates private bridge interface
rfbr0(10.232.0.1/24) with NAT. - Configures nftables bridge filters to block inter-workspace traffic and restrict host access.
- Installs and enables
raft-network.serviceandraft-expire.timerunits.
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:
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-devRetrieve and pin the image fingerprint
Query the published raft-dev image on the host:
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:
{
"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:
raft doctorCheck 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.