From 793f499178ebe20aef223842ade17275a390f384 Mon Sep 17 00:00:00 2001 From: claude-hdb Date: Mon, 13 Jul 2026 23:31:32 +0000 Subject: [PATCH] fix: a clone must not inherit its source's identity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two boxes cloned from one snapshot came up holding the SAME IP address — 10.87.0.128, on the same dnsmasq lease, matching to the second on the lease timer. Incus does regenerate the MAC (they differed), but /etc/machine-id rides along inside the disk image, and systemd derives its DHCP client identifier from it. Same client-id, same lease. This breaks the workflow claudebox exists for: log in once, snapshot, clone forever. Every clone of a snapshot is, to the network, the same machine as its source and as its siblings. Truncating /etc/machine-id makes systemd mint a fresh one at next boot, so the clone path now resets it and restarts before handing the box over. Costs one reboot; the alternative is colliding boxes. Found by the drill on a live host (#26) — and it also explains why the sibling-isolation probe (#15 A3) could never work: it was aiming box A at box A's own address. Co-Authored-By: Claude Fable 5 --- bin/claudebox | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/bin/claudebox b/bin/claudebox index 9da33b7..b91e556 100755 --- a/bin/claudebox +++ b/bin/claudebox @@ -405,6 +405,27 @@ wait_agent() { done } +# A clone must not BE its source. Incus regenerates the MAC, but /etc/machine-id +# rides along inside the disk — and systemd derives its DHCP client identifier +# (DUID) from it. Same client-id, same dnsmasq lease: two boxes, one IP address, +# to the second on the lease timer. Every box cloned from one snapshot collided +# on the network, which is exactly the workflow claudebox exists for (log in +# once, snapshot, clone forever). +# +# Truncating /etc/machine-id makes systemd mint a fresh one on the next boot, so +# the reset costs one reboot. Do it before handing the box over, never after. +reset_identity() { + local i="$1" + echo "claudebox: giving the clone its own identity (machine-id, DHCP lease)..." + incus exec "$i" -- sh -c ' + : >/etc/machine-id + rm -f /var/lib/dbus/machine-id + ln -sf /etc/machine-id /var/lib/dbus/machine-id + ' || die "could not reset the clone's machine-id" + incus restart "$i" + wait_agent "$i" +} + cmd_new() { [ -n "$name" ] || usage_error "usage: $(synopsis_of new)" local instance; instance="$(iname_of "$name")" @@ -415,6 +436,7 @@ cmd_new() { incus copy "$srcref" "$instance" incus start "$instance" wait_agent "$instance" + reset_identity "$instance" echo "claudebox: cloned $srcref — isolation and Claude auth carry over from the source." else local m extra=(); m="$(pick_mode)" -- 2.45.2