OpenBSD FAQ - Building the System from Source [FAQ Index]

OpenBSD's flavors

There are three flavors of OpenBSD: Graphically, the development of these flavors looks something like this:
       ,------o-----------o----X                    5.6 Stable
       |      .           .
       |      .    ,------o---------o----X          5.7 Stable
       |      .    |      .         .
       |      .    |      .    ,----o----------o--> 5.8 Stable
       |      .    |      .    |    .          .
       |      .    |      .    |    .    ,-----o--> 5.9 Stable
       |      .    |      .    |    .    |     .
       |      .    |      .    |    .    |     .
 -->5.6Rel----->5.7Rel----->5.8Rel----->5.9Rel----> Current

          Time --->
In the above illustration, the vertical dotted lines denote bug fixes being incorporated into the -stable branches.

Further thoughts on the three flavors are here.

What are snapshots?

Between formal releases of OpenBSD, snapshots are made available through the mirrors. These are builds of whatever code is in the tree at the instant the builder grabbed a copy of the code for that particular platform.

It is possible that you may uncover bugs in snapshots. This is one of the reasons why they are built and distributed. If you find a bug in a snapshot, make sure it is reported.

If you desire to run -current, a recent snapshot is usually all you need. Upgrading to a snapshot is the starting point before building -current from source.

Details can be found on the following -current page.

What code was used to build a snapshot?

It is sometimes asked if there is any way to get a copy of exactly the code used to build a snapshot. The answer is no.
  1. There is no significant benefit to this.

  2. Snapshots are built as desired, as time permits and as resources become available.

    On fast platforms, several snapshots may be released in one day. On slower platforms, it may take a week or more to build a snapshot. Providing tags or markers in the source tree for each snapshot would be quite impractical.

  3. Snapshots often contain experimental code that isn't yet committed to the CVS tree.

Building OpenBSD from source

The main reference is release(8). Read this manpage before you proceed. This FAQ section is intended to help you with the necessary preparation.


Building OpenBSD from source involves a number of steps:


The actual process of building the base system is explained in steps 2 and 3 of release(8): Some users may also wish to which are the subject of the remainder of release(8).

Upgrade to the closest available binaries

Make sure you have the closest available binaries installed. Use this table to look at where you are, where you wish to go, and what binary you should start with:

You are at Goal Binary upgrade to then ...
Old -release New release Newest release Done!
-release -stable Newest release Fetch & build -stable
Old -stable -stable Newest release Fetch & build -stable
-release -current Latest snapshot (optional) Fetch & build -current
Old -current -current Latest snapshot (optional) Fetch & build -current

It is recommended that you install the binary sets by using the (U)pgrade option of the install media. If that is not possible, you can also unpack the binary sets as described in the upgrade instructions of the release.

Fetching the source code

OpenBSD source is managed using the CVS version control system. The cvs(1) program is used to pull a copy of the desired source to your local machine for compilation. This can be done by using an Anonymous CVS server. You can also maintain a local CVS repository using the CVSync or rsync programs available as packages.

First, you must cvs checkout the source tree. After that, you maintain the tree by running cvs update to pull updated files to your local tree.

An introduction to cvs(1) and detailed instructions for fetching the source trees are on the Anonymous CVS page. If you are new to using cvs(1), you may also want to read the CVS tips below.

Avoiding root privileges

Avoid running cvs(1) as root. The /usr/src directory is writable for wsrc by default. So, add users that need to use cvs(1) to the wsrc group:
# user mod -G wsrc exampleuser
Since they're not part of the base install, you must create the directories and set their permissions manually to make use of the wsrc group:
# cd /usr
# mkdir -p   xenocara ports
# chgrp wsrc xenocara ports
# chmod 775  xenocara ports

Example: Fetching the -current trees

We assume you are using a public Anonymous CVS server, We also assume that sh(1) is the shell.

To checkout a -current src tree, you can use the following:

