From aebc225ddca6850a2e59b41295702a86936dbe71 Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Thu, 25 Jun 2026 11:23:36 +0200 Subject: [PATCH] skill(freebsd): add boot environment rollback + cross-release override MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two improvements from the live OSA upgrade run: 1. Boot environment rollback: step 2 (before any base changes) now creates a BE with naming convention MAJOR.MINOR-upgrade-DD.mon.YY. pkgbase does NOT auto-snapshot ZFS — this must be done manually. If the upgrade misbehaves after reboot, bectl activate + reboot = instant rollback. 2. Cross-release override: pkgbase refuses to fetch 15.1 packages while running 15.0 userland. Document the env OSVERSION=1501000 override needed to cross the boundary. Renumbered subsequent steps 2→3, 3→4, ..., 7→8. --- skills/freebsd-os-upgrade/SKILL.md | 35 ++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/skills/freebsd-os-upgrade/SKILL.md b/skills/freebsd-os-upgrade/SKILL.md index 2e0f2d1..763f315 100644 --- a/skills/freebsd-os-upgrade/SKILL.md +++ b/skills/freebsd-os-upgrade/SKILL.md @@ -71,7 +71,22 @@ pkg update -f && pkg upgrade # ports packages (separate from base here) *Pre-reboot status capture* in the reference (hostname, `freebsd-version -k` / `-u`, `uname -r`, services, `jls`, `pfctl -s info`). Record permission-limited checks as such, not as "down". -2. **Upgrade base** (by the method from step 0): +2. **Create a boot environment rollback point** — before any base changes. + The host is root-on-ZFS, so a boot environment is instant and near-free. + If the upgrade misbehaves after reboot, `bectl activate ` + reboot + puts you back exactly where you were. + + ```sh + bectl create MAJOR.MINOR-upgrade-DD.mon.YY + # example: 15.1-upgrade-25.jun.26 + bectl list | grep upgrade + ``` + + Name convention: `-upgrade-` — operator-facing, + readable at a glance. pkg does NOT auto-create ZFS boot environments; + this must be done manually. + +3. **Upgrade base** (by the method from step 0): - **pkgbase**: a pkgbase host already has a `FreeBSD-base` repo — **inspect it** (`pkg -vv | grep -A6 -i FreeBSD-base`) and **edit that existing entry in place**. A pinned `base_release_0` only delivers 15.0 patch levels; point @@ -80,23 +95,29 @@ pkg update -f && pkg upgrade # ports packages (separate from base here) undefined, last-wins behavior. Then `pkg update`, **dry-run** with `pkg upgrade -n` to confirm 15.1 base packages are actually offered, then `pkg upgrade` (base + ports together). + + **Cross-release override:** pkgbase refuses to fetch packages for a + newer release while running the old userland. Override with: + `env OSVERSION=1501000 ABI="FreeBSD:15:amd64" pkg update -f` then use + the same env for `pkg upgrade -n` and the real `pkg upgrade`. + (Replace `1501000` with the target release's __FreeBSD_version.) - **freebsd-update**: `freebsd-update -r upgrade` then `freebsd-update install`. Either way the new kernel is staged; the system runs the old one until reboot. -3. **Confirm a reboot is needed**: `freebsd-version -k` newer than `uname -r` +4. **Confirm a reboot is needed**: `freebsd-version -k` newer than `uname -r` means staged-not-active. State that plainly and **reboot only on explicit operator go-ahead** — never reboot the always-on board host autonomously. -4. **After reboot**: on freebsd-update hosts, run `freebsd-update install` again +5. **After reboot**: on freebsd-update hosts, run `freebsd-update install` again to finish userland. Then the *Post-reboot verification* block — `-k`/`-u`/ `uname -r` must all match, and the app-readiness checks (Clawdie control plane, Forgejo, jails, PF, Tailscale) must pass. -5. **Packages**: same-major ABI (`FreeBSD:15:amd64`) is unchanged, so this is a - freshness refresh, not a rebuild — pkgbase already covered it in step 2; +6. **Packages**: same-major ABI (`FreeBSD:15:amd64`) is unchanged, so this is a + freshness refresh, not a rebuild — pkgbase already covered it in step 3; freebsd-update hosts do `pkg update -f && pkg upgrade`. A same-major PostgreSQL bump needs no dump/restore (restart/reboot to load new binaries). -6. **Upgrade the jails** — the host upgrade does NOT touch them. Do this after +7. **Upgrade the jails** — the host upgrade does NOT touch them. Do this after the host is on the new kernel. See *Jails* below. -7. **Vulnerability audit**: if `pkg audit` still flags packages (host or jails), +8. **Vulnerability audit**: if `pkg audit` still flags packages (host or jails), do not imply the upgrade failed — the upgrade completed; unrelated packages remain vulnerable until fixed versions land. (Wording in the reference.)