From 912e0621cab6b00c41e97a66f9c64f1ec1436d4f Mon Sep 17 00:00:00 2001 From: claude-hdb Date: Tue, 14 Jul 2026 17:05:39 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20disable=20Secure=20Boot=20on=20box=20VMs?= =?UTF-8?q?=20=E2=80=94=20'bad=20shim=20signature'=20hung=20every=20mint?= =?UTF-8?q?=20at=20GRUB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The console log finally showed the real error behind the GRUB-menu hang: error: prohibited by secure boot policy. error: bad shim signature. Failed to boot both default and fallback entries. Incus defaults VMs to security.secureboot=true. A Debian cloud image whose shim is signed with a key this host's OVMF does not trust then fails signature verification, the kernel never loads, and the VM sits at the GRUB menu forever — which is exactly the 5-min agent timeout on every box. It worked in runs 11–15 on the old cached image and broke the moment --purge-storage re-downloaded a build with a different shim. security.secureboot=false on VM launch (cmd_new, and the drill's legacy box). Secure Boot inside a throwaway box is not part of its threat model — the VM boundary is — and off, it boots reliably across image rebuilds. Container mode has no firmware and is unaffected. Bare repro that isolated it: 'incus launch images:debian/13/cloud x --vm' alone reproduced the hang, proving it was never the 0.5.0 code. --- bin/box | 9 ++++++++- drill/drill.sh | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/bin/box b/bin/box index f076c98..0e840ec 100755 --- a/bin/box +++ b/bin/box @@ -630,7 +630,14 @@ cmd_new() { load_template "$t" m="$(pick_mode)" # shellcheck disable=SC2054 # "root,size=..." is a single incus argument - if [ "$m" = vm ]; then extra+=(--vm --device "root,size=$T_DISK"); else extra+=(--config security.nesting=true); fi + # security.secureboot=false: Incus defaults VMs to secureboot ON, and a + # Debian cloud image whose shim is signed with a key the host's OVMF does + # not trust dies with "bad shim signature / prohibited by secure boot + # policy" and drops to the GRUB menu forever — the kernel never loads. It + # is not part of a throwaway box's threat model (the VM boundary is), and + # turning it off boots reliably across image rebuilds. Container mode has + # no firmware, so it does not apply there. + if [ "$m" = vm ]; then extra+=(--vm --device "root,size=$T_DISK" --config security.secureboot=false); else extra+=(--config security.nesting=true); fi # The template's identity is stamped ONTO the instance: which template, # which user. 'incus copy' preserves user.* keys (audit B2), so a clone # knows what it is without ever consulting the template again. diff --git a/drill/drill.sh b/drill/drill.sh index a82093c..d8edd7a 100755 --- a/drill/drill.sh +++ b/drill/drill.sh @@ -779,7 +779,8 @@ else # old stack, wearing the old tag. This is what migrate has to move. printf '\n minting a faithful legacy box on the old stack…\n' if mint_legacy=$(incus launch images:debian/13/cloud legacybox --profile claude-dev \ - --config user.claudebox=1 --vm --device root,size=20GiB 2>&1); then + --config user.claudebox=1 --vm --device root,size=20GiB \ + --config security.secureboot=false 2>&1); then wait_box legacybox && ok "legacy box up on the old stack (claudenet, user.claudebox=1)" \ || no "legacy box never came up — cannot drill migration" box list 2>/dev/null | grep -q '^legacybox' \