$ cd /usr
$ export
$ cvs -d$CVSROOT checkout -P src
Once you have a tree, you can update it at a later time:
$ cd /usr/src
$ export
$ cvs -d$CVSROOT up -Pd
If you want them, you can fetch the xenocara and ports trees with
$ cvs -d$CVSROOT checkout -P xenocara ports
As all parts of OpenBSD must be kept in sync, all trees you use should be checked out and updated at the same time.

Example: Fetching the -stable trees

To checkout the -stable trees, do
$ cd /usr
$ export
$ cvs -d$CVSROOT checkout -rOPENBSD_5_9 -P src xenocara ports
and to update, issue
$ cd /usr/src
$ cvs -q up -rOPENBSD_5_9 -Pd
and similarly for /usr/xenocara and /usr/ports.

Build OpenBSD

At this point you are ready to build OpenBSD from source.

If you are building -current, review changes and special build instructions listed in current.html.

Follow the detailed instructions in release(8).

Making a release

A release is the complete set of files that can be used to install or upgrade OpenBSD on another computer. If you have only one computer running OpenBSD, you really don't have any reason to make a release, as the above build process will do everything you need. An example use would be to build -stable on a fast machine, then make a release to be installed on all your other machines.

The instructions on making a release are in release(8). The release process uses the binaries created in the /usr/obj directory in the building process above.

Note: if you wish to distribute the resultant file sets by HTTP for use by the upgrade or install scripts, you will need to add an index.txt file that contains the list of all the files in your newly created release.

# ls -nT > index.txt

Building X

Starting with X.Org v7, X switched to a modular build system, splitting the X.Org source tree into more than three hundred more-or-less independent packages.

To simplify life for OpenBSD users, a meta-build called Xenocara was developed. This system converts X back into one big tree to be built in one process. As an added bonus, this build process is much more similar to the build process used by the rest of OpenBSD than the previous versions were.

The official instructions for building X exist in the xenocara/README file and in step 5 of release(8).

Further reading on the build process

Common problems when compiling

Most of the time, problems in the build process are caused by not following the directions carefully. There are occasional real problems with building -current from the most recent snapshot, but failures when building -release or -stable are almost always user error.

Most problems are usually one of the following:

I forgot to make obj before make build

