Cover V10, I01


Installing OpenBSD on Small Disks

Mike Murray

As sys admins, we can automate a large number of tasks, including installation. With Solaris, we use Jumpstart servers; with Red Hat, we use their Kickstart feature. However, OpenBSD does not provide an easy way to automate installation. Its installer is a very simple one -- a few choices of generic packages are offered, and everything else is done by hand. Recently, for a client, however, I needed to perform a special type of installation on OpenBSD. The client had just acquired new hardware that came with flash disks (instead of the traditional hard drive), and they wanted to perform an installation of OpenBSD that would allow them to run their nameserver on those disks. However, the flash disks were only 128 MB in size. Since the most basic possible installation of OpenBSD requires approximately 69 MB (without a current version of BIND or the compiler packages), I knew this was not going to be an easy task. However, we believed that the performance of the disks would be desirable (not to mention the possible security benefits of removing all the excess binaries from a system to lock it down). After I completed this task, I created a script from my documentation, so that if I had ever had to do it again, it would be easier. In this article, I will explain the process that I used and the script I created.

There are three tasks involved in building this type of nameserver:

  • Cut the system down to the appropriate size.
  • Build the nameserver daemon.
  • Configure the system and the nameserver.

As such, the script follows this basic path. First, it cuts itself into multiple temporary files, then it removes all unnecessary files, and, finally, builds and configures BIND. Although it may seem odd to permanently remove the binaries first, this script is designed to build the BIND (or DNS) server in under 128 MB of disk space. Thus, because of the size of the compiler and ports packages (which will be added to the system temporarily during the execution of the script), the unessential system binaries are removed very near the beginning of the script. (Listings for this article can be downloaded from the Sys Admin Web site:

OpenBSD, like most modern operating systems, comes with a large number of binaries and a large list of services enabled by default. While OpenBSD is an extremely secure and efficient OS, these things are not at all necessary for single task machines (like a nameserver). Unfortunately, this install process has no option to select or deselect individual packages (at least as far as I have been able to find). So, when I attempted to reduce the footprint, I had to examine almost all files placed on the system by default to determine whether they could be removed without affecting functionality. For this reason, the script includes the full pathnames of the files that are to be removed from the system. Some of you may not like my choice of files to be removed; for this reason, the script has a command-line flag that allows you to choose a file containing your own list.

ex to the Rescue

This inclusion of the list of binaries in the file brought its own set of problems of course. First among these problems was the need to find an easy way for the script to read the list (without the obvious method of placing the list in the middle of the script as a variable). Doing it by hand, I would likely open the file in vi, cut out all the extraneous lines, and pass the contents of the leftover file into whatever I wanted to use. At that point, I opened up the man page for vi, and remembered the ex command set. For those of you that don't have much experience with, or knowledge of ex, it is the line-based editor upon which vi is built. Although most sys admins are familiar with sed and awk for text parsing based on regular expressions, not as many are familiar with ex. However, ex is a useful tool that fits the way sys admins often deal with text: line-by-line, regardless of the content of the lines. So, in this case, I used the following syntax:

cp $MYDIR/$MYNAME /tmp/dep.files
echo ":wq" | ex -c "1,287 d" /tmp/dep.files
These two commands allowed me to perform (automatically) the exact set of tasks that I would have performed by hand; that is, they create a copy of the script file in the /tmp directory. Then, ex runs the command to delete the first 287 lines out of the file, and waits for the user to issue the next command. I pass that command (the vi command to save and quit, :wq) to ex through the pipe.

Patching the Files

The last step was to make sure that I had a working (if unconfigured) nameserver running upon reboot. This step required moving all of the named configuration files into the appropriate directory, as well as editing the system's startup scripts. There are sample versions of the files that must be set up in the installation of BIND. To run the named daemon, these must be moved into the /var/named directory, and a few edits made to the named.conf file to inform BIND of the location of those files. These files hold the information about the machines and networks that the nameserver will distribute. Also, I edited the startup script /etc/rc.conf to disable services like portmap and NFS (that OpenBSD starts by default), and replaced the script /etc/rc to remove references to binaries that had already been removed from the system.

This step required that I copy the sample named configuration files into /var/named, then rewrite two files in the system: the named.conf file and /etc/rc.conf, which controls services started in OpenBSD. Again, I would simply open the files in vi and edit them by hand. However, in attempting to automate the process, I needed a way to replace selected lines in these files easily and quickly (and without completely rewriting the file). Here, the patch utility was my choice; it was simple to take the files that I had changed by hand, and take a diff of those files with the originals. Those diffs are also included in the script. I cut them out of the script using ex in the same way as above. These files are then used as input to patch the copies that are on the local system, exactly as you would patch any other text file:

patch -p0 /etc/rc.conf < /tmp/patch.rc
The purpose of this script is not so that the client can do it again; they could use dd for that. The real purpose here is to create a script that allows me to do it again, for a different client, without performing all the tasks by hand (because the act of selecting the files to be removed was a very long job). This type of script will save me a great deal of time next time I need to do this; I can instead spend that time doing something more useful, and allow the script to do the simple, repetitive tasks for me.

Mike Murray is a consultant for Taos, The Sys Admin Company in San Francisco. He is currently assigned to Hiverworld, Inc. as a member of their security appliance engineering team. Mike has four years of systems administration experience on a variety of platforms (but he's happiest on OpenBSD). He can be contacted at