GRUB keeps the firmware's text console; phone-home back to HTTP
CI / agent (push) Successful in 3s
CI / site (push) Successful in 2s
CI / go (push) Successful in 40s

Lab, Secure Boot VM: the deployed Debian booted under Secure Boot
through the chainload, but its console was garbled after the network
GRUB had switched the display mode; GRUB menus now use the firmware's
text console (terminal_output console), which also suits serial/SOL.

phone-home over HTTPS failed once on that first boot (TLS: bad record
MAC on the region's side; the same request works from the machine
since), and cloud-init spends its 10 tries within milliseconds. Its
content is not secret and its token only works from the machine's
address, so it goes over HTTP again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Ilker ManapandClaude Opus 5.5 committed 2026-10-30 12:51:22 +01:00
1 parent c494c7b226
commit b2ad0210bf
3 files changed
+15 -7

No files matched your search

+6 -2
View File
@@ -91,8 +91,12 @@ region and `deploy/install-rack.sh` on rack hosts (new dnsmasq layout, signed ra
the agents' endpoints and images on 443. Agents accept the CA by the fingerprint on the PXE
command line and do not fall back to HTTP. Old agents keep working over HTTP. The commissioning
image has to be rebuilt to get the new agents.
- The stateless overlay client works the same way (rebuild stateless images), and a deployed OS
calls home over HTTPS.
- The stateless overlay client works the same way (rebuild stateless images).
- **UEFI and Secure Boot.** UEFI machines PXE-boot through Debian's signed shim and GRUB, so machines
with Secure Boot on can boot at all; before, the firmware refused the unsigned `syslinux.efi`.
- GRUB menus are made from the pxelinux ones.
- The local disk is booted by chainloading the installed OS's signed loader.
- Secure Boot verifies the kernel; the initrd and squashfs are not covered.
- **BMC certificates.** HTTPS BMCs (Redfish, Proxmox) are pinned on first use. The certificate
is read in a handshake that carries no credentials, and a changed certificate gets none
(`tls_fingerprint`; cleared on an address change or a BMC firmware update by Rollcall).
+4 -5
View File
@@ -297,11 +297,10 @@ func (a *App) renderSeed(j *Job, sp DeploySpec, token string) []seedFile {
if len(sp.Packages) > 0 {
fmt.Fprintf(&b, "packages: %s\n", yamlList(sp.Packages))
}
home := base
if t := a.agentTLS(base); t != "" && a.ca != nil {
home = t // the deployed OS trusts the Rollcall CA (bootcmd below), so it calls home over HTTPS
}
fmt.Fprintf(&b, "phone_home:\n url: %s/api/v1/phone-home/%s\n post: [instance_id, hostname, fqdn, pub_key_ed25519]\n tries: 10\n", home, token)
// plain HTTP on purpose: nothing in it is secret (the token only works from this
// machine's address), and cloud-init spends its 10 tries within milliseconds, so a
// TLS hiccup on first boot (seen once on Debian: bad record MAC) loses "booted"
fmt.Fprintf(&b, "phone_home:\n url: %s/api/v1/phone-home/%s\n post: [instance_id, hostname, fqdn, pub_key_ed25519]\n tries: 10\n", base, token)
b.WriteString("final_message: \"rollcall: deployed, up after $UPTIME s\"\n") // only $UPTIME/$TIMESTAMP/$DATASOURCE/$VERSION are expanded
ud = b.String()
}
+5
View File
@@ -24,6 +24,7 @@ import (
)
const grubDispatch = `# generated by rollcall: the machine's own menu, else the one for unknown machines
terminal_output console
set timeout=8
configfile $prefix/grub.cfg-$net_default_mac
configfile $prefix/grub.cfg-default
@@ -90,6 +91,10 @@ func pxelinuxToGrub(body string) string {
}
var b strings.Builder
b.WriteString("# generated by rollcall from the pxelinux menu\n")
// the firmware's text console: GRUB does not switch the display mode, so the OS
// it starts gets the firmware's own (OVMF showed a garbled console after a switch),
// and serial/SOL consoles see the menu
b.WriteString("terminal_output console\n")
fmt.Fprintf(&b, "set default=%d\nset timeout=%d\n", def, timeout)
for _, e := range entries {
fmt.Fprintf(&b, "menuentry %s {\n", grubQuote(e.label))