By doing a make build before doing a make obj, you will end up with the object files scattered in your /usr/src directory. This is a bad thing. If you wish to try to avoid re-fetching your entire src tree again, you can try the following to clean out obj files:
$ cd /usr/src
$ find . -type l -name obj | xargs rm
$ make cleandir
$ rm -rf /usr/obj/*
$ make obj

The build stopped with a "Signal 11" error

Building OpenBSD and other programs from source is a task which pushes hardware harder than most others, making intensive use of CPU, disk and memory. Signal 11 failures are typically caused by hardware problems.

You will probably find it best to repair or replace the components that are causing trouble, as problems may show themselves in other ways in the future.

For much more information, see the Sig11 FAQ.

Miscellaneous questions and tips

Why is /usr/obj on its own partition?

If you build often, one benefit is simple: it is typically much faster to...
# umount /usr/obj
# newfs YourObjPartition
# mount /usr/obj
...than to remove the contents of the directory with rm.

How do I not build parts of the tree?

Use the SKIPDIR option of mk.conf(5).

Can I cross-compile?

Cross-compiling tools are in the system, for use by developers bringing up a new platform. However, they are not maintained for general use.

When the developers bring up support for a new platform, one of the first big tests is a native-build. Building the system from source puts considerable load on the OS and machine, and does a very good job of testing how well the system really works. For this reason, OpenBSD does all the build process on the platform the build is being used for.

Building a custom kernel

It is assumed you really enjoy pain. It is also assumed that you have a goal that can not be achieved by either a boot time configuration (UKC) or by configuring a GENERIC kernel. If all of this is not true, you should stick to using GENERIC. Really.

OpenBSD kernel generation is controlled by configuration files, which are located in the /usr/src/sys/arch/<arch>/conf/ directory by default. All architectures have a file, GENERIC, which is used to generate the standard OpenBSD kernel for that platform. There may also be other configuration files which are used to create kernels with different focuses, for example, for minimal RAM, diskless workstations, etc.

The configuration file is processed by config(8), which creates and populates a compilation directory in ../compile, on a typical installation, that would be in /usr/src/sys/arch/<arch>/compile/. config(8) also creates a Makefile, and other files required to successfully build the kernel.

Kernel configuration options are options that you add to your kernel configuration that place certain features into your kernel. This allows you to have exactly the support you want, without having support for unneeded devices. There are a multitude of options that allow you to customize your kernel. Here we will go over only some of them, those that are most commonly used. Check the options(4) man page for a complete list of options. As these change from time to time, you should make sure you use a man page for the same version of OpenBSD you are building. You can also check the example configuration files that are available for your architecture.

Do not add, remove, or change options in your kernel unless you actually have a reason to do so! Do not edit the GENERIC configuration file!! The only kernel configuration which is supported by the OpenBSD team is the GENERIC kernel, the combination of the options in /usr/src/sys/arch/<arch>/conf/GENERIC and /usr/src/sys/conf/GENERIC as shipped by the OpenBSD team (i.e., NOT edited). Reporting a problem on a customized kernel will almost always result in you being told to try to reproduce the problem with a GENERIC kernel. Not all options are compatible with each other, and many options are required for the system to work. There is no guarantee that a custom-configured kernel can be built. There is also no guarantee that a custom-configured kernel will actually run, even if it compiles properly.

You can see all the platform-specific configuration files in the src/sys/arch directory. As an example, the files for an amd64 kernel would be in src/sys/arch/amd64/conf.

Look closely at these files and you will notice a line near the top similar to:

include "../../../conf/GENERIC"
This means that it is referencing another configuration file, one that stores platform-independent options. When creating your kernel configuration, be sure to look through sys/conf/GENERIC.

Kernel configuration options should be placed in your kernel configuration file in the format of:

option      name
option      name=value
For example, to place option "DEBUG" in the kernel, add a line like this:
option      DEBUG
Options in the OpenBSD kernel are translated into compiler preprocessor options, therefore an option like DEBUG would have the source compiled with option -DDEBUG, which is equivalent to doing a #define DEBUG throughout the kernel.

Sometimes, you may wish to disable an option that is already defined, typically in the src/sys/conf/GENERIC file. While you could modify a copy of that file, a better choice would be to use the rmoption statement. For example, if you really wanted to disable the in-kernel debugger (not recommended!), you would add a line such as:

rmoption DDB
in your kernel configuration file. option DDB is defined in src/sys/conf/GENERIC, but the above rmoption line deactivates it.

Once again, please see options(4) for more information about the specifics of these options. Also note that many of the options also have their own manual pages -- always read everything available about an option before adding or removing it from your kernel.

Building a custom kernel

In this case, we will build a kernel that supports the boca(4) ISA multi-port serial card. This card is not in the GENERIC kernel, due to conflicts with other drivers. There are two common ways to make a custom kernel.

The first method is to create a "wrapper" file that "includes" the standard GENERIC kernel and any options you need that aren't in GENERIC. In this case, our wrapper file looks like this:

include "arch/i386/conf/GENERIC"

boca0  at       isa? port 0x100 irq 10     # BOCA 8-port serial cards
com*   at       boca? slave ?
The two lines regarding the boca(4) card are copied from the commented out lines in GENERIC, with the IRQ adjusted as needed. The advantage to using this "wrapper" file is any unrelated changes in GENERIC are updated automatically with any other source code update. The disadvantage is one can not remove devices (though in general, that's a bad idea, anyway).

The other way to generate a custom kernel is to make a copy of the standard GENERIC config file, giving it another name, then edit as needed. The disadvantage to this method is that later updates to the GENERIC configuration file have to be merged into your copy, or you have to remake your configuration file.

In either event, after making your custom kernel configuration file, use config(8) and make the kernel as documented above.

Full instructions for creating your own custom kernel are in the config(8) man page.

Boot-time configuration

Sometimes when booting your system you might notice that the kernel finds your device but maybe at the wrong IRQ. And maybe you need to use this device right away. Well, without rebuilding the kernel, you can use OpenBSD's boot time kernel configuration. This will only correct your problem for one time. If you reboot, you will have to repeat this procedure. So, this is only meant as a temporary fix, and you should correct the problem using config(8). Your kernel does however need option BOOT_CONFIG in the kernel, which GENERIC does have.

Most of this document can be found in the man page boot_config(8).

To boot into the User Kernel Config, or UKC, use the -c option at boot time.

boot> boot hd0a:/bsd -c
Or whichever kernel it is you want to boot. Doing this will bring up a UKC prompt. From here you can issue commands directly to the kernel specifying devices you want to change or disable or even enable.

Here is a list of common commands in the UKC.

Once you have your kernel configured, use quit or exit and continue booting. After doing so, you should make the change permanent in your kernel image, as described in Using config(8) to change your kernel.

Using config(8) to change your kernel

The -e and -u options of config(8) can be extremely helpful and save wasted time compiling your kernel. The -e flag allows you to enter the UKC or User Kernel Config on a running system. These changes will then take place on your next reboot. The -u flag tests to see if any changes were made to the running kernel during boot, meaning you used boot -c to enter the UKC while booting your system.

The following example shows the disabling of the ep* devices in the kernel. For safety's sake, you must use the -o option which writes the changes out to the file specified. For example: config -e -o /bsd will write the changes to The example doesn't use the -o option, therefore changes are just ignored and not written back to the kernel binary. For more information pertaining to error and warning messages, read the config(8) man page.

# config -e /bsd
ukc> ?
        help                                Command help list
        add             dev                 Add a device
        base            8|10|16             Base on large numbers
        change          devno|dev           Change device
        disable         attr val|devno|dev  Disable device
        enable          attr val|devno|dev  Enable device
        find            devno|dev           Find device
        list                                List configuration
        lines           count               # of lines per page
        show            [attr [val]]        Show attribute
        exit                                Exit, without saving changes
        quit                                Quit, saving current changes
        timezone        [mins [dst]]        Show/change timezone
        bufcachepercent [number]            Show/change BUFCACHEPERCENT
        nkmempg         [number]            Show/change NKMEMPAGES
ukc> list
  0 video* at uvideo* flags 0x0
  1 audio* at uaudio*|sb0|sb*|gus0|pas0|ess*|wss0|wss*|ym*|eap*|envy*|eso*|sv*|n
aestro*|esa*|yds*|emu* flags 0x0
  2 midi* at umidi*|sb0|sb*|ym*|mpu*|mpu*|autri*|eap*|envy* flags 0x0
  3 drm* at inteldrm*|radeondrm* flags 0x0
  4 inteldrm* at vga0|vga* flags 0x0
  5 radeondrm* at vga0|vga* flags 0x0
  6 radio* at udsbr*|bktr0|fms* flags 0x0
  7 vscsi0 at root flags 0x0
  8 softraid0 at root flags 0x0
  9 nsphy* at url*|udav*|mos*|axe*|aue*|xe*|ef*|hme*|lii*|bce*|ale*|alc*|age*|jm
l*|mtd*|fxp*|fxp*|xl*|xl*|ep0|ep*|ep*|ep*|ep*|ep* phy -1 flags 0x0
 10 nsphyter* at url*|udav*|mos*|axe*|aue*|xe*|ef*|hme*|lii*|bce*|ale*|alc*|age*
*|rl*|mtd*|fxp*|fxp*|xl*|xl*|ep0|ep*|ep*|ep*|ep*|ep* phy -1 flags 0x0
ukc> disable ep
 98 ep* disabled
 99 ep* disabled
301 ep0 disabled
302 ep* disabled
303 ep* disabled
360 ep* disabled
ukc> quit
not forced
In the above example, all ep devices are disabled in the kernel and will not be probed. In some situations where you have used the UKC during boot, via boot -c, you will need these changes to be written out permanently. To do this you need to use the -u option. In the following example, the computer was booted into the UKC and the wi(4) device was disabled. Since changes made with boot -c are NOT permanent, these changes must be written out. This example writes the changes made from boot -c into a new kernel binary:
# config -e -u -o /bsd
Processing history...
167 wi* disabled
168 wi* disabled
443 wi* disabled
Enter 'help' for information
ukc> quit

Getting more verbose output during boot

Getting more verbose output can be very helpful when trying to debug problems when booting. If you have a problem wherein your boot media won't boot and need to get more information, simply reboot. When you get to the "boot>" prompt, boot with boot -c. This will bring you into the UKC>, then do:
UKC> verbose
autoconf verbose enabled
UKC> quit
Now you will be given extremely verbose output upon boot.

More on OpenBSD's flavors

It is worth pointing out that the name -stable is not intended to imply that -current is unreliable or less robust in production. Rather, the APIs (how the programs talk to the OS) and features of -current are changing and evolving, whereas the operation and APIs of -stable are the same as the release it is based on. This means you shouldn't have to relearn features of your system, change any configuration files, or have any problem adding additional applications to your system.

In fact, as our hope is to continually improve OpenBSD, the goal is that -current should be more reliable, more secure and, of course, have greater features than -stable. Put bluntly, the "best" version of OpenBSD is -current.

Most users should be running either -stable or -release. That being said, many people do run -current on production systems, and it is important that people do so to identify bugs and test new features. However, if you don't know how to properly describe, diagnose and deal with a problem, don't tell yourself (or anyone else) that you're "helping the project" by running -current. "It didn't work!" is not a useful bug report. "The recent changes to the pciide driver broke compatibility with my Slugchip-based IDE interface, dmesg of working and broken systems follow..." might be a useful report.

There are times when "normal" users may wish to live on the cutting edge and run -current. The most common reason is that the user has a device which is not supported by -release (and thus, not -stable), or wishes to use a new feature of -current. In this case, the choice may be either -current or not using the device, and -current may be the better option. However, one should not expect hand-holding from the developers.

What do "upgrading" and "updating" mean?

You will often see references to upgrading and updating OpenBSD installs. Even though these words have similar meanings, they are used slightly differently in OpenBSD.


This is the process of installing a newer version of OpenBSD, with new functionality. For example, going from one release to another, or going from the June 12th snapshot to the June 20th snapshot. When upgrading, you will typically have to consult either following -current or the upgrade guide (when changing releases) to make the changes required to run the upgraded version of OpenBSD.


The process of applying patches to a system to improve the operation without changing the basic functionality or binary compatibility. This is typically done by following the source patching process or by following the stable process. When you update your system, it goes from a -release to -stable (or patched -release) of the same release version. You may then later update it to a newer -stable of the same release version. The update process is typically very painless, as no /etc files or other system configurations need to be changed.

So, you may install a -release system from CD, then update it to -stable a few times, then upgrade it to the next release from CD, and update that a few times before upgrading it again to the following release.

Keeping things in sync

It is important to understand that OpenBSD is an operating system intended to be taken as a whole, not a kernel with a bunch of utilities stuck on.

You must make sure your kernel, userland (the supporting utilities and files) and ports tree are all in sync, or unpleasant things will happen.

One should also understand that the upgrade process is supported in only one direction: from older to newer, and from -stable to -current. You can not run -current (or a snapshot), then decide you are living too dangerously, and step back to -stable. You are on your own if you choose any path other than the supported option of reloading your system from scratch.

CVS tips