Skip to content

MÓDULO TBI — TLSStress Bench Image

First-boot ZTP image — operator USB / qcow2 / OCI handoff to the cluster.

Function

TBI (TLSStress Bench Image) is what the customer's new node boots from. It bundles Ubuntu 24.04 LTS minimal + the tbi-agent Go binary + k3s + gVisor + cloud-init. On first boot, the agent fingerprints the hardware + posts to VALIDATOR.Art /enroll + receives a JoinBundle + writes k3s / CA / WireGuard config files + enables the cluster join.

Per ADR-0087. Paired with VALIDATOR.Art ADR-0086 on the receiver side.

Identity

Element Value
Plane n/a (image, not a runtime MÓDULO)
Build pipeline build/tbi/ mkosi config + scripts
Agent binary pkg/tbi-agent/ Go module (cross-built for amd64/arm64)
K8s CronJob k8s/oobi/98-tbi-builder-cronjob.yaml (slot .98)
Library PVC tbi-library 50 GiB RWX
Dashboard /admin/tbi-library
ADR ADR-0087

What ships in the image

  • Ubuntu 24.04 LTS noble minimal base
  • tbi-agent at /usr/local/bin/tbi-agent (cross-compiled Go binary)
  • tbi-agent.service systemd unit (enabled by default; ProtectSystem strict, runAsNonRoot, Restart on-failure)
  • cloud-init drop-in honoring /etc/tlsstress/{claim.token,validator-url} (operator-supplied via user-data)
  • k3s v1.31.4+k3s1 pre-installed but disabled (agent enables after enrollment)
  • containerd + gVisor runsc runtime class (sandboxes DoYour.Art + KALI.Art pods)
  • lldpd + snmpd daemons (protocol-level discovery for the validator's cascade)
  • Hardware probes: lshw, dmidecode, ipmitool, smartmontools, ethtool, pciutils, usbutils
  • WireGuard userspace tools (kernel module ships in Ubuntu noble)
  • Debug toolkit: vim, curl, jq, less

Multi-format output

Format Use case Size (approx) Build command
ISO bootable Lab on-site, USB / DVD ~1.8 GB ./scripts/build-tbi.sh iso
Raw IMG KVM / VMware / Proxmox ~1.6 GB ./scripts/build-tbi.sh img
QCOW2 (compressed) Cloud / hypervisor ~1.0 GB ./scripts/build-tbi.sh qcow2
OCI container Cloud-native via Cluster API ~800 MB ./scripts/build-tbi.sh oci
All four Release cut ./scripts/build-tbi.sh all

ZTP enrollment flow (6 phases)

PHASE 1  Image build factory (build/tbi/) — mkosi + Sigstore cosign
PHASE 2  First boot (customer site) — TBI boots, lldpd + snmpd up,
         cloud-init drops /etc/tlsstress/{claim.token,validator-url},
         tbi-agent.service starts
PHASE 3  Enrollment — agent gathers HardwareFingerprint, POSTs /enroll
         to VALIDATOR.Art (slot .97); validator returns JoinBundle
PHASE 4  Provisioning — agent writes k3s/agent.env + ca-bundle.pem +
         node-cert.pem (0600) + wg0.peers; enables k3s.service
PHASE 5  MÓDULO assignment — k3s joins cluster + applies role-specific
         manifests from JoinBundle.ModuleManifests
PHASE 6  Ongoing — agent posts /heartbeat every 60s; 404 ⇒ re-enroll

Operator delivery — cloud-init user-data shape

The operator drops both files via cloud-init write_files:

#cloud-config
write_files:
  - path: /etc/tlsstress/claim.token
    permissions: '0600'
    content: |
      eyJ2IjoxLCJpZCI6InRvay1hYmMi...      # HMAC-signed validator token
  - path: /etc/tlsstress/validator-url
    content: |
      http://validator-art.oobi-fabric.svc.cluster.local:8086

The claim token comes from /admin/validator-art → "Issue token" (V-3 UI). The validator URL points at slot .97 by default.

tbi-agent CLI

tbi-agent \
  --validator-url=http://validator-art.oobi-fabric.svc.cluster.local:8086 \
  --claim-token=...                # OR TBI_CLAIM_TOKEN env OR /etc/tlsstress/claim.token
  --base-dir=/etc \                # where to write k3s/CA/wg files (chroot-able for tests)
  --heartbeat-interval=60s \
  --dry-run=false \                # true ⇒ compute target paths, do NOT write
  --preferred-role=               # optional operator hint forwarded to /enroll

Operator controls (Dashboard)

/admin/tbi-library is the canonical surface:

Section Action
Artifacts table filename / format / version / size / built_at / cosign status (✓ signed or unsigned) / shortened SHA-256
"Rebuild now" button Kicks off a one-off rebuild outside the weekly CronJob cadence (POST /api/tbi/rebuild)
Placeholder banner (TBI-3 MVP) Visible until Phase B wires the real PVC volume-listing via TBI-builder sidecar

Weekly rebuild CronJob

k8s/oobi/98-tbi-builder-cronjob.yaml slot .98 (natural successor to validator-art .97):

Field Value
Schedule 0 4 * * 0 (Sun 04:00 UTC)
Concurrency Forbid (build takes ~15 min, shares PVC)
History 3 successful + 3 failed
Resources req 2c/8GiB, limit 4c/12GiB
Image ghcr.io/nollagluiz/ai_forse/tbi-builder:v0.1.0
Command build-tbi.sh all
Output /var/lib/tbi-library (PVC mount)
Signing Optional tbi-builder-cosign Secret (optional: true)
Security privileged: true (mkosi needs loop + ns caps)

Build prerequisites (host)

  • mkosi >= 24pipx install mkosi
  • systemd >= 252 (for systemd-repart)
  • qemu-utils (for qcow2 conversion)
  • cosign — optional; emits <artifact>.sig when COSIGN_KEY env set

Environment variables

Var Default Description
TBI_VERSION 0.1.0 Embedded in tbi-agent --version and the artifact filename
GOARCH amd64 Cross-compile target for tbi-agent (also arm64)
COSIGN_KEY (unset) Path to cosign private key — when set, emits <artifact>.sig
OUTPUT_DIR ../../out/tbi Where artifacts land
GVISOR_RELEASE 20250122.0 gVisor binary release tag (consumed by install-runtime.sh)
K3S_VERSION v1.31.4+k3s1 k3s binary version (consumed by install-k3s.sh)

Deferred (post-Phase-I-scaffold)

  • Phase I-late: FIPS hardening + bare-metal QEMU smoke in CI (needs self-hosted runner with root + loop)
  • Phase B: Real PVC volume-listing in Dashboard (replace placeholder) + CA.Art / k3s / WireGuard wired into JoinBundle
  • Phase G: Live force-directed topology graph on /admin/topology
  • Phase I: Multi-region distribution (mirror sync to customer-owned HTTP mirror)
  • Phase J: Air-gap shipping logistics (USB physical, customer key handoff) + intent-based provisioning