In this article we will explain how to migrate a FreeBSD 12.2 system to 13.0. The main features to highlight in version 13 are the incorporation of OpenZFS and TLS in the kernel itself. For more details, we can see the release notes at this link: https://www.freebsd.org/releases/13.0R/relnotes/
The migration will be carried out differently depending on whether it is a physical system or a virtualized jail, and there are also variations depending on the boot system used. On the other hand, we will also explain some aspects to take into account if we use FUSE, ZFS or Poudriere.
- Operating system
- Loader update: EFI
- Loader update: BIOS
- ZFS update
- FUSE update
- IOCAGE update
- Iocage - Template
- Poudriere
- Poudriere - cleaning
Operating system
We update the kernel and core tools to the latest version within 12.2:
freebsd-update install
We do the same with binary packages:
pkg autoremove
We check the current version:
12.2-RELEASE-p6
We create a new boot environment (BE):
bectl list
BE Active Mountpoint Space Created
13 - - 8K 2021-05-15 18:03
default NR / 41.7G 2020-11-27 23:58
We mount the BE:
Successfully mounted 13 at /var/tmp/BE-13
We chroot to this directory:
mount -t devfs devfs /dev
rm -rf /var/db/freebsd-update
mkdir /var/db/freebsd-update
We upgraded to 13.0:
We installed kernel and modules:
We installed userspace/binaries/libraries:
The assistant informs us that we must reinstall all installed packages:
Completing this upgrade requires removing old shared object files.
Please rebuild all installed 3rd party software (e.g., programs
installed from the ports tree) and then run "/usr/sbin/freebsd-update install"
again to finish installing updates.
We reinstall according to whether we use binary packages or ports:
pkg upgrade
git -C /usr/ports pull
cd /usr/ports
make fetchindex
for PORT in $(pkg info|awk '{print$1}'); do PORT_PATH=$(pkg info $PORT|grep Origin|awk '{print$3}') && echo PORT: $PORT - $PORT_PATH && cd /usr/ports/$PORT_PATH && export BATCH="yes" && make clean reinstall clean; done
It will detect the ABI change and reinstall all installed packages.
We remove old libraries and files:
Exit the chroot:
Unmount the BE:
Activate the BE to be loaded on the next boot:
Another important aspect of the OS is the loader, to switch to version 13.0 we must also update it.
Loader update: EFI
Locate the EFI partition:
40 409600 nvd0p1 efi (200M)
Mount the partition and display its contents:
find /mnt
/mnt
/mnt/efi
/mnt/efi/boot
/mnt/efi/boot/BOOTx64.efi
/mnt/efi/boot/startup.nsh
/mnt/System Volume Information
Update the loader:
Unmount the EFI partition:
In the following link, we can see the change in managing the EFI partition:
https://www.freebsd.org/releases/13.0R/relnotes/#boot
Prior releases had a complete ms-dos formatted filesystem packaged into boot1.efifat. Older versions of FreeBSD installed this filesystem image into a raw partition. However, uses of the ESP have proliferated, making this inflexible approach no longer desirable.
Users have varied needs for the size of this partition, and multiple booting setups require more detailed access.
To update old ESP partitions, users should stop using the gpart(8) utility. Instead, ESP partitions should be mounted as MS-DOS filesystems as /boot/efi, and /boot/loader.efi should be copied to /boot/efi/efi/boot/bootx64.efi if the default setup is use.
If the efibootmgr(8) utility is used to customize the boot environment, this file should be copied to the location set with the -l flag.
Previously, an image of the EFI partition was directly dumped to a partition:
gpart bootcode -p /boot/boot1.efifat -i 1 vtbd1
Now, mount the EFI partition and copy the file:
loader.efi
Loader update: BIOS
If we boot using BIOS, we need to locate the boot partition:
40 1024 ada0p1 freebsd-boot (512K)
Dump the contents of the file /boot/pmbr to the MBR (first 512 bytes) of the disk and the contents of the file /boot/gptzfsboot to the boot partition:
partcode written to ada0p1
bootcode written to ada0
Restart:
If something goes wrong, we can always boot into the other BE.
If, on the other hand, we lose the bootloader, we can restore it by booting a FreeBSD13 ISO and copying loader.efi to the EFI partition or rewriting the MBR and boot partition if using BIOS mode.
In EFI mode, we will see the new loader:
In BIOS mode, we will continue with the old one:
Check the version:
13.0-RELEASE
When we are sure that the new version works fine, we can rename the BE:
bectl rename 13 default
ZFS update
When the ZFS code is updated, we need to update the system pools to enable the new functionalities:
pool: zroot
state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
the pool may no longer be accessible by software that does not support
the features. See zpool-features(5) for details.
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
nvd0p4 ONLINE 0 0 0
errors: No known data errors
Update the pool:
pool: zroot
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
nvd0p4 ONLINE 0 0 0
errors: No known data errors
FUSE update
The name of the FUSE kernel module has been renamed, so we update the module list:
kld_list="nvidia-modeset fusefs vmm if_tap if_bridge nmdm linux linux64 linprocfs linsysfs fdescfs"
IOCAGE update
First, we update the parent to 13.0 following the previous steps in this same article.
The next step is to update both the OS and the packages to their latest version in each of the jails.
pkg autoremove
Now we can update them to 13.0. We download the RELEASE from Iocage:
[0] 11.2-RELEASE
[1] 11.3-RELEASE
[2] 11.4-RELEASE
[3] 12.0-RELEASE
[4] 12.1-RELEASE
[5] 12.2-RELEASE
[6] 13.0-RELEASE
Type the number of the desired RELEASE
Press [Enter] to fetch the default selection: (13.0)
Type EXIT to quit:
Fetching: 13.0-RELEASE
We update each of the jails:
iocage update $JAILNAME
iocage console $JAILNAME
If we see the following error message, we need to change the shell to the default one before accessing the jail:
ld-elf.so.1: Shared object “libncursesw.so.8” not found, required by “bash”
Inside the jail
Depending on whether we use binary packages or ports, we will execute:
pkg-static upgrade -f
git -C /usr/ports pull
cd /usr/ports
make fetchindex
for PORT in $(pkg info|awk '{print$1}'); do PORT_PATH=$(pkg info $PORT|grep Origin|awk '{print$3}') && echo PORT: $PORT - $PORT_PATH && cd /usr/ports/$PORT_PATH && export BATCH="yes" && make clean reinstall clean; done
When we finish, we exit the jail.
We revert the shell change:
We finish the update:
NOTE: Updates using Iocage automatically create a snapshot with each update, so if something goes wrong, it can be easily reverted.
But we need to keep in mind that snapshots take up disk space:
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
storage 928G 822G 106G - - 34% 88% 1.00x ONLINE -
zroot 109G 104G 5.38G - - 87% 95% 1.00x ONLINE -
+----------------+-------+------+------+-------+-------+
| NAME | CRT | RES | QTA | USE | AVA |
+================+=======+======+======+=======+=======+
| Andromeda | 1.56x | none | none | 3.48G | 13.5G |
+----------------+-------+------+------+-------+-------+
| DrWho | 1.74x | none | none | 7.33G | 13.5G |
+----------------+-------+------+------+-------+-------+
| HAProxy | 1.59x | none | none | 4.71G | 13.5G |
+----------------+-------+------+------+-------+-------+
| Infinity | 1.56x | none | none | 4.09G | 13.5G |
+----------------+-------+------+------+-------+-------+
| Lomax | 1.42x | none | none | 5.82G | 13.5G |
+----------------+-------+------+------+-------+-------+
| Mistery | 1.50x | none | none | 12.4G | 13.5G |
+----------------+-------+------+------+-------+-------+
| Potras | 1.61x | none | none | 6.33G | 13.5G |
+----------------+-------+------+------+-------+-------+
| basic_template | 1.64x | none | none | 4.46G | 13.5G |
+----------------+-------+------+------+-------+-------+
| redis00 | 1.55x | none | none | 3.37G | 13.5G |
+----------------+-------+------+------+-------+-------+
| redis01 | 1.58x | none | none | 3.39G | 13.5G |
+----------------+-------+------+------+-------+-------+
| redis02 | 1.58x | none | none | 3.39G | 13.5G |
+----------------+-------+------+------+-------+-------+
| rxWod | 1.75x | none | none | 10.1G | 13.5G |
+----------------+-------+------+------+-------+-------+
Once we are sure that the jail is working fine, we can clean up the snapshots:
JAIL=….
for SNAPTOREMOVE in $(iocage snaplist $JAIL|grep -v root|grep -v ‘+’|grep -v ‘NAME’|awk ‘{print$2}’); do
iocage snapremove -n $SNAPTOREMOVE $JAIL
done
Iocage - Template
To update templates, we first need to convert them to a jail, update them, and then convert them back to a template:
+-----+----------------+-------+--------------+--------------+
| JID | NAME | STATE | RELEASE | IP4 |
+=====+================+=======+==============+==============+
| - | basic_template | down | 12.2-RELEASE | 192.168.69.9 |
+-----+----------------+-------+--------------+--------------+
iocage start $JAIL
Update it as if it were a regular jail:
Delete the template snapshots:
JAIL=….
for SNAPTOREMOVE in $(iocage snaplist $JAIL|grep -v root|grep -v ‘+’|grep -v ‘NAME’|awk ‘{print$2}’); do
iocage snapremove -n $SNAPTOREMOVE $JAIL
done
Convert it back to a template:
+-----+----------------+-------+--------------+--------------+
| JID | NAME | STATE | RELEASE | IP4 |
+=====+================+=======+==============+==============+
| - | basic_template | down | 13.0-RELEASE | 192.168.69.9 |
+-----+----------------+-------+--------------+--------------+
Poudriere
We download the new RELEASE version:
JAILNAME VERSION ARCH METHOD TIMESTAMP PATH
freebsd_12-2x64 12.2-RELEASE-p6 amd64 ftp 2021-05-10 23:36:10 /usr/local/poudriere/jails/freebsd_12-2x64
freebsd_13-0x64 13.0-RELEASE amd64 ftp 2021-05-17 15:19:03 /usr/local/poudriere/jails/freebsd_13-0x64
We migrate the generic compilation options:
The options by package:
The configuration of compilation options:
We update the jail and ports:
poudriere ports -u -p HEAD
We compile the ports:
The client part would be as follows:
poudriere: {
url: "http://poudriere.alfaexploit.com/packages/freebsd_13-0x64-HEAD/",
mirror_type: "http",
signature_type: "pubkey",
pubkey: "/usr/local/etc/ssl/certs/poudriere.cert",
enabled: yes,
}
We check that the repository content is accessible:
<html>
<head><title>Index of /packages/</title></head>
<body>
<h1>Index of /packages/</h1><hr><pre><a href="../">../</a>
<a href="freebsd_12-2x64-HEAD/">freebsd_12-2x64-HEAD/</a> 10-May-2021 21:37 -
<a href="freebsd_13-0x64-HEAD/">freebsd_13-0x64-HEAD/</a> 17-May-2021 17:54 -
</pre><hr></body>
</html>
We recompile all the packages:
If we use an automatic script on the build server as indicated
here
, we must also modify it:
#!/usr/local/bin/bash
poudriere jail -u -j freebsd_13-0x64
poudriere ports -u -p HEAD
poudriere options -j freebsd_13-0x64 -p HEAD -f /usr/local/etc/poudriere.d/port-list
poudriere bulk -j freebsd_13-0x64 -p HEAD -f /usr/local/etc/poudriere.d/port-list
Poudriere - Cleaning
We remove the jail:
We remove the source code of the packages:
We remove the logs:
We remove the compiled packages:
We remove some residual directories:
rm -rf /usr/local/etc/poudriere.d/freebsd_12-2x64-HEAD-options
rm /usr/local/etc/poudriere.d/freebsd_12-2x64-make.conf
We remove the old version of the data.json file: