BSD DevCenter
oreilly.comSafari Books Online.Conferences.


Building a FreeBSD Build System
Pages: 1, 2, 3

Next, mount the new filesystem entries in /etc/fstab:

% mount -a

Next, configure your clients' /etc/make.conf, which should match the build server pretty closely. My typical make.conf is:


Because you won't be able to write to the /usr/ports mount, add a line so that you can still build ports locally:


To configuring which kernel to use, add the line:


There's a distinction to consider here. You will definitely want to set different values for the KERNCONF variable between your build server and your clients. You must add every kernel to the KERNCONF variable on the build server that you want to be available to your build set. On every client in your build set, you need to set only one kernel in the KERNCONF variable.

If you have portupgrade installed, add the following to /usr/local/etc/pkgtools.conf; otherwise, it will fail:

ENV['PORTS_INDEX'] = '/usr/work'
ENV['PORTS_DBDIR'] = '/usr/work'

RCS and mergemaster

The biggest trick with the biggest time benefit is to configure mergemaster to be a fast process. The maintainer of mergemaster has gone to great lengths to keep it very hands-on, so that new users don't run into trouble or misunderstand what it does while it runs. While this step of the build system removes some of the hands-on requirements, I have built in some safety nets that will keep you from falling too hard in the event of a mistake.

I set the MM_PRE_COMPARE_SCRIPT hook to mergemaster by creating an /etc/mergemaster.rc file:

PRESERVE_FILES_DIR=/var/tmp/mergemaster/preserved-files-`date +%y%m%d-%H%M%S`

mergemaster will automatically find and source this file by default. This rc file tells mergemaster to call a script called /usr/src/ I put this into /usr/src so that any client using the build system can also source it. One problem with this is that I cannot guarantee that the FreeBSD organization won't horribly disfigure or abuse the src folder. It's under its control, so to make this setup more solid, it's best to keep the script in another location and copy it to /usr/src nightly, or make it a local package and install it to all the clients.

The next step is to put your configs under RCS. The first safety net of this script is that if the /etc/RCS directory does not exist, it won't do anything different from what mergemaster already does. Once you create the /etc/RCS directory, you activate it. Be sure to put any and all config files you have modified under RCS with:

% ci -l -t-Import filename

I've modified a few config files under /etc:


If you want to keep your SSH host keys, add:


mergemaster will update some files under boot, root, var, and of course etc. Test this on your staging server. After running it, you can always recover from the directory you set for the PRESERVE_FILES_DIR in the mergemaster.rc file. (Everything replaced automatically will go into a subfolder called rcs_mergemaster.)

This addition does two things. First, it installs any file that is included with the latest release as long as the file it replaces does not have a corresponding RCS entry. If it does, it will assume you have updated the file and will continue with the standard mergemaster method of showing you the differences and offering to merge. The second addition, or side benefit, is that you now can keep your config files in version control. No longer do you need to keep 100 dated or initialed backups before making a change. Just check it in with a lock, and write a short message about your change when you are done modifying it.

The only problem is you now have to convert all your coworkers to the RCS way. There is a way around that as well. I have included a script called that you can run at night; it will check in while locking any files that have already been placed under RCS. Just set the directory it should search under for its argument.

Update Procedure

Now it's time to reap the reward of the ultimate build system. What complicated and wizardly commands do you need to know? Just the familiar old procedure (which you should of course test on the staging server first):

% mergemaster -p
% make installkernel
% reboot
% make installworld
% mergemaster
% reboot

You have now completed your first update on the ultimate updater. Keep in mind that you still need to follow the upgrade guidelines. For instance, upgrading from 4.11 to 6.0 requires an intermediate upgrade to 5.3. Also, you may want to look to such projects as clusterssh to perform multiple upgrades/updates at once or cfengine to automate the builds to run.


Meyer, Mike. "Tracking for Multiple Machines," FreeBSD Handbook, 2005 (accessed January 13, 2006).

Thanks goes to the mailing lists of,, and

Bjorn Nelson built a FreeBSD build system while working as a system administrator at Baruch College.

Return to the BSD DevCenter.

Sponsored by: