Bare-metal commissioning,
one static binary.

Rollcall does what MAAS does when a new server first shows up: PXE-boot an ephemeral image, take a full hardware inventory, create an administrator account on the BMC, and remember the machine. No cloud controller, no agents on your OS, no fleet of services.

Go ยท single binaryPostgreSQLDebian live image IPMI / ipmitoolInfiniBand awareWeb UI + CLI + API

How it works

A machine goes from unknown to ready in one boot, without anyone typing anything.

PXE boot

dnsmasq hands out DHCP and TFTP. Unknown MACs land on the default pxelinux menu, which starts commissioning after 8 seconds.

Ephemeral image

A Debian 13 live image (full kernel, non-free firmware, IB and NVMe tooling) is fetched over HTTP and runs from RAM. Disks are never touched.

Inventory

DMI, DIMMs, CPUs, disks with SMART, NVMe, NICs with firmware and link, InfiniBand HCAs, GPUs, every PCI device, LLDP switch ports, TPM.

BMC account

In-band ipmitool finds the LAN channel and creates commissioner with ADMINISTRATOR rights and a random password.

Report & power off

Everything is posted to the server. The password is sealed with AES-256-GCM before it reaches PostgreSQL. The machine powers off.

Known from now on

A per-MAC PXE file stops future boots of the image. Power and boot device are controlled through the API, UI or CLI, with ipmitool running on the server.

Features

Small surface, enterprise hardware in mind.

One binary, everything inside

HTTP API, embedded web UI, CLI subcommands, schema migrations and PXE bookkeeping ship as a single static Go executable. Deploy with scp.

Secrets stay on the server

BMC passwords are encrypted at rest with a local master key, never returned by the API, and only ever used by ipmitool inside the server process.

Real hardware first

The image carries firmware for Broadcom, QLogic, Intel and Mellanox NICs, rdma-core, infiniband-diags, mstflint, nvme-cli, smartmontools, lldpd.

Virtual machines too

No in-band IPMI? Rollcall can map MACs to known BMCs. The repo ships pve-vbmc, an IPMI BMC emulator for Proxmox VMs, so the whole flow runs in a lab.

Two tokens, two audiences

The live image authenticates with an agent token baked into the kernel command line; people and automation use a separate admin bearer token.

Re-commission on demand

Drop the PXE override, set bootdev pxe and power-cycle through the BMC with one click or rollcall recommission ID -now.

OS deployment from cloud images

Debian, Ubuntu, Rocky, AlmaLinux and CentOS Stream images are streamed onto the disk (curl | zstd | dd, sha256-verified) and seeded for cloud-init: hostname, SSH keys, optional upgrade, phone-home. No installer.

Images that stay fresh

rollcall os sync watches the vendors' checksum files nightly, downloads only what changed, verifies it and flips a current symlink. Pin or promote versions; running jobs keep theirs.

Stateless HPC nodes

Or skip the disk: boot a Debian root image into RAM, overlay slurm.conf, munge key, hosts and SSH keys rendered per node from the inventory.

Quick start

On the host that already runs your DHCP/TFTP for the provisioning network.

# 1. database
sudo -u postgres psql \
  -c "CREATE ROLE rollcall LOGIN PASSWORD 'secret';" \
  -c "CREATE DATABASE rollcall OWNER rollcall;"

# 2. config
rollcall keygen   # admin_token
rollcall keygen   # agent_token
sudo install -d -m 0750 /etc/rollcall
sudo cp config.json /etc/rollcall/config.json

# 3. install binary, unit, pxelinux menu
cd deploy && sudo ./install.sh

# 4. build the live image (~8 min)
sudo ../agent/build-image.sh
$ rollcall list
ID               STATE   MODEL                   RAM   NIC IB  BMC
m-2ef1dab828c8   ready   Dell PowerEdge R760     1.0T  4   2   10.4.0.21 (inband,ok)
m-9c01a3bd7e12   ready   Supermicro SYS-421GE    2.0T  6   4   10.4.0.22 (inband,ok)

$ rollcall power m-2ef1dab828c8 status
Chassis Power is on

$ rollcall show m-2ef1dab828c8 | head -3
m-2ef1dab828c8  state=ready
  Dell Inc. PowerEdge R760  S/N 7XK2Q94
  CPU: Intel Xeon Platinum 8468  sockets=2 ...

Then point the UI at http://<server>/ and paste the admin token. Machines appear as they boot.

API

JSON over HTTP. Admin calls carry Authorization: Bearer <admin_token>; the agent sends X-Rollcall-Token.

MethodPathWhoPurpose
POST/api/v1/commissionagentInventory upload from the live image
GET/api/v1/bmc-hint?macs=agentOut-of-band BMC hint for machines without in-band IPMI
GET/api/v1/machinesadminList with summaries (CPU, RAM, disks, NICs, IB, GPUs, BMC state)
GET/api/v1/machines/{id}adminFull record: inventory, BMC (without secret), events
POST/api/v1/machines/{id}/poweradmin{"action":"on|off|soft|cycle|reset|status"}
POST/api/v1/machines/{id}/bootdevadmin{"device":"pxe|disk|cdrom|bios|none"}
POST/api/v1/machines/{id}/recommission[?now=1]adminBoot the image again on next PXE, or right now via the BMC
DELETE/api/v1/machines/{id}adminForget the machine

What the inventory contains

Collected by rollcall-agent.py inside the live image and stored as JSON per machine.

System

Manufacturer, product, serial, UUID, SKU, baseboard, chassis, asset tag, BIOS vendor/version/date, TPM.

Compute

CPU model, sockets, cores, threads, NUMA nodes, caches, virtualization flags; memory total plus every DIMM slot with size, type, speed, vendor, part and serial.

Storage

All block devices with model, serial, bus, rotational flag, sector sizes, SMART health and firmware, NVMe list, storage controllers from PCI.

Network

NICs with driver, firmware, speed, link state, permanent MAC, PCI address, NUMA node, SR-IOV capacity; LLDP neighbours to map switch ports.

InfiniBand

HCAs with node and port GUIDs, firmware, board id, per-port state, physical state, rate, LID and link layer.

BMC

LAN channel, IP source, MAC, gateway, VLAN, firmware, FRU, user table before commissioning, created account and verification result.