Version-aware install: migrate boxes across an upgrade instead of refusing #67

Closed
opened 2026-07-17 13:34:14 +00:00 by claude-bot-andresmgsl · 0 comments
claude-bot-andresmgsl commented 2026-07-17 13:34:14 +00:00 (Migrated from github.com)

Follow-up to #66, which added the escape hatch. Splitting the "hard but cool" half out as its own issue, per @danmt on that PR:

the easy escape hatch is to fail loudly if you do the curl install and you already have it installed, or if you have running boxes […] And the hard but cool solution is that its just magical, you run it, and if its already the same version it just tells you, if its not, it migrates boxes and everything. I feel like we really want to go the hard route, i'd do it as a separate issue do the hatch first.

Where #66 leaves things

install.sh now builds the host stack itself, so an upgrade reaches under boxes attached to that stack. Today it:

  • proceeds when the version+ref are unchanged (says so, migrates nothing);
  • proceeds when the host has no boxes (nothing to lose);
  • refuses, loudly and before touching $DEST, when the install would change version/ref and boxes exist;
  • BOX_FORCE_UPGRADE=1 overrides; the drill sets it, since wiping boxes is its job.

Refusing is the placeholder. The goal is that it just works.

What "magical" needs

  1. Know what a box was built by. Boxes are tagged user.box=1 / user.box.template / user.box.user, but nothing records the box VERSION that minted them. Without that, an upgrade cannot tell a box that needs migrating from one that does not. Probably user.box.version stamped at mint, alongside the existing user.box.* keys.
  2. Know what actually changes between two versions. The stack is network + ACL + profile + firewall. Most upgrades change none of it, and those should be a silent no-op on a host with 50 running boxes. A cheap "does the shipped stack differ from the live stack" comparison would let the common case skip everything.
  3. Migrate per box, resumably. migrate-host already moves pre-0.4.0 boxes onto the current stack (--box, --all-boxes, --retire-legacy) — that is the shape to build on rather than reinvent, and possibly the place this belongs.
  4. Say no when it cannot. A downgrade, or a box whose template no longer exists, should keep refusing rather than half-migrate.

Open question that blocks the honest version of this

What are the real consequences of reconfiguring boxnet under attached boxes? Nobody has measured it. From reading setup-host.sh, an upgrade re-runs incus network set boxnet security.acls=…, dns.mode=none, and raw.dnsmasq, and drill.sh's own comment records that this stalled:

setup-host.sh reconfigures the network's ACLs, and a previous run's boxes are still ATTACHED to that network — 'incus network set' then has to push the change onto every live NIC, which is how run 6 stalled.

Until someone runs that on a real host with live boxes and reports what happens — DNS blip? connectivity blip? stall? nothing at all when values are unchanged? — the migration cannot know what it must protect boxes from, and the hatch is the honest default. A drill phase that mints boxes, upgrades under them, and asserts they survive would answer it.

Also worth deciding

The obvious manual recovery path does not work today: box rm deletes a box and every snapshot it has, so "snapshot → rm → restore with --from" loses the data at rm (a snapshot does not outlive its box). If refusing is meant to leave people a way out, there is a gap — some export/publish that survives the box, or a documented copy-it-out-first step. #66's error message currently says to copy data out first rather than suggest the lossy path.

🤖 Generated with Claude Code

Follow-up to #66, which added the escape hatch. Splitting the "hard but cool" half out as its own issue, per @danmt on that PR: > the easy escape hatch is to fail loudly if you do the curl install and you already have it installed, or if you have running boxes […] And the hard but cool solution is that its just magical, you run it, and if its already the same version it just tells you, if its not, it migrates boxes and everything. I feel like we really want to go the hard route, i'd do it as a separate issue do the hatch first. ## Where #66 leaves things `install.sh` now builds the host stack itself, so an upgrade reaches under boxes attached to that stack. Today it: - proceeds when the version+ref are unchanged (says so, migrates nothing); - proceeds when the host has no boxes (nothing to lose); - **refuses, loudly and before touching `$DEST`,** when the install would change version/ref and boxes exist; - `BOX_FORCE_UPGRADE=1` overrides; the drill sets it, since wiping boxes is its job. Refusing is the placeholder. The goal is that it just works. ## What "magical" needs 1. **Know what a box was built by.** Boxes are tagged `user.box=1` / `user.box.template` / `user.box.user`, but nothing records the box VERSION that minted them. Without that, an upgrade cannot tell a box that needs migrating from one that does not. Probably `user.box.version` stamped at mint, alongside the existing `user.box.*` keys. 2. **Know what actually changes between two versions.** The stack is network + ACL + profile + firewall. Most upgrades change none of it, and those should be a silent no-op on a host with 50 running boxes. A cheap "does the shipped stack differ from the live stack" comparison would let the common case skip everything. 3. **Migrate per box, resumably.** `migrate-host` already moves pre-0.4.0 boxes onto the current stack (`--box`, `--all-boxes`, `--retire-legacy`) — that is the shape to build on rather than reinvent, and possibly the place this belongs. 4. **Say no when it cannot.** A downgrade, or a box whose template no longer exists, should keep refusing rather than half-migrate. ## Open question that blocks the honest version of this **What are the real consequences of reconfiguring `boxnet` under attached boxes?** Nobody has measured it. From reading `setup-host.sh`, an upgrade re-runs `incus network set boxnet security.acls=…`, `dns.mode=none`, and `raw.dnsmasq`, and drill.sh's own comment records that this stalled: > setup-host.sh reconfigures the network's ACLs, and a previous run's boxes are still ATTACHED to that network — 'incus network set' then has to push the change onto every live NIC, which is how run 6 stalled. Until someone runs that on a real host with live boxes and reports what happens — DNS blip? connectivity blip? stall? nothing at all when values are unchanged? — the migration cannot know what it must protect boxes from, and the hatch is the honest default. A drill phase that mints boxes, upgrades under them, and asserts they survive would answer it. ## Also worth deciding The obvious manual recovery path does not work today: `box rm` deletes a box **and every snapshot it has**, so "snapshot → rm → restore with `--from`" loses the data at `rm` (a snapshot does not outlive its box). If refusing is meant to leave people a way out, there is a gap — some export/publish that survives the box, or a documented copy-it-out-first step. #66's error message currently says to copy data out first rather than suggest the lossy path. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/box#67
No description provided.