How to Safely Upgrade FreeBSD Between Major Versions
A method-aware FreeBSD major-upgrade runbook covering release eligibility, boot environments, external backup, staged installation, bootcode, packages, and rollback.
A FreeBSD major upgrade changes the base-system ABI and may change drivers, boot loaders, configuration defaults, package compatibility, and service behavior. The safe path depends on how the base system is managed. Distribution-set installations use freebsd-update, pkgbase installations use the FreeBSD-base repository, and source installations follow the source-build procedure. These methods are not interchangeable.
This article uses the supported 14.4-RELEASE to 15.1-RELEASE path to illustrate the current distribution-set workflow. Target release instructions can change exact commands, OSVERSION values, bootcode steps, and supported starting points. The target’s official upgrade page remains authoritative on change day.
Prove the source, target, and management method
Record installed kernel and userland, architecture, boot method, root filesystem, package state, and updater ownership:
freebsd-version -kru
uname -m
sysctl machdep.bootmethod
mount -p
zpool status -v
pkg which /usr/bin/uname
pkg check -d
pkg audit -F
The FreeBSD 15.1 instructions use pkg which /usr/bin/uname as the decision point. “Was not found in the database” indicates a distribution-set installation eligible for its freebsd-update path. A result such as FreeBSD-runtime-15.0 indicates packaged base. A source-built host needs its source runbook.
Verify that both current release and upgrade path are supported. The 15.1 instructions accept 14.4 or 15.0 as starting releases; an older host must first reach an approved intermediate version. Do not jump directly from an end-of-life release because a command happens to accept the target string.
Read release-specific evidence before scheduling
Review the target announcement, release notes, errata, upgrading instructions, hardware notes, and all intermediate /usr/src/UPDATING or package notes that apply. Search for the host’s storage controller, network driver, CPU architecture, ZFS features, jails, hypervisor, third-party kernel modules, encryption, and boot firmware.
Inventory custom kernels, loader tunables, deprecated rc variables, packages from private repositories, locked packages, locally built ports, and .pkgnew files. Export service configuration and a list of prime packages. Confirm current backups and monitoring are healthy before introducing another variable.
Write acceptance tests in advance: console boot, network on every required interface, storage import, encrypted datasets, DNS, time, SSH, PF, jails, bhyve guests, databases, queues, application transactions, backups, and external monitoring. “The version changed” is not acceptance.
Build two independent rollback layers
On a supported root-on-ZFS layout, create a boot environment:
bectl create -r pre-15.1
bectl list
The recursive option is appropriate only after understanding the dataset layout. Separately mounted application datasets may not be part of the boot environment, and a boot environment remains in the same pool. Verify what it covers.
Take an application-consistent, off-host backup of all required data and configuration, then restore representative content onto another system. A recursive zfs snapshot zroot@name is not a full backup and the statement that one zfs rollback safely returns the entire machine is false. Snapshots share pool failure, can omit datasets, and rolling back active descendants can destroy newer data.
Confirm out-of-band console, loader-menu access, recovery media, encryption keys, boot-pool access, and a written decision point for rollback. Do not begin when the only operator path is the SSH session the upgrade may break.
Bring the current release fully up to date
For the verified distribution-set path, apply pending security and errata patches before the version upgrade:
freebsd-update fetch
freebsd-update install
freebsd-version -kru
Reboot first if the installed kernel changed, then confirm services. Update third-party packages on the current ABI, resolve broken dependencies and audit findings, and stop conflicting automated update jobs. Preserve enough repository availability to reinstall packages for the new ABI later.
If freebsd-update reports that packaged base is in use, stop. Follow the target release’s pkgbase section instead of attempting to bypass the check.
Stage the distribution-set kernel upgrade
For the officially supported 14.4 to 15.1 example:
freebsd-update upgrade -r 15.1-RELEASE
freebsd-update install
Read every merge and deletion prompt. Compare configuration semantically; accepting either side blindly can remove security policy or retain an obsolete directive. Save the transcript and do not reboot if the fetch, merge, or first install reported unresolved errors.
The first install phase places the new kernel. Reboot into it before userland installation:
shutdown -r +10min "Rebooting for FreeBSD kernel upgrade"
At console, confirm the intended kernel boots, storage imports, root mounts read-write, and management networking works. A custom kernel requires the GENERIC preparation documented by the Handbook and confirmation that it contains every driver required for boot and remote access.
Upgrade userland and third-party packages in order
After the new kernel is running:
freebsd-update install
freebsd-version -kru
This installs new userland. A major ABI transition requires third-party packages to be reinstalled from repositories built for the target release. The current Handbook uses:
pkg-static upgrade -f
pkg check -d
pkg audit -F
Preview and review the repository transaction where the tooling permits, and keep console access. Custom packages must exist for the new ABI and options. Reinstalling pkg alone is not enough; every package that may link against changed base libraries needs a target-compatible build.
Restart and test critical services before removing compatibility libraries. Review package messages, .pkgnew files, ownership, and service enablement. Rebuild a custom kernel against the new source only through its documented process.
Complete any remaining freebsd-update phase:
freebsd-update install
Depending on library changes, the upgrade can have two or three install phases. Continue according to the command’s output and official target instructions rather than assuming a fixed count.
Upgrade bootcode using the target-specific procedure
An updated filesystem and kernel do not update every boot loader copy automatically. The FreeBSD 15.1 instructions first identify the boot method:
sysctl machdep.bootmethod
efibootmgr -v
gpart show
UEFI, BIOS with GPT, architecture, ESP location, root filesystem, and mirrored disks determine the commands. Copying an amd64 loader.efi path onto AArch64 or writing gptzfsboot to the wrong disk can make the host unbootable. Follow the exact release instructions, update every required boot disk, verify files or bootcode, and do not run zpool upgrade merely because new features are available.
Reboot, validate, and monitor before promotion
Perform the final reboot and capture state:
freebsd-version -kru
uname -a
pkg check -d
pkg audit
service -e
sockstat -4 -6 -l
bectl list
Run the predefined application tests from real clients. Review console, dmesg, storage health, route tables, PF, DNS, time synchronization, crash dumps, service logs, package repository origin, backup jobs, and external alerts. Watch at least one normal workload and scheduled-maintenance cycle.
Keep the prior boot environment and external backup through the acceptance window. When the new environment is approved, confirm the intended environment is persistently active. Remove the old one only after retention policy permits and another recovery path has been tested.
Roll back by failure stage, not improvisation
If the new kernel cannot boot, use the loader menu or prior boot environment. kernel.old may exist but is not a complete rollback contract and can be overwritten by repeated installs. If userland or services fail, booting the preserved environment is safer than recursively rolling back live datasets.
freebsd-update rollback can reverse its last installed update on supported distribution-set systems, but it does not restore third-party packages, databases, separately mounted data, firmware, or every configuration action. A pkgbase rollback follows its boot-environment and package procedure. Restore application data from the consistent external backup only when required and with an explicit data-loss boundary.
Document the failure, stop automated jobs, preserve logs, and decide whether to repair forward or roll back completely. A safe major upgrade is one whose method, boot path, packages, services, data, and recovery have all been proved—not merely one that reaches a login prompt.
Related:
- Building a Custom FreeBSD Kernel from Source
- How to Use ZFS Boot Environments with bectl for Safe Upgrades
Sources: