System: up-to-date with FreeBSD

Jochem Kossen (aka jk)
Author's Homepage:

last updated November 5, 2002
(created October 20, 2001)


After a FreeBSD -RELEASE has been released, development continues to the next version. Development is done in a number of branches, like -STABLE and -CURRENT. In this article I'll explain how to track the -STABLE branch.

-STABLE is the branch which will bring the next stable release. -CURRENT is the unstable development branch. -CURRENT is only meant for developers!

NB: -STABLE is a BRANCH. That means it is being developed constantly. This also means -STABLE could be broken at any moment. Do not worry though, I've never noticed any problem with it...

Sites used for information:


1 Updating sources

  1. install system sources
    # /stand/sysinstall

    Choose ``Configure'', then ``Distributions'', then ``src'', and there choose ``all'', then ``Exit'', and ``OK'', and follow directions on screen to install them.

  2. install the net/cvsup port
    # cd /usr/ports/net/cvsup
    # make WITHOUT_X11=yes install clean

    Note: old versions of cvsup-bin (pre 16.1e) had a bug which caused those versions to be incompatible with newer cvsup servers. If you have such an old version, please fetch a newer package from

  3. open etc/make.conf with your favorite text-editor. If /etc/make.conf doesn't exist, create it. Add the following lines to it:
    SUP=            /usr/local/bin/cvsup
    SUP_UPDATE=     yes
    SUPFILE=        /usr/share/examples/cvsup/stable-supfile
    PORTSSUPFILE=   /usr/share/examples/cvsup/ports-supfile
  4. update the sources and the ports tree
    # cd /usr/src
    # make update

    or, to only update ports:

    # cd /usr/ports
    # make update

    Note: If you only want to update ports, you can now skip to section [*] on page [*] .

