Updating FreeBSD in iocage

In this document we will explain how to migrate to a newer FreeBSD version both on hosts and on jails.

You can always refer to Chapter 24: Updating and Upgrading FreeBSD for more detailed information.

Updating the host

FreeBSD is known for being reliable and to be painlessly upgradeable, even with custom setups, like I do, with manual partitioning, ZFS on root, FreeBSD can handle this easily.

We should start by evaluating the current version we have installed, with:

uname -mrs

which in my case renders FreeBSD 12.2-RELEASE amd64.

We should make sure you apply all existing pending updates for FreeBSD 12.x:

sudo freebsd-update fetch sudo freebsd-update install sudo pkg update sudo pkg upgrade

Make sure to have a snapshot of the machine or VMWare snapshot for a VM.

Once all updates are installed, we can then proceed to do the upgrade (in this case to 13.0-RELEASE):

sudo freebsd-update -r 13.0-RELEASE upgrade

After that process is done, which may take a while, you will get prompted

To install the downloaded upgrades, run "/usr/sbin/freebsd-update install"

You should thus run:

sudo /usr/sbin/freebsd-update install

Then reboot the machine, then run again:

sudo /usr/sbin/freebsd-update install

Then you should perform a second reboot and you will have a system with the new OS but old packages.

Your /etc/resolv.conf might be overriden during the update. Make sure to check this.

The next logical step to follow, after the last reboot, is to upgrade all packages of the system, once again with:

sudo pkg update sudo pkg upgrade

Once all software is up-to-date, run again:

sudo /usr/sbin/freebsd-update install

and another reboot is recommended.

Updating jails

Even though this is a low-risk process, for production systems that cannot allow any downtime it is recommended to simply create a new jail with the new release, and switch traffic to the new jail. This requires more work, but will be safer, and is a benefit of having a jailed environment.

Upon a successful update of your host's system, any of your existing jails will still be using the release where you created them. Ideally you should always keep your jails to the same major release as your host.

You can get an overview of your jails with:

sudo iocage list

You should pre-fetch the wanted release files, which will then be available for all upgrades and for any new jails you might want to create with said version.

sudo iocage fetch -r 13.0-RELEASE

If the machine you are working on contains many jails, you should likely open several SSH sessions and upgrade the jails in parallel, of course at the cost of CPU & RAM usage.

In order to upgrade a jail's FreeBSD version you should run:

sudo iocage upgrade <name of your jail> -r 13.0-RELEASE

then we must update all packages within the jail:

sudo iocage pkg <name of your jail> update sudo iocage pkg <name of your jail> upgrade -y

it is recommendable to restart the jail after the procedure:

sudo iocage restart <name of your jail>

Cleaning up

It is highly recommendable to cleanup your system after verifying everything is stable and in order. Several files, backups and rollbacks can then be deleted, often saving 8GB+ of space. There are several handy tricks to be able to clean a FreeBSD machine and shave some disk GB.

You can do some cleanup by removing the fetched pkg files, both on your host

sudo pkg clean

and on your jails:

sudo iocage pkg <your jail> clean -y

You can check the current allocated size for zpools by running:

zpool list NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT iocage 19.5G 13.5G 5.97G - - 66% 69% 1.00x ONLINE - zroot 17.5G 3.72G 13.8G - - 23% 21% 1.00x ONLINE -

You can check which zfs file systems are currently taking more space with:

