FreeBSD 4.8 to FreeBSD 4.11 binary upgrade

Shortly before the End-of-Life for FreeBSD 4.8, I sent out a "heads up" to a few fora warning people that now was the time to upgrade to FreeBSD 4.11. Unsurprisingly, several people replied with the obvious question: "How?"

The most standard approach to upgrading FreeBSD between versions has always been to update the /usr/src tree (usually using cvsup) and run the "buildworld", "buildkernel", "installkernel", and "installworld" steps. Since unnecessary compilation is undesireable, I decided to put together a step-by-step guide to upgrading to FreeBSD 4.11 using the published ISO image. Of course, this is only useful if you are happy with a GENERIC kernel.

What follows are the steps I used to upgrade my FreeBSD 4.8-RELEASE-p27 box to FreeBSD 4.11-RELEASE; I can't guarantee that they'll work for everyone, but this should be at least a good starting point.

N.B. I only install the "bin", "crypto", "dict", "doc", and "manpages" distributions here -- I don't want the "catpages", compat, "games", "info", "ports", "proflibs", or "src" distributions. If you want a different set of distributions, change the lists in steps 6, 9, and 10.

  1. If you haven't done so already, install FreeBSD Update.

    cd /usr/ports/security/freebsd-update && make install clean
    cp /usr/local/etc/freebsd-update.conf.sample /usr/local/etc/freebsd-update.conf
  2. Using FreeBSD Update, generate a list of files from the base system which have been locally modified. We might not want to overwrite these.

    freebsd-update -v IDS | tail +8 | grep . | lam -s '.' - > /root/base-modified
  3. Edit this list and delete files for which you don't want to keep your local changes. You'll almost certainly want to delete any lines starting with ./usr/, but you'll probably want to keep the lines which start with ./etc/ or ./var/log/.

    ee /root/base-modified
    (or use vi or any other text editor you have installed.)

  4. Generate a list of files installed which belong to the old RELEASE. We'll be using this list to make sure we don't leave old files lying around after the upgrade.

    cut -f 1 -d '$' /usr/local/freebsd-update/work/md5all | uniq |
    	while read X; do
    		if [ -f $X ]; then echo $X; fi;
    	done | sort > /root/base-old
  5. Download an ISO image for the new release and mount it.

    fetch -o /usr/miniinst.iso	\
    vnconfig -c /dev/vn0 /usr/miniinst.iso
    mount -t cd9660 -o ro /dev/vn0 /mnt
  6. For the files which have been locally modified, extract the new versions to a temporary directory.

    mkdir /usr/release
    for dist in bin crypto dict doc manpages; do
    	cat /mnt/${dist}/${dist}.?? |
    		tar -xpzf - -I /root/base-modified -C /usr/release
    done 2>/dev/null
  7. For each of these files (in /root/base-modified), compare the existing and new versions to see if you need to update anything. (I didn't, but sometimes there are necessary changes in configuration files -- for example, in FreeBSD 4.7 a new "sshd" user was added.)

    diff -u /etc/group /usr/release/etc/group
    diff -u /etc/ttys /usr/release/etc/ttys
  8. Clear the immutable flag on files from the base system to make sure that we can overwrite or delete them.

    xargs chflags noschg < /root/base-old
  9. Extract the new release (minus the locally modified files that we don't want to overwrite).

    for dist in bin crypto dict doc manpages; do
    	cat /mnt/${dist}/${dist}.?? |
    		tar -xpzf - -X /root/base-modified -C /
  10. Generate a list of files which belong to the new release, and compare this to the list of files which were in the old release, so that we can clean up the garbage left behind.

    ( for dist in bin crypto dict doc manpages; do
    	cat /mnt/${dist}/${dist}.?? | tar -tzf -
    done; cat /root/base-modified ) | sort | uniq | cut -c 2- > /root/base-new
    comm -13 base-new base-old | xargs rm
  11. Link the GENERIC kernel into /kernel.

    ln /kernel.GENERIC /kernel
  12. Clean up.

    umount /mnt
    vnconfig -u vn0c
    rm -r /usr/release
    rm /usr/miniinst.iso
    rm /root/base-modified /root/base-old /root/base-new
  13. Reboot into your new 4.11-RELEASE system.

    shutdown -r now