2 Building the base system and kernel

  1. Read /usr/src/UPDATING

    UPDATING contains important information and clues needed for upgrading FreeBSD. It could be you need to add a user first, or enable a device in your kernel, or whatever. Things like this are in UPDATING, so read it:

    # less /usr/src/UPDATING
  2. remove old obj files
    # cd /usr/obj
    # chflags -R noschg *
    # rm -fr *
  3. update files essential for buildworld
    # mergemaster -p
    (for complete usage of mergemaster, see section [*] on page [*])

    Note: the -p option of mergemaster first appeared in FreeBSD 4.6. If you're running an older version, just copy /usr/src/usr.sbin/mergemaster/ to /usr/sbin/mergemaster, and use that.

  4. build the world
    # cd /usr/src
    # make -j4 buildworld
  5. build the kernel

    (change MYKERNEL to the name of your custom kernel configuration file or GENERIC if you don't use a custom configured kernel)

    # cd /usr/src
    # make -j4 buildkernel KERNCONF=MYKERNEL

3 Installing the base system and kernel

If you've never used mergemaster before, now is a good time for practicing mergemaster, which you need later on to update /etc. Read section [*] on page [*] and after that, return to this.

  1. install your new kernel:

    (change MYKERNEL to the name of your custom kernel configuration file or GENERIC if you don't use a custom configured kernel)

    # cd /usr/src
    # make installkernel KERNCONF=MYKERNEL
  2. reboot with your new kernel into single-user mode
    # reboot space at the boot prompt, then enter boot -s and press Enter or Return...

    This is what the mentioned boot prompt looks like:

    Hit [Enter] to boot immediately, or any other key for command prompt.
    Booting [kernel] in 9 seconds...
  3. it asks for the location of the shell to be used

    choose /bin/sh (just press Enter or Return as this is the default)

  4. install the world
    # mount -a -t nonfs
    # cd /usr/src
    # make installworld
  5. update /etc
    # rm -fr /etc.old
    # cp -Rp /etc /etc.old
    # /usr/sbin/mergemaster
  6. update /stand
    # cd /usr/src/release
    # make all install
  7. reboot and enjoy your new -STABLE system
    # fastboot

4 Upgrading ports/packages

Note: if you didn't update the ports tree yet (with make update), read section [*] on page [*] first.

With the sup file demonstrated in Section 1, you also fetched an updated ports tree in /usr/ports. In this section I'll demonstrate how to use the ports tree to upgrade the installed packages/ports easily.

  1. install the sysutils/portupgrade port

    Portupgrade is a very nice tool which makes upgrading of FreeBSD ports and packages real easy.

    # cd /usr/ports/sysutils/portupgrade
    # make install distclean
  2. check which packages need updating

    Not really necessary, but i like to see which packages need updating

    # pkg_version -v |grep -v up-to-date |less
  3. upgrade the ports

    Portupgrade keeps track of it's own package database as well as the main FreeBSD package database. Sometimes after an upgrade, dependencies are incorrectly set in portupgrade's database. This happens when upgrading a port on which another port which is not upgraded depends

    This is easily fixed by issuing this command before using portupgrade, and i recommend doing it before each use of the portupgrade command:

    # pkgdb -F

    You can use different approaches, the simplest is this, which upgrades all port:

    # portupgrade -a

    You can also upgrade just one port, lets say aalib needs updating:

    # portupgrade aalib

    Something slightly more complex: I want to upgrade gdbm and all it's upward-recursive and downward recursive dependencies:

    # portupgrade -rR gdbm

    Here's how to upgrade all packages, downwards-recursive AND upwards-recursive, and clean up obsolete shared libraries:

    # portupgrade -urRa

    Damn, this is becoming too easy! As a last example, here's how to upgrade a few packages, and the last one with the WITHOUT_GNOME=yes argument

    # portupgrade Xaw3d pwm python -m WITHOUT_GNOME=yes gaim

    Portupgrade is very powerful, and the man-pages are very well written. Please consult them for more instructions.

5 Using Mergemaster

mergemaster is used to update configuration files in /etc. To practice, it's a good idea to use a fake /etc directory, so you won't screw your real /etc directory.

# mkdir /practice
# cp -R /etc /practice/etc
# /usr/sbin/mergemaster -D/practice

Now you can screw up everything you want, because mergemaster will only change files in the /practice directory.

When calling the command mergemaster, it creates a directory /var/tmp/temproot in which it creates a new version of the /etc directory, or in the practicing case a new version of the /practice/etc directory. After that, mergemaster starts comparing files from both directories.

When it finds a file in /var/tmp/temproot which differs from the file in /etc (or /practice/etc), it shows the difference between the files, and offers you a few choices:

  *** Displaying differences between ./etc/defaults/rc.conf and installed versio
--- /practice/etc/defaults/rc.conf      Wed May  1 12:25:41 2002
+++ ./etc/defaults/rc.conf      Thu May  2 12:19:09 2002
@@ -13,7 +13,7 @@
+# For the following option you need to have TCP_DROP_SYNFIN set in your
+# kernel.  Please refer to LINT and NOTES for details.
 tcp_drop_synfin="NO"           # Set to YES to drop TCP packets with SYN+FIN
                                # NOTE: this violates the TCP specification
-icmp_drop_redirect="NO"              # Set to YES to ignore ICMP REDIRECT pac
+icmp_drop_redirect="YES"       # Set to YES to ignore ICMP REDIRECT packets
 icmp_log_redirect="NO"         # Set to YES to log ICMP REDIRECT packets
 network_interfaces="auto"      # List of network interfaces (or "auto").
 cloned_interfaces=""           # List of cloned network interfaces to create.
  Use 'd' to delete the temporary ./etc/defaults/rc.conf
  Use 'i' to install the temporary ./etc/defaults/rc.conf
  Use 'm' to merge the temporary and installed versions
  Use 'v' to view the diff results again
  Default is to leave the temporary file to deal with by hand
How should I deal with this? [Leave it for later]

Lines beginning with + are only in the new file. Lines beginning with - are only in the old file. Lines without either a + or - at the beginning are context lines, lines which are the same in both files.

Sometimes, mergemaster comes across a file in /var/tmp/temproot which doesn't exist in the old /etc. Then it offers only the d and i options. It's recommended to choose i in this case, unless you know what you're doing.

After either of these options, with the exception of the m option, mergemaster moves on to compare the next two files, and goes through the same cycle for those files again.

When you choose m, it starts a utility called sdiff (consult sdiff(1) too) which displays two sections from both files which are different next to each other, separated by a pipe ( | ), and beneath that a prompt ( % ). The whole thing could look like this:

icmp_drop_redirect="NO"           # Set | icmp_drop_redirect="YES"         # Set

The version left from the | represents the version from the old file. The version right from the | represents the version from the new file.

You can press h and Enter or Return for help.

Mostly, you'll only need to use l (use version left from the |) and r (use version right from the |)

If you need both versions concatenated, use e b. This will open up an editor (specified by the EDITOR environment variable), and you can edit the result.

Warning: Never press q. This will end the sdiff session, and leave you with an empty file.

When the merging is done (when it reaches the end of both files) it will end itself, and mergemaster will re-appear asking you what to do with the merged file:

  Use 'i' to install merged file
  Use 'r' to re-do the merge
  Use 'v' to view the merged file
  Default is to leave the temporary file to deal with by hand
    *** How should I deal with the merged file? [Leave it for later]

Sometimes it's a good idea to first choose v before you decide what to do with the merged file.

If you choose i, it will install the merged file, and mergemaster will continue to compare the next two files. If you want to keep your old file, just press Enter. Press r to re-do the merging.

6 Q/A

  1. What does the ``tag=.'' part mean in the ports-all line?

    It means it will fetch the -CURRENT branch of ports. For ports there's only one branch. There is no -STABLE branch of ports, so the -CURRENT branch of ports is the one to use.

  2. Then why don't you change the ``*default tag=RELENG_4'' line to ``*default tag=.''?

    DON'T DO THAT !!! It would mean we're going to fetch -CURRENT (unstable development) system sources. Those are only for developers and testers (experienced people).

  3. Which *default tags exist?

    Check Basically, at the time of this writing, these are of interest:

7 Noticable changes to this document