zfs list NAME USED AVAIL REFER MOUNTPOINT iocage 13.5G 5.38G 24K /iocage iocage/iocage 13.5G 5.38G 29.5K /iocage/iocage iocage/iocage/download 803M 5.38G 24K /iocage/iocage/download iocage/iocage/download/12.2-RELEASE 402M 5.38G 402M /iocage/iocage/download/12.2-RELEASE iocage/iocage/download/13.0-RELEASE 401M 5.38G 401M /iocage/iocage/download/13.0-RELEASE iocage/iocage/images 24K 5.38G 24K /iocage/iocage/images iocage/iocage/jails 10.5G 5.38G 24K /iocage/iocage/jails iocage/iocage/jails/elk-d 4.19G 5.38G 25.5K /iocage/iocage/jails/elk-d iocage/iocage/jails/elk-d/root 4.19G 5.38G 4.51G /iocage/iocage/jails/elk-d/root iocage/iocage/jails/jaeger-d 4.00G 5.38G 25.5K /iocage/iocage/jails/jaeger-d iocage/iocage/jails/jaeger-d/root 4.00G 5.38G 4.32G /iocage/iocage/jails/jaeger-d/root iocage/iocage/jails/web-server-d 2.26G 5.38G 25.5K /iocage/iocage/jails/web-server-d iocage/iocage/jails/web-server-d/root 2.26G 5.38G 2.57G /iocage/iocage/jails/web-server-d/root iocage/iocage/log 28K 5.38G 28K /iocage/iocage/log iocage/iocage/releases 2.26G 5.38G 24K /iocage/iocage/releases iocage/iocage/releases/12.2-RELEASE 1.20G 5.38G 24K /iocage/iocage/releases/12.2-RELEASE iocage/iocage/releases/12.2-RELEASE/root 1.20G 5.38G 1.20G /iocage/iocage/releases/12.2-RELEASE/root iocage/iocage/releases/13.0-RELEASE 1.06G 5.38G 24K /iocage/iocage/releases/13.0-RELEASE iocage/iocage/releases/13.0-RELEASE/root 1.06G 5.38G 1.06G /iocage/iocage/releases/13.0-RELEASE/root iocage/iocage/templates 24K 5.38G 24K /iocage/iocage/templates zroot 3.72G 13.2G 24K /zroot zroot/ROOT 3.23G 13.2G 24K none zroot/ROOT/default 3.23G 13.2G 3.23G / zroot/tmp 26.5K 13.2G 26.5K /tmp zroot/usr 497M 13.2G 24K /usr zroot/usr/home 3.50M 13.2G 3.50M /usr/home zroot/usr/obj 24K 13.2G 24K /usr/obj zroot/usr/ports 72K 13.2G 24K /usr/ports zroot/usr/ports/distfiles 24K 13.2G 24K /usr/ports/distfiles zroot/usr/ports/packages 24K 13.2G 24K /usr/ports/packages zroot/usr/src 493M 13.2G 493M /usr/src zroot/var 259K 13.2G 24K /var zroot/var/audit 24K 13.2G 24K /var/audit zroot/var/crash 24K 13.2G 24K /var/crash zroot/var/log 135K 13.2G 135K /var/log zroot/var/mail 28K 13.2G 28K /var/mail zroot/var/tmp 24K 13.2G 24K /var/tmp

By looking at the above output you can see we have both the 12.2-RELEASE and 13.0-RELEASE versions of FreeBSD saved in our machine. In our case, we have successfully upgraded to 13.0-RELEASE and thus can remove all files stored related to 12.2-RELEASE. We can do this by simply removing the zfs dataset containing the 12.2-RELEASE download:

sudo zfs destroy -r iocage/iocage/download/12.2-RELEASE

Be extremely wary when running this command and ask someone more experienced if you are doubting!

We also can then clean the freebsd-update remaining files by removing the rollback and creating a new empty folder:

sudo rm -rf /var/db/freebsd-update/files sudo mkdir /var/db/freebsd-update/files sudo chmod 755 /var/db/freebsd-update/files

This should also be done in the jails if you upgraded them:

sudo iocage exec <your jail> rm -rf /var/db/freebsd-update/files sudo iocage exec <your jail> mkdir /var/db/freebsd-update/files sudo iocage exec <your jail> chmod 755 /var/db/freebsd-update/files

When you update to a new major version you might end up keeping old datasets lying around. These can be seen like above in the output of zfs list.

Very likely at iocage/iocage/releases/12.2-RELEASE and iocage/iocage/releases/12.2-RELEASE/root.

We must first find the "cloned" datasets with:

sudo zfs list -t snapshot -o name,clones

which outputs something like:

NAME CLONES iocage/iocage/releases/12.2-RELEASE/root@database iocage/iocage/jails/database/root iocage/iocage/releases/12.2-RELEASE/root@cache-store iocage/iocage/jails/cache-store/root

and then we can promote the clones to be the primary datasets for that jail:

sudo zfs promote iocage/iocage/jails/database/root sudo zfs promote iocage/iocage/jails/cache-store/root

The clones can be removed with:

sudo zfs destroy iocage/iocage/releases/12.2-RELEASE/root sudo zfs destroy iocage/iocage/releases/12.2-RELEASE

After all the cleanup it is recommended to restart the machine and verify it all works